• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
15 using namespace v8::internal;
16 
17 static const int kBufferSize = 100;
18 
19 
20 // Removes trailing '0' digits.
TrimRepresentation(Vector<char> representation)21 static 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 
TEST(FastDtoaShortestVariousDoubles)31 TEST(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 
TEST(FastDtoaPrecisionVariousDoubles)101 TEST(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 
TEST(FastDtoaGayShortest)202 TEST(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 
TEST(FastDtoaGayPrecision)231 TEST(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