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. 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 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 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 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 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