//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file reimplements builtins that are normally provided by compiler-rt, which is // not provided on Windows. This should go away once compiler-rt is shipped on Windows. // #include #include template static std::__complex_t mul_impl(T a, T b, T c, T d) { T __ac = a * c; T __bd = b * d; T __ad = a * d; T __bc = b * c; T __x = __ac - __bd; T __y = __ad + __bc; if (std::isnan(__x) && std::isnan(__y)) { bool recalc = false; if (std::isinf(a) || std::isinf(b)) { a = std::copysign(std::isinf(a) ? T(1) : T(0), a); b = std::copysign(std::isinf(b) ? T(1) : T(0), b); if (std::isnan(c)) c = std::copysign(T(0), c); if (std::isnan(d)) d = std::copysign(T(0), d); recalc = true; } if (std::isinf(c) || std::isinf(d)) { c = std::copysign(std::isinf(c) ? T(1) : T(0), c); d = std::copysign(std::isinf(d) ? T(1) : T(0), d); if (std::isnan(a)) a = std::copysign(T(0), a); if (std::isnan(b)) b = std::copysign(T(0), b); recalc = true; } if (!recalc && (std::isinf(__ac) || std::isinf(__bd) || std::isinf(__ad) || std::isinf(__bc))) { if (std::isnan(a)) a = std::copysign(T(0), a); if (std::isnan(b)) b = std::copysign(T(0), b); if (std::isnan(c)) c = std::copysign(T(0), c); if (std::isnan(d)) d = std::copysign(T(0), d); recalc = true; } if (recalc) { __x = T(INFINITY) * (a * c - b * d); __y = T(INFINITY) * (a * d + b * c); } } return {__x, __y}; } extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex double __muldc3(double a, double b, double c, double d) { return mul_impl(a, b, c, d); } extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex float __mulsc3(float a, float b, float c, float d) { return mul_impl(a, b, c, d); } template std::__complex_t div_impl(T a, T b, T c, T d) { int ilogbw = 0; T __logbw = std::logb(std::fmax(std::fabs(c), std::fabs(d))); if (std::isfinite(__logbw)) { ilogbw = static_cast(__logbw); c = std::scalbn(c, -ilogbw); d = std::scalbn(d, -ilogbw); } T denom = c * c + d * d; T x = std::scalbn((a * c + b * d) / denom, -ilogbw); T y = std::scalbn((b * c - a * d) / denom, -ilogbw); if (std::isnan(x) && std::isnan(y)) { if ((denom == T(0)) && (!std::isnan(a) || !std::isnan(b))) { x = std::copysign(T(INFINITY), c) * a; y = std::copysign(T(INFINITY), c) * b; } else if ((std::isinf(a) || std::isinf(b)) && std::isfinite(c) && std::isfinite(d)) { a = std::copysign(std::isinf(a) ? T(1) : T(0), a); b = std::copysign(std::isinf(b) ? T(1) : T(0), b); x = T(INFINITY) * (a * c + b * d); y = T(INFINITY) * (b * c - a * d); } else if (std::isinf(__logbw) && __logbw > T(0) && std::isfinite(a) && std::isfinite(b)) { c = std::copysign(std::isinf(c) ? T(1) : T(0), c); d = std::copysign(std::isinf(d) ? T(1) : T(0), d); x = T(0) * (a * c + b * d); y = T(0) * (b * c - a * d); } } return {x, y}; } extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex double __divdc3(double a, double b, double c, double d) { return div_impl(a, b, c, d); } extern "C" _LIBCPP_EXPORTED_FROM_ABI _Complex float __divsc3(float a, float b, float c, float d) { return div_impl(a, b, c, d); }