brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.7 KiB · ab26322 Raw
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