111 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9//10// This file reimplements builtins that are normally provided by compiler-rt, which is11// not provided on Windows. This should go away once compiler-rt is shipped on Windows.12//13 14#include <cmath>15#include <complex>16 17template <class T>18static std::__complex_t<T> mul_impl(T a, T b, T c, T d) {19 T __ac = a * c;20 T __bd = b * d;21 T __ad = a * d;22 T __bc = b * c;23 T __x = __ac - __bd;24 T __y = __ad + __bc;25 if (std::isnan(__x) && std::isnan(__y)) {26 bool recalc = false;27 if (std::isinf(a) || std::isinf(b)) {28 a = std::copysign(std::isinf(a) ? T(1) : T(0), a);29 b = std::copysign(std::isinf(b) ? T(1) : T(0), b);30 if (std::isnan(c))31 c = std::copysign(T(0), c);32 if (std::isnan(d))33 d = std::copysign(T(0), d);34 recalc = true;35 }36 if (std::isinf(c) || std::isinf(d)) {37 c = std::copysign(std::isinf(c) ? T(1) : T(0), c);38 d = std::copysign(std::isinf(d) ? T(1) : T(0), d);39 if (std::isnan(a))40 a = std::copysign(T(0), a);41 if (std::isnan(b))42 b = std::copysign(T(0), b);43 recalc = true;44 }45 if (!recalc && (std::isinf(__ac) || std::isinf(__bd) || std::isinf(__ad) || std::isinf(__bc))) {46 if (std::isnan(a))47 a = std::copysign(T(0), a);48 if (std::isnan(b))49 b = std::copysign(T(0), b);50 if (std::isnan(c))51 c = std::copysign(T(0), c);52 if (std::isnan(d))53 d = std::copysign(T(0), d);54 recalc = true;55 }56 if (recalc) {57 __x = T(INFINITY) * (a * c - b * d);58 __y = T(INFINITY) * (a * d + b * c);59 }60 }61 return {__x, __y};62}63 64extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex double __muldc3(double a, double b, double c, double d) {65 return mul_impl(a, b, c, d);66}67 68extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex float __mulsc3(float a, float b, float c, float d) {69 return mul_impl(a, b, c, d);70}71 72template <class T>73std::__complex_t<T> div_impl(T a, T b, T c, T d) {74 int ilogbw = 0;75 T __logbw = std::logb(std::fmax(std::fabs(c), std::fabs(d)));76 if (std::isfinite(__logbw)) {77 ilogbw = static_cast<int>(__logbw);78 c = std::scalbn(c, -ilogbw);79 d = std::scalbn(d, -ilogbw);80 }81 82 T denom = c * c + d * d;83 T x = std::scalbn((a * c + b * d) / denom, -ilogbw);84 T y = std::scalbn((b * c - a * d) / denom, -ilogbw);85 if (std::isnan(x) && std::isnan(y)) {86 if ((denom == T(0)) && (!std::isnan(a) || !std::isnan(b))) {87 x = std::copysign(T(INFINITY), c) * a;88 y = std::copysign(T(INFINITY), c) * b;89 } else if ((std::isinf(a) || std::isinf(b)) && std::isfinite(c) && std::isfinite(d)) {90 a = std::copysign(std::isinf(a) ? T(1) : T(0), a);91 b = std::copysign(std::isinf(b) ? T(1) : T(0), b);92 x = T(INFINITY) * (a * c + b * d);93 y = T(INFINITY) * (b * c - a * d);94 } else if (std::isinf(__logbw) && __logbw > T(0) && std::isfinite(a) && std::isfinite(b)) {95 c = std::copysign(std::isinf(c) ? T(1) : T(0), c);96 d = std::copysign(std::isinf(d) ? T(1) : T(0), d);97 x = T(0) * (a * c + b * d);98 y = T(0) * (b * c - a * d);99 }100 }101 return {x, y};102}103 104extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex double __divdc3(double a, double b, double c, double d) {105 return div_impl(a, b, c, d);106}107 108extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex float __divsc3(float a, float b, float c, float d) {109 return div_impl(a, b, c, d);110}111