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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF_H
10#define LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF_H
11
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 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 NaN
35 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| = 0
44 if (x_abs == 0) {
45 fputil::raise_except_if_required(FE_DIVBYZERO);
46 fputil::set_errno_if_required(ERANGE);
47 return FPBits::inf(sign: xbits.sign()).get_val();
48 }
49
50 // -inf <= x < 0
51 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) = 0
58 return FPBits::zero(sign: xbits.sign()).get_val();
59 }
60
61 // TODO: add float based approximation when
62 // LIBC_TARGET_CPU_HAS_FPU_DOUBLE is not defined
63 double result = 1.0 / fputil::sqrt<double>(x: fputil::cast<double>(x));
64
65 return fputil::cast<float>(x: result);
66}
67
68} // namespace math
69} // namespace LIBC_NAMESPACE_DECL
70
71#endif // LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF_H
72