FLANG

real.h
1 //===-- include/flang/Common/real.h -----------------------------*- 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 FORTRAN_COMMON_REAL_H_
10 #define FORTRAN_COMMON_REAL_H_
11
12 // Characteristics of IEEE-754 & related binary floating-point numbers.
13 // The various representations are distinguished by their binary precisions
14 // (number of explicit significand bits and any implicit MSB in the fraction).
15
16 #include <cinttypes>
17
18 namespace Fortran::common {
19
20 // Total representation size in bits for each type
21 static constexpr int BitsForBinaryPrecision(int binaryPrecision) {
22 switch (binaryPrecision) {
23 case 8:
24 return 16; // IEEE single (truncated): 1+8+7
25 case 11:
26 return 16; // IEEE half precision: 1+5+10
27 case 24:
28 return 32; // IEEE single precision: 1+8+23
29 case 53:
30 return 64; // IEEE double precision: 1+11+52
31 case 64:
32 return 80; // x87 extended precision: 1+15+64
33 case 106:
34 return 128; // "double-double": 2*(1+11+52)
35 case 113:
36 return 128; // IEEE quad precision: 1+15+112
37 default:
38 return -1;
39 }
40 }
41
42 // Number of significant decimal digits in the fraction of the
43 // exact conversion of the least nonzero (subnormal) value
44 // in each type; i.e., a 128-bit quad value can be formatted
45 // exactly with FORMAT(E0.22981).
46 static constexpr int MaxDecimalConversionDigits(int binaryPrecision) {
47 switch (binaryPrecision) {
48 case 8:
49 return 93;
50 case 11:
51 return 17;
52 case 24:
53 return 105;
54 case 53:
55 return 751;
56 case 64:
57 return 11495;
58 case 106:
59 return 2 * 751;
60 case 113:
61 return 11530;
62 default:
63 return -1;
64 }
65 }
66
67 template <int BINARY_PRECISION> class RealDetails {
68 private:
69 // Converts bit widths to whole decimal digits
70 static constexpr int LogBaseTwoToLogBaseTen(int logb2) {
71 constexpr std::int64_t LogBaseTenOfTwoTimesTenToThe12th{301029995664};
72 constexpr std::int64_t TenToThe12th{1000000000000};
73 std::int64_t logb10{
74 (logb2 * LogBaseTenOfTwoTimesTenToThe12th) / TenToThe12th};
75 return static_cast<int>(logb10);
76 }
77
78 public:
79 static constexpr int binaryPrecision{BINARY_PRECISION};
80 static constexpr int bits{BitsForBinaryPrecision(binaryPrecision)};
81 static constexpr bool isImplicitMSB{binaryPrecision != 64 /*x87*/};
82 static constexpr int significandBits{binaryPrecision - isImplicitMSB};
83 static constexpr int exponentBits{bits - significandBits - 1 /*sign*/};
84 static constexpr int maxExponent{(1 << exponentBits) - 1};
85 static constexpr int exponentBias{maxExponent / 2};
86
87 static constexpr int decimalPrecision{
88 LogBaseTwoToLogBaseTen(binaryPrecision - 1)};
89 static constexpr int decimalRange{LogBaseTwoToLogBaseTen(exponentBias - 1)};
90
91 // Number of significant decimal digits in the fraction of the
92 // exact conversion of the least nonzero subnormal.
93 static constexpr int maxDecimalConversionDigits{
94 MaxDecimalConversionDigits(binaryPrecision)};
95
96 static_assert(binaryPrecision > 0);
97 static_assert(exponentBits > 1);
98 static_assert(exponentBits <= 15);
99 };
100
101 } // namespace Fortran::common
102 #endif // FORTRAN_COMMON_REAL_H_
Fortran::common::RealDetails
Definition: real.h:67