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#include "fast-dtoa.h"
12#include "gay-precision.h"
13#include "gay-shortest.h"
14
15using namespace v8::internal;
16
17static const int kBufferSize = 100;
18
19
20// Removes trailing '0' digits.
21static void TrimRepresentation(Vector<char> representation) {
22  int len = StrLength(representation.start());
23  int i;
24  for (i = len - 1; i >= 0; --i) {
25    if (representation[i] != '0') break;
26  }
27  representation[i + 1] = '\0';
28}
29
30
31TEST(FastDtoaShortestVariousDoubles) {
32  char buffer_container[kBufferSize];
33  Vector<char> buffer(buffer_container, kBufferSize);
34  int length;
35  int point;
36  int status;
37
38  double min_double = 5e-324;
39  status = FastDtoa(min_double, FAST_DTOA_SHORTEST, 0,
40                    buffer, &length, &point);
41  CHECK(status);
42  CHECK_EQ("5", buffer.start());
43  CHECK_EQ(-323, point);
44
45  double max_double = 1.7976931348623157e308;
46  status = FastDtoa(max_double, FAST_DTOA_SHORTEST, 0,
47                    buffer, &length, &point);
48  CHECK(status);
49  CHECK_EQ("17976931348623157", buffer.start());
50  CHECK_EQ(309, point);
51
52  status = FastDtoa(4294967272.0, FAST_DTOA_SHORTEST, 0,
53                    buffer, &length, &point);
54  CHECK(status);
55  CHECK_EQ("4294967272", buffer.start());
56  CHECK_EQ(10, point);
57
58  status = FastDtoa(4.1855804968213567e298, FAST_DTOA_SHORTEST, 0,
59                    buffer, &length, &point);
60  CHECK(status);
61  CHECK_EQ("4185580496821357", buffer.start());
62  CHECK_EQ(299, point);
63
64  status = FastDtoa(5.5626846462680035e-309, FAST_DTOA_SHORTEST, 0,
65                    buffer, &length, &point);
66  CHECK(status);
67  CHECK_EQ("5562684646268003", buffer.start());
68  CHECK_EQ(-308, point);
69
70  status = FastDtoa(2147483648.0, FAST_DTOA_SHORTEST, 0,
71                    buffer, &length, &point);
72  CHECK(status);
73  CHECK_EQ("2147483648", buffer.start());
74  CHECK_EQ(10, point);
75
76  status = FastDtoa(3.5844466002796428e+298, FAST_DTOA_SHORTEST, 0,
77                    buffer, &length, &point);
78  if (status) {  // Not all FastDtoa variants manage to compute this number.
79    CHECK_EQ("35844466002796428", buffer.start());
80    CHECK_EQ(299, point);
81  }
82
83  uint64_t smallest_normal64 = V8_2PART_UINT64_C(0x00100000, 00000000);
84  double v = Double(smallest_normal64).value();
85  status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);
86  if (status) {
87    CHECK_EQ("22250738585072014", buffer.start());
88    CHECK_EQ(-307, point);
89  }
90
91  uint64_t largest_denormal64 = V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF);
92  v = Double(largest_denormal64).value();
93  status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);
94  if (status) {
95    CHECK_EQ("2225073858507201", buffer.start());
96    CHECK_EQ(-307, point);
97  }
98}
99
100
101TEST(FastDtoaPrecisionVariousDoubles) {
102  char buffer_container[kBufferSize];
103  Vector<char> buffer(buffer_container, kBufferSize);
104  int length;
105  int point;
106  int status;
107
108  status = FastDtoa(1.0, FAST_DTOA_PRECISION, 3, buffer, &length, &point);
109  CHECK(status);
110  CHECK_GE(3, length);
111  TrimRepresentation(buffer);
112  CHECK_EQ("1", buffer.start());
113  CHECK_EQ(1, point);
114
115  status = FastDtoa(1.5, FAST_DTOA_PRECISION, 10, buffer, &length, &point);
116  if (status) {
117    CHECK_GE(10, length);
118    TrimRepresentation(buffer);
119    CHECK_EQ("15", buffer.start());
120    CHECK_EQ(1, point);
121  }
122
123  double min_double = 5e-324;
124  status = FastDtoa(min_double, FAST_DTOA_PRECISION, 5,
125                    buffer, &length, &point);
126  CHECK(status);
127  CHECK_EQ("49407", buffer.start());
128  CHECK_EQ(-323, point);
129
130  double max_double = 1.7976931348623157e308;
131  status = FastDtoa(max_double, FAST_DTOA_PRECISION, 7,
132                    buffer, &length, &point);
133  CHECK(status);
134  CHECK_EQ("1797693", buffer.start());
135  CHECK_EQ(309, point);
136
137  status = FastDtoa(4294967272.0, FAST_DTOA_PRECISION, 14,
138                    buffer, &length, &point);
139  if (status) {
140    CHECK_GE(14, length);
141    TrimRepresentation(buffer);
142    CHECK_EQ("4294967272", buffer.start());
143    CHECK_EQ(10, point);
144  }
145
146  status = FastDtoa(4.1855804968213567e298, FAST_DTOA_PRECISION, 17,
147                    buffer, &length, &point);
148  CHECK(status);
149  CHECK_EQ("41855804968213567", buffer.start());
150  CHECK_EQ(299, point);
151
152  status = FastDtoa(5.5626846462680035e-309, FAST_DTOA_PRECISION, 1,
153                    buffer, &length, &point);
154  CHECK(status);
155  CHECK_EQ("6", buffer.start());
156  CHECK_EQ(-308, point);
157
158  status = FastDtoa(2147483648.0, FAST_DTOA_PRECISION, 5,
159                    buffer, &length, &point);
160  CHECK(status);
161  CHECK_EQ("21475", buffer.start());
162  CHECK_EQ(10, point);
163
164  status = FastDtoa(3.5844466002796428e+298, FAST_DTOA_PRECISION, 10,
165                    buffer, &length, &point);
166  CHECK(status);
167  CHECK_GE(10, length);
168  TrimRepresentation(buffer);
169  CHECK_EQ("35844466", buffer.start());
170  CHECK_EQ(299, point);
171
172  uint64_t smallest_normal64 = V8_2PART_UINT64_C(0x00100000, 00000000);
173  double v = Double(smallest_normal64).value();
174  status = FastDtoa(v, FAST_DTOA_PRECISION, 17, buffer, &length, &point);
175  CHECK(status);
176  CHECK_EQ("22250738585072014", buffer.start());
177  CHECK_EQ(-307, point);
178
179  uint64_t largest_denormal64 = V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF);
180  v = Double(largest_denormal64).value();
181  status = FastDtoa(v, FAST_DTOA_PRECISION, 17, buffer, &length, &point);
182  CHECK(status);
183  CHECK_GE(20, length);
184  TrimRepresentation(buffer);
185  CHECK_EQ("22250738585072009", buffer.start());
186  CHECK_EQ(-307, point);
187
188  v = 3.3161339052167390562200598e-237;
189  status = FastDtoa(v, FAST_DTOA_PRECISION, 18, buffer, &length, &point);
190  CHECK(status);
191  CHECK_EQ("331613390521673906", buffer.start());
192  CHECK_EQ(-236, point);
193
194  v = 7.9885183916008099497815232e+191;
195  status = FastDtoa(v, FAST_DTOA_PRECISION, 4, buffer, &length, &point);
196  CHECK(status);
197  CHECK_EQ("7989", buffer.start());
198  CHECK_EQ(192, point);
199}
200
201
202TEST(FastDtoaGayShortest) {
203  char buffer_container[kBufferSize];
204  Vector<char> buffer(buffer_container, kBufferSize);
205  bool status;
206  int length;
207  int point;
208  int succeeded = 0;
209  int total = 0;
210  bool needed_max_length = false;
211
212  Vector<const PrecomputedShortest> precomputed =
213      PrecomputedShortestRepresentations();
214  for (int i = 0; i < precomputed.length(); ++i) {
215    const PrecomputedShortest current_test = precomputed[i];
216    total++;
217    double v = current_test.v;
218    status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);
219    CHECK_GE(kFastDtoaMaximalLength, length);
220    if (!status) continue;
221    if (length == kFastDtoaMaximalLength) needed_max_length = true;
222    succeeded++;
223    CHECK_EQ(current_test.decimal_point, point);
224    CHECK_EQ(current_test.representation, buffer.start());
225  }
226  CHECK_GT(succeeded*1.0/total, 0.99);
227  CHECK(needed_max_length);
228}
229
230
231TEST(FastDtoaGayPrecision) {
232  char buffer_container[kBufferSize];
233  Vector<char> buffer(buffer_container, kBufferSize);
234  bool status;
235  int length;
236  int point;
237  int succeeded = 0;
238  int total = 0;
239  // Count separately for entries with less than 15 requested digits.
240  int succeeded_15 = 0;
241  int total_15 = 0;
242
243  Vector<const PrecomputedPrecision> precomputed =
244      PrecomputedPrecisionRepresentations();
245  for (int i = 0; i < precomputed.length(); ++i) {
246    const PrecomputedPrecision current_test = precomputed[i];
247    double v = current_test.v;
248    int number_digits = current_test.number_digits;
249    total++;
250    if (number_digits <= 15) total_15++;
251    status = FastDtoa(v, FAST_DTOA_PRECISION, number_digits,
252                      buffer, &length, &point);
253    CHECK_GE(number_digits, length);
254    if (!status) continue;
255    succeeded++;
256    if (number_digits <= 15) succeeded_15++;
257    TrimRepresentation(buffer);
258    CHECK_EQ(current_test.decimal_point, point);
259    CHECK_EQ(current_test.representation, buffer.start());
260  }
261  // The precomputed numbers contain many entries with many requested
262  // digits. These have a high failure rate and we therefore expect a lower
263  // success rate than for the shortest representation.
264  CHECK_GT(succeeded*1.0/total, 0.85);
265  // However with less than 15 digits almost the algorithm should almost always
266  // succeed.
267  CHECK_GT(succeeded_15*1.0/total_15, 0.9999);
268}
269