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