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-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 //
10 // This file reimplements builtins that are normally provided by compiler-rt, which is
11 // not provided on Windows. This should go away once compiler-rt is shipped on Windows.
12 //
13
14 #include <cmath>
15 #include <complex>
16
17 template <class T>
mul_impl(T a,T b,T c,T d)18 static 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
__muldc3(double a,double b,double c,double d)64 extern "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
__mulsc3(float a,float b,float c,float d)68 extern "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
72 template <class T>
div_impl(T a,T b,T c,T d)73 std::__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
__divdc3(double a,double b,double c,double d)104 extern "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
__divsc3(float a,float b,float c,float d)108 extern "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