xref: /llvm-project/libcxx/src/support/win32/compiler_rt_shims.cpp (revision 5aacf93a8968b1ae83382ed0ce6de8279b0cd753)
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