brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.1 KiB · 5da1e73 Raw
72 lines · c
1//===-- Implementation header for rsqrtf ------------------------*- C++ -*-===//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#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF_H10#define LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF_H11 12#include "hdr/errno_macros.h"13#include "hdr/fenv_macros.h"14#include "src/__support/FPUtil/FEnvImpl.h"15#include "src/__support/FPUtil/FPBits.h"16#include "src/__support/FPUtil/cast.h"17#include "src/__support/FPUtil/sqrt.h"18#include "src/__support/macros/optimization.h"19 20namespace LIBC_NAMESPACE_DECL {21namespace math {22 23LIBC_INLINE static constexpr float rsqrtf(float x) {24  using FPBits = fputil::FPBits<float>;25  FPBits xbits(x);26 27  uint32_t x_u = xbits.uintval();28  uint32_t x_abs = x_u & 0x7fff'ffffU;29 30  constexpr uint32_t INF_BITS = FPBits::inf().uintval();31 32  // x is 0, inf/nan, or negative.33  if (LIBC_UNLIKELY(x_u == 0 || x_u >= INF_BITS)) {34    // x is NaN35    if (x_abs > INF_BITS) {36      if (xbits.is_signaling_nan()) {37        fputil::raise_except_if_required(FE_INVALID);38        return FPBits::quiet_nan().get_val();39      }40      return x;41    }42 43    // |x| = 044    if (x_abs == 0) {45      fputil::raise_except_if_required(FE_DIVBYZERO);46      fputil::set_errno_if_required(ERANGE);47      return FPBits::inf(xbits.sign()).get_val();48    }49 50    // -inf <= x < 051    if (x_u > 0x7fff'ffffU) {52      fputil::raise_except_if_required(FE_INVALID);53      fputil::set_errno_if_required(EDOM);54      return FPBits::quiet_nan().get_val();55    }56 57    // x = +inf => rsqrt(x) = 058    return FPBits::zero(xbits.sign()).get_val();59  }60 61  // TODO: add float based approximation when62  // LIBC_TARGET_CPU_HAS_FPU_DOUBLE is not defined63  double result = 1.0 / fputil::sqrt<double>(fputil::cast<double>(x));64 65  return fputil::cast<float>(result);66}67 68} // namespace math69} // namespace LIBC_NAMESPACE_DECL70 71#endif // LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF_H72