V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
double.h
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_DOUBLE_H_
6 #define V8_DOUBLE_H_
7 
8 #include "src/base/macros.h"
9 #include "src/diy-fp.h"
10 
11 namespace v8 {
12 namespace internal {
13 
14 // We assume that doubles and uint64_t have the same endianness.
15 inline uint64_t double_to_uint64(double d) { return bit_cast<uint64_t>(d); }
16 inline double uint64_to_double(uint64_t d64) { return bit_cast<double>(d64); }
17 
18 // Helper functions for doubles.
19 class Double {
20  public:
21  static constexpr uint64_t kSignMask = V8_2PART_UINT64_C(0x80000000, 00000000);
22  static constexpr uint64_t kExponentMask =
23  V8_2PART_UINT64_C(0x7FF00000, 00000000);
24  static constexpr uint64_t kSignificandMask =
25  V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF);
26  static constexpr uint64_t kHiddenBit =
27  V8_2PART_UINT64_C(0x00100000, 00000000);
28  static constexpr int kPhysicalSignificandSize =
29  52; // Excludes the hidden bit.
30  static constexpr int kSignificandSize = 53;
31 
32  Double() : d64_(0) {}
33  explicit Double(double d) : d64_(double_to_uint64(d)) {}
34  explicit Double(uint64_t d64) : d64_(d64) {}
35  explicit Double(DiyFp diy_fp)
36  : d64_(DiyFpToUint64(diy_fp)) {}
37 
38  // The value encoded by this Double must be greater or equal to +0.0.
39  // It must not be special (infinity, or NaN).
40  DiyFp AsDiyFp() const {
41  DCHECK_GT(Sign(), 0);
42  DCHECK(!IsSpecial());
43  return DiyFp(Significand(), Exponent());
44  }
45 
46  // The value encoded by this Double must be strictly greater than 0.
47  DiyFp AsNormalizedDiyFp() const {
48  DCHECK_GT(value(), 0.0);
49  uint64_t f = Significand();
50  int e = Exponent();
51 
52  // The current double could be a denormal.
53  while ((f & kHiddenBit) == 0) {
54  f <<= 1;
55  e--;
56  }
57  // Do the final shifts in one go.
58  f <<= DiyFp::kSignificandSize - kSignificandSize;
59  e -= DiyFp::kSignificandSize - kSignificandSize;
60  return DiyFp(f, e);
61  }
62 
63  // Returns the double's bit as uint64.
64  uint64_t AsUint64() const {
65  return d64_;
66  }
67 
68  // Returns the next greater double. Returns +infinity on input +infinity.
69  double NextDouble() const {
70  if (d64_ == kInfinity) return Double(kInfinity).value();
71  if (Sign() < 0 && Significand() == 0) {
72  // -0.0
73  return 0.0;
74  }
75  if (Sign() < 0) {
76  return Double(d64_ - 1).value();
77  } else {
78  return Double(d64_ + 1).value();
79  }
80  }
81 
82  int Exponent() const {
83  if (IsDenormal()) return kDenormalExponent;
84 
85  uint64_t d64 = AsUint64();
86  int biased_e =
87  static_cast<int>((d64 & kExponentMask) >> kPhysicalSignificandSize);
88  return biased_e - kExponentBias;
89  }
90 
91  uint64_t Significand() const {
92  uint64_t d64 = AsUint64();
93  uint64_t significand = d64 & kSignificandMask;
94  if (!IsDenormal()) {
95  return significand + kHiddenBit;
96  } else {
97  return significand;
98  }
99  }
100 
101  // Returns true if the double is a denormal.
102  bool IsDenormal() const {
103  uint64_t d64 = AsUint64();
104  return (d64 & kExponentMask) == 0;
105  }
106 
107  // We consider denormals not to be special.
108  // Hence only Infinity and NaN are special.
109  bool IsSpecial() const {
110  uint64_t d64 = AsUint64();
111  return (d64 & kExponentMask) == kExponentMask;
112  }
113 
114  bool IsInfinite() const {
115  uint64_t d64 = AsUint64();
116  return ((d64 & kExponentMask) == kExponentMask) &&
117  ((d64 & kSignificandMask) == 0);
118  }
119 
120  int Sign() const {
121  uint64_t d64 = AsUint64();
122  return (d64 & kSignMask) == 0? 1: -1;
123  }
124 
125  // Precondition: the value encoded by this Double must be greater or equal
126  // than +0.0.
127  DiyFp UpperBoundary() const {
128  DCHECK_GT(Sign(), 0);
129  return DiyFp(Significand() * 2 + 1, Exponent() - 1);
130  }
131 
132  // Returns the two boundaries of this.
133  // The bigger boundary (m_plus) is normalized. The lower boundary has the same
134  // exponent as m_plus.
135  // Precondition: the value encoded by this Double must be greater than 0.
136  void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
137  DCHECK_GT(value(), 0.0);
138  DiyFp v = this->AsDiyFp();
139  bool significand_is_zero = (v.f() == kHiddenBit);
140  DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
141  DiyFp m_minus;
142  if (significand_is_zero && v.e() != kDenormalExponent) {
143  // The boundary is closer. Think of v = 1000e10 and v- = 9999e9.
144  // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
145  // at a distance of 1e8.
146  // The only exception is for the smallest normal: the largest denormal is
147  // at the same distance as its successor.
148  // Note: denormals have the same exponent as the smallest normals.
149  m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
150  } else {
151  m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
152  }
153  m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
154  m_minus.set_e(m_plus.e());
155  *out_m_plus = m_plus;
156  *out_m_minus = m_minus;
157  }
158 
159  double value() const { return uint64_to_double(d64_); }
160 
161  // Returns the significand size for a given order of magnitude.
162  // If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude.
163  // This function returns the number of significant binary digits v will have
164  // once its encoded into a double. In almost all cases this is equal to
165  // kSignificandSize. The only exception are denormals. They start with leading
166  // zeroes and their effective significand-size is hence smaller.
167  static int SignificandSizeForOrderOfMagnitude(int order) {
168  if (order >= (kDenormalExponent + kSignificandSize)) {
169  return kSignificandSize;
170  }
171  if (order <= kDenormalExponent) return 0;
172  return order - kDenormalExponent;
173  }
174 
175  private:
176  static constexpr int kExponentBias = 0x3FF + kPhysicalSignificandSize;
177  static constexpr int kDenormalExponent = -kExponentBias + 1;
178  static constexpr int kMaxExponent = 0x7FF - kExponentBias;
179  static constexpr uint64_t kInfinity = V8_2PART_UINT64_C(0x7FF00000, 00000000);
180 
181  // The field d64_ is not marked as const to permit the usage of the copy
182  // constructor.
183  uint64_t d64_;
184 
185  static uint64_t DiyFpToUint64(DiyFp diy_fp) {
186  uint64_t significand = diy_fp.f();
187  int exponent = diy_fp.e();
188  while (significand > kHiddenBit + kSignificandMask) {
189  significand >>= 1;
190  exponent++;
191  }
192  if (exponent >= kMaxExponent) {
193  return kInfinity;
194  }
195  if (exponent < kDenormalExponent) {
196  return 0;
197  }
198  while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) {
199  significand <<= 1;
200  exponent--;
201  }
202  uint64_t biased_exponent;
203  if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) {
204  biased_exponent = 0;
205  } else {
206  biased_exponent = static_cast<uint64_t>(exponent + kExponentBias);
207  }
208  return (significand & kSignificandMask) |
209  (biased_exponent << kPhysicalSignificandSize);
210  }
211 };
212 
213 } // namespace internal
214 } // namespace v8
215 
216 #endif // V8_DOUBLE_H_
Definition: libplatform.h:13