brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.6 KiB · 30ab58f Raw
87 lines · c
1//===-- Implementation header for rsqrtf16 ----------------------*- 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_RSQRTF16_H10#define LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF16_H11 12#include "include/llvm-libc-macros/float16-macros.h"13 14#ifdef LIBC_TYPES_HAS_FLOAT1615 16#include "src/__support/FPUtil/FEnvImpl.h"17#include "src/__support/FPUtil/FPBits.h"18#include "src/__support/FPUtil/ManipulationFunctions.h"19#include "src/__support/FPUtil/cast.h"20#include "src/__support/FPUtil/multiply_add.h"21#include "src/__support/FPUtil/sqrt.h"22#include "src/__support/macros/optimization.h"23 24namespace LIBC_NAMESPACE_DECL {25namespace math {26 27LIBC_INLINE static constexpr float16 rsqrtf16(float16 x) {28  using FPBits = fputil::FPBits<float16>;29  FPBits xbits(x);30 31  uint16_t x_u = xbits.uintval();32  uint16_t x_abs = x_u & 0x7fff;33 34  constexpr uint16_t INF_BIT = FPBits::inf().uintval();35 36  // x is 0, inf/nan, or negative.37  if (LIBC_UNLIKELY(x_u == 0 || x_u >= INF_BIT)) {38    // x is NaN39    if (x_abs > INF_BIT) {40      if (xbits.is_signaling_nan()) {41        fputil::raise_except_if_required(FE_INVALID);42        return FPBits::quiet_nan().get_val();43      }44      return x;45    }46 47    // |x| = 048    if (x_abs == 0) {49      fputil::raise_except_if_required(FE_DIVBYZERO);50      fputil::set_errno_if_required(ERANGE);51      return FPBits::inf(xbits.sign()).get_val();52    }53 54    // -inf <= x < 055    if (x_u > 0x7fff) {56      fputil::raise_except_if_required(FE_INVALID);57      fputil::set_errno_if_required(EDOM);58      return FPBits::quiet_nan().get_val();59    }60 61    // x = +inf => rsqrt(x) = 062    return FPBits::zero().get_val();63  }64 65  // TODO: add integer based implementation when LIBC_TARGET_CPU_HAS_FPU_FLOAT66  // is not defined67  float result = 1.0f / fputil::sqrt<float>(fputil::cast<float>(x));68 69  // Targeted post-corrections to ensure correct rounding in half for specific70  // mantissa patterns71  const uint16_t half_mantissa = x_abs & 0x3ff;72  if (LIBC_UNLIKELY(half_mantissa == 0x011F)) {73    result = fputil::multiply_add(result, 0x1.0p-21f, result);74  } else if (LIBC_UNLIKELY(half_mantissa == 0x0313)) {75    result = fputil::multiply_add(result, -0x1.0p-21f, result);76  }77 78  return fputil::cast<float16>(result);79}80 81} // namespace math82} // namespace LIBC_NAMESPACE_DECL83 84#endif // LIBC_TYPES_HAS_FLOAT1685 86#endif // LLVM_LIBC_SRC___SUPPORT_MATH_RSQRTF16_H87