1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
//===-- Properties of floating point numbers --------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_UTILS_FPUTIL_FLOAT_PROPERTIES_H
#define LLVM_LIBC_UTILS_FPUTIL_FLOAT_PROPERTIES_H
#include "PlatformDefs.h"
#include <stdint.h>
namespace __llvm_libc {
namespace fputil {
template <typename T> struct FloatProperties {};
template <> struct FloatProperties<float> {
typedef uint32_t BitsType;
static_assert(sizeof(BitsType) == sizeof(float),
"Unexpected size of 'float' type.");
static constexpr uint32_t bitWidth = sizeof(BitsType) << 3;
static constexpr uint32_t mantissaWidth = 23;
static constexpr uint32_t exponentWidth = 8;
static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1;
static constexpr BitsType signMask = BitsType(1)
<< (exponentWidth + mantissaWidth);
static constexpr BitsType exponentMask = ~(signMask | mantissaMask);
static constexpr uint32_t exponentBias = 127;
// If a number x is a NAN, then it is a quiet NAN if:
// QuietNaNMask & bits(x) != 0
// Else, it is a signalling NAN.
static constexpr BitsType quietNaNMask = 0x00400000U;
};
template <> struct FloatProperties<double> {
typedef uint64_t BitsType;
static_assert(sizeof(BitsType) == sizeof(double),
"Unexpected size of 'double' type.");
static constexpr uint32_t bitWidth = sizeof(BitsType) << 3;
static constexpr uint32_t mantissaWidth = 52;
static constexpr uint32_t exponentWidth = 11;
static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1;
static constexpr BitsType signMask = BitsType(1)
<< (exponentWidth + mantissaWidth);
static constexpr BitsType exponentMask = ~(signMask | mantissaMask);
static constexpr uint32_t exponentBias = 1023;
// If a number x is a NAN, then it is a quiet NAN if:
// QuietNaNMask & bits(x) != 0
// Else, it is a signalling NAN.
static constexpr BitsType quietNaNMask = 0x0008000000000000ULL;
};
#if defined(LONG_DOUBLE_IS_DOUBLE)
// Properties for numbers represented in 64 bits long double on Windows
// platform.
template <> struct FloatProperties<long double> {
typedef uint64_t BitsType;
static_assert(sizeof(BitsType) == sizeof(double),
"Unexpected size of 'double' type.");
static constexpr uint32_t bitWidth = FloatProperties<double>::bitWidth;
static constexpr uint32_t mantissaWidth =
FloatProperties<double>::mantissaWidth;
static constexpr uint32_t exponentWidth =
FloatProperties<double>::exponentWidth;
static constexpr BitsType mantissaMask =
FloatProperties<double>::mantissaMask;
static constexpr BitsType signMask = FloatProperties<double>::signMask;
static constexpr BitsType exponentMask =
FloatProperties<double>::exponentMask;
static constexpr uint32_t exponentBias =
FloatProperties<double>::exponentBias;
};
#elif defined(SPECIAL_X86_LONG_DOUBLE)
// Properties for numbers represented in 80 bits long double on non-Windows x86
// platforms.
template <> struct FloatProperties<long double> {
typedef __uint128_t BitsType;
static_assert(sizeof(BitsType) == sizeof(long double),
"Unexpected size of 'long double' type.");
static constexpr uint32_t bitWidth = (sizeof(BitsType) << 3) - 48;
static constexpr uint32_t mantissaWidth = 63;
static constexpr uint32_t exponentWidth = 15;
static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1;
static constexpr BitsType signMask = BitsType(1)
<< (exponentWidth + mantissaWidth + 1);
static constexpr BitsType exponentMask = ((BitsType(1) << exponentWidth) - 1)
<< (mantissaWidth + 1);
static constexpr uint32_t exponentBias = 16383;
};
#else
// Properties for numbers represented in 128 bits long double on non x86
// platform.
template <> struct FloatProperties<long double> {
typedef __uint128_t BitsType;
static_assert(sizeof(BitsType) == sizeof(long double),
"Unexpected size of 'long double' type.");
static constexpr uint32_t bitWidth = sizeof(BitsType) << 3;
static constexpr uint32_t mantissaWidth = 112;
static constexpr uint32_t exponentWidth = 15;
static constexpr BitsType mantissaMask = (BitsType(1) << mantissaWidth) - 1;
static constexpr BitsType signMask = BitsType(1)
<< (exponentWidth + mantissaWidth);
static constexpr BitsType exponentMask = ~(signMask | mantissaMask);
static constexpr uint32_t exponentBias = 16383;
};
#endif
// Define the float type corresponding to the BitsType.
template <typename BitsType> struct FloatType;
template <> struct FloatType<uint32_t> {
static_assert(sizeof(uint32_t) == sizeof(float),
"Unexpected size of 'float' type.");
typedef float Type;
};
template <> struct FloatType<uint64_t> {
static_assert(sizeof(uint64_t) == sizeof(double),
"Unexpected size of 'double' type.");
typedef double Type;
};
template <typename BitsType>
using FloatTypeT = typename FloatType<BitsType>::Type;
} // namespace fputil
} // namespace __llvm_libc
#endif // LLVM_LIBC_UTILS_FPUTIL_FLOAT_PROPERTIES_H
|