1// Copyright 2006-2008 the V8 project authors. All rights reserved.
2
3#include <stdlib.h>
4
5#include "v8.h"
6
7#include "platform.h"
8#include "cctest.h"
9#include "diy-fp.h"
10#include "double.h"
11
12
13using namespace v8::internal;
14
15
16TEST(Uint64Conversions) {
17  // Start by checking the byte-order.
18  uint64_t ordered = V8_2PART_UINT64_C(0x01234567, 89ABCDEF);
19  CHECK_EQ(3512700564088504e-318, Double(ordered).value());
20
21  uint64_t min_double64 = V8_2PART_UINT64_C(0x00000000, 00000001);
22  CHECK_EQ(5e-324, Double(min_double64).value());
23
24  uint64_t max_double64 = V8_2PART_UINT64_C(0x7fefffff, ffffffff);
25  CHECK_EQ(1.7976931348623157e308, Double(max_double64).value());
26}
27
28TEST(AsDiyFp) {
29  uint64_t ordered = V8_2PART_UINT64_C(0x01234567, 89ABCDEF);
30  DiyFp diy_fp = Double(ordered).AsDiyFp();
31  CHECK_EQ(0x12 - 0x3FF - 52, diy_fp.e());
32  // The 52 mantissa bits, plus the implicit 1 in bit 52 as a UINT64.
33  CHECK(V8_2PART_UINT64_C(0x00134567, 89ABCDEF) == diy_fp.f());  // NOLINT
34
35  uint64_t min_double64 = V8_2PART_UINT64_C(0x00000000, 00000001);
36  diy_fp = Double(min_double64).AsDiyFp();
37  CHECK_EQ(-0x3FF - 52 + 1, diy_fp.e());
38  // This is a denormal; so no hidden bit.
39  CHECK(1 == diy_fp.f());  // NOLINT
40
41  uint64_t max_double64 = V8_2PART_UINT64_C(0x7fefffff, ffffffff);
42  diy_fp = Double(max_double64).AsDiyFp();
43  CHECK_EQ(0x7FE - 0x3FF - 52, diy_fp.e());
44  CHECK(V8_2PART_UINT64_C(0x001fffff, ffffffff) == diy_fp.f());  // NOLINT
45}
46
47
48TEST(AsNormalizedDiyFp) {
49  uint64_t ordered = V8_2PART_UINT64_C(0x01234567, 89ABCDEF);
50  DiyFp diy_fp = Double(ordered).AsNormalizedDiyFp();
51  CHECK_EQ(0x12 - 0x3FF - 52 - 11, diy_fp.e());
52  CHECK((V8_2PART_UINT64_C(0x00134567, 89ABCDEF) << 11) ==
53        diy_fp.f());  // NOLINT
54
55  uint64_t min_double64 = V8_2PART_UINT64_C(0x00000000, 00000001);
56  diy_fp = Double(min_double64).AsNormalizedDiyFp();
57  CHECK_EQ(-0x3FF - 52 + 1 - 63, diy_fp.e());
58  // This is a denormal; so no hidden bit.
59  CHECK(V8_2PART_UINT64_C(0x80000000, 00000000) == diy_fp.f());  // NOLINT
60
61  uint64_t max_double64 = V8_2PART_UINT64_C(0x7fefffff, ffffffff);
62  diy_fp = Double(max_double64).AsNormalizedDiyFp();
63  CHECK_EQ(0x7FE - 0x3FF - 52 - 11, diy_fp.e());
64  CHECK((V8_2PART_UINT64_C(0x001fffff, ffffffff) << 11) ==
65        diy_fp.f());  // NOLINT
66}
67
68
69TEST(IsDenormal) {
70  uint64_t min_double64 = V8_2PART_UINT64_C(0x00000000, 00000001);
71  CHECK(Double(min_double64).IsDenormal());
72  uint64_t bits = V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF);
73  CHECK(Double(bits).IsDenormal());
74  bits = V8_2PART_UINT64_C(0x00100000, 00000000);
75  CHECK(!Double(bits).IsDenormal());
76}
77
78
79TEST(IsSpecial) {
80  CHECK(Double(V8_INFINITY).IsSpecial());
81  CHECK(Double(-V8_INFINITY).IsSpecial());
82  CHECK(Double(OS::nan_value()).IsSpecial());
83  uint64_t bits = V8_2PART_UINT64_C(0xFFF12345, 00000000);
84  CHECK(Double(bits).IsSpecial());
85  // Denormals are not special:
86  CHECK(!Double(5e-324).IsSpecial());
87  CHECK(!Double(-5e-324).IsSpecial());
88  // And some random numbers:
89  CHECK(!Double(0.0).IsSpecial());
90  CHECK(!Double(-0.0).IsSpecial());
91  CHECK(!Double(1.0).IsSpecial());
92  CHECK(!Double(-1.0).IsSpecial());
93  CHECK(!Double(1000000.0).IsSpecial());
94  CHECK(!Double(-1000000.0).IsSpecial());
95  CHECK(!Double(1e23).IsSpecial());
96  CHECK(!Double(-1e23).IsSpecial());
97  CHECK(!Double(1.7976931348623157e308).IsSpecial());
98  CHECK(!Double(-1.7976931348623157e308).IsSpecial());
99}
100
101
102TEST(IsInfinite) {
103  CHECK(Double(V8_INFINITY).IsInfinite());
104  CHECK(Double(-V8_INFINITY).IsInfinite());
105  CHECK(!Double(OS::nan_value()).IsInfinite());
106  CHECK(!Double(0.0).IsInfinite());
107  CHECK(!Double(-0.0).IsInfinite());
108  CHECK(!Double(1.0).IsInfinite());
109  CHECK(!Double(-1.0).IsInfinite());
110  uint64_t min_double64 = V8_2PART_UINT64_C(0x00000000, 00000001);
111  CHECK(!Double(min_double64).IsInfinite());
112}
113
114
115TEST(IsNan) {
116  CHECK(Double(OS::nan_value()).IsNan());
117  uint64_t other_nan = V8_2PART_UINT64_C(0xFFFFFFFF, 00000001);
118  CHECK(Double(other_nan).IsNan());
119  CHECK(!Double(V8_INFINITY).IsNan());
120  CHECK(!Double(-V8_INFINITY).IsNan());
121  CHECK(!Double(0.0).IsNan());
122  CHECK(!Double(-0.0).IsNan());
123  CHECK(!Double(1.0).IsNan());
124  CHECK(!Double(-1.0).IsNan());
125  uint64_t min_double64 = V8_2PART_UINT64_C(0x00000000, 00000001);
126  CHECK(!Double(min_double64).IsNan());
127}
128
129
130TEST(Sign) {
131  CHECK_EQ(1, Double(1.0).Sign());
132  CHECK_EQ(1, Double(V8_INFINITY).Sign());
133  CHECK_EQ(-1, Double(-V8_INFINITY).Sign());
134  CHECK_EQ(1, Double(0.0).Sign());
135  CHECK_EQ(-1, Double(-0.0).Sign());
136  uint64_t min_double64 = V8_2PART_UINT64_C(0x00000000, 00000001);
137  CHECK_EQ(1, Double(min_double64).Sign());
138}
139
140
141TEST(NormalizedBoundaries) {
142  DiyFp boundary_plus;
143  DiyFp boundary_minus;
144  DiyFp diy_fp = Double(1.5).AsNormalizedDiyFp();
145  Double(1.5).NormalizedBoundaries(&boundary_minus, &boundary_plus);
146  CHECK_EQ(diy_fp.e(), boundary_minus.e());
147  CHECK_EQ(diy_fp.e(), boundary_plus.e());
148  // 1.5 does not have a significand of the form 2^p (for some p).
149  // Therefore its boundaries are at the same distance.
150  CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
151  CHECK((1 << 10) == diy_fp.f() - boundary_minus.f());  // NOLINT
152
153  diy_fp = Double(1.0).AsNormalizedDiyFp();
154  Double(1.0).NormalizedBoundaries(&boundary_minus, &boundary_plus);
155  CHECK_EQ(diy_fp.e(), boundary_minus.e());
156  CHECK_EQ(diy_fp.e(), boundary_plus.e());
157  // 1.0 does have a significand of the form 2^p (for some p).
158  // Therefore its lower boundary is twice as close as the upper boundary.
159  CHECK_GT(boundary_plus.f() - diy_fp.f(), diy_fp.f() - boundary_minus.f());
160  CHECK((1 << 9) == diy_fp.f() - boundary_minus.f());  // NOLINT
161  CHECK((1 << 10) == boundary_plus.f() - diy_fp.f());  // NOLINT
162
163  uint64_t min_double64 = V8_2PART_UINT64_C(0x00000000, 00000001);
164  diy_fp = Double(min_double64).AsNormalizedDiyFp();
165  Double(min_double64).NormalizedBoundaries(&boundary_minus, &boundary_plus);
166  CHECK_EQ(diy_fp.e(), boundary_minus.e());
167  CHECK_EQ(diy_fp.e(), boundary_plus.e());
168  // min-value does not have a significand of the form 2^p (for some p).
169  // Therefore its boundaries are at the same distance.
170  CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
171  // Denormals have their boundaries much closer.
172  CHECK((static_cast<uint64_t>(1) << 62) ==
173        diy_fp.f() - boundary_minus.f());  // NOLINT
174
175  uint64_t smallest_normal64 = V8_2PART_UINT64_C(0x00100000, 00000000);
176  diy_fp = Double(smallest_normal64).AsNormalizedDiyFp();
177  Double(smallest_normal64).NormalizedBoundaries(&boundary_minus,
178                                                 &boundary_plus);
179  CHECK_EQ(diy_fp.e(), boundary_minus.e());
180  CHECK_EQ(diy_fp.e(), boundary_plus.e());
181  // Even though the significand is of the form 2^p (for some p), its boundaries
182  // are at the same distance. (This is the only exception).
183  CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
184  CHECK((1 << 10) == diy_fp.f() - boundary_minus.f());  // NOLINT
185
186  uint64_t largest_denormal64 = V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF);
187  diy_fp = Double(largest_denormal64).AsNormalizedDiyFp();
188  Double(largest_denormal64).NormalizedBoundaries(&boundary_minus,
189                                                  &boundary_plus);
190  CHECK_EQ(diy_fp.e(), boundary_minus.e());
191  CHECK_EQ(diy_fp.e(), boundary_plus.e());
192  CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
193  CHECK((1 << 11) == diy_fp.f() - boundary_minus.f());  // NOLINT
194
195  uint64_t max_double64 = V8_2PART_UINT64_C(0x7fefffff, ffffffff);
196  diy_fp = Double(max_double64).AsNormalizedDiyFp();
197  Double(max_double64).NormalizedBoundaries(&boundary_minus, &boundary_plus);
198  CHECK_EQ(diy_fp.e(), boundary_minus.e());
199  CHECK_EQ(diy_fp.e(), boundary_plus.e());
200  // max-value does not have a significand of the form 2^p (for some p).
201  // Therefore its boundaries are at the same distance.
202  CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
203  CHECK((1 << 10) == diy_fp.f() - boundary_minus.f());  // NOLINT
204}
205
206
207TEST(NextDouble) {
208  CHECK_EQ(4e-324, Double(0.0).NextDouble());
209  CHECK_EQ(0.0, Double(-0.0).NextDouble());
210  CHECK_EQ(-0.0, Double(-4e-324).NextDouble());
211  Double d0(-4e-324);
212  Double d1(d0.NextDouble());
213  Double d2(d1.NextDouble());
214  CHECK_EQ(-0.0, d1.value());
215  CHECK_EQ(0.0, d2.value());
216  CHECK_EQ(4e-324, d2.NextDouble());
217  CHECK_EQ(-1.7976931348623157e308, Double(-V8_INFINITY).NextDouble());
218  CHECK_EQ(V8_INFINITY,
219           Double(V8_2PART_UINT64_C(0x7fefffff, ffffffff)).NextDouble());
220}
221