1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include <stdlib.h> 29 30 #include "src/v8.h" 31 32 #include "src/base/platform/platform.h" 33 #include "src/diy-fp.h" 34 #include "src/double.h" 35 #include "src/fast-dtoa.h" 36 #include "test/cctest/cctest.h" 37 #include "test/cctest/gay-precision.h" 38 #include "test/cctest/gay-shortest.h" 39 40 using namespace v8::internal; 41 42 static const int kBufferSize = 100; 43 44 45 // Removes trailing '0' digits. 46 static void TrimRepresentation(Vector<char> representation) { 47 int len = StrLength(representation.start()); 48 int i; 49 for (i = len - 1; i >= 0; --i) { 50 if (representation[i] != '0') break; 51 } 52 representation[i + 1] = '\0'; 53 } 54 55 56 TEST(FastDtoaShortestVariousDoubles) { 57 char buffer_container[kBufferSize]; 58 Vector<char> buffer(buffer_container, kBufferSize); 59 int length; 60 int point; 61 int status; 62 63 double min_double = 5e-324; 64 status = FastDtoa(min_double, FAST_DTOA_SHORTEST, 0, 65 buffer, &length, &point); 66 CHECK(status); 67 CHECK_EQ("5", buffer.start()); 68 CHECK_EQ(-323, point); 69 70 double max_double = 1.7976931348623157e308; 71 status = FastDtoa(max_double, FAST_DTOA_SHORTEST, 0, 72 buffer, &length, &point); 73 CHECK(status); 74 CHECK_EQ("17976931348623157", buffer.start()); 75 CHECK_EQ(309, point); 76 77 status = FastDtoa(4294967272.0, FAST_DTOA_SHORTEST, 0, 78 buffer, &length, &point); 79 CHECK(status); 80 CHECK_EQ("4294967272", buffer.start()); 81 CHECK_EQ(10, point); 82 83 status = FastDtoa(4.1855804968213567e298, FAST_DTOA_SHORTEST, 0, 84 buffer, &length, &point); 85 CHECK(status); 86 CHECK_EQ("4185580496821357", buffer.start()); 87 CHECK_EQ(299, point); 88 89 status = FastDtoa(5.5626846462680035e-309, FAST_DTOA_SHORTEST, 0, 90 buffer, &length, &point); 91 CHECK(status); 92 CHECK_EQ("5562684646268003", buffer.start()); 93 CHECK_EQ(-308, point); 94 95 status = FastDtoa(2147483648.0, FAST_DTOA_SHORTEST, 0, 96 buffer, &length, &point); 97 CHECK(status); 98 CHECK_EQ("2147483648", buffer.start()); 99 CHECK_EQ(10, point); 100 101 status = FastDtoa(3.5844466002796428e+298, FAST_DTOA_SHORTEST, 0, 102 buffer, &length, &point); 103 if (status) { // Not all FastDtoa variants manage to compute this number. 104 CHECK_EQ("35844466002796428", buffer.start()); 105 CHECK_EQ(299, point); 106 } 107 108 uint64_t smallest_normal64 = V8_2PART_UINT64_C(0x00100000, 00000000); 109 double v = Double(smallest_normal64).value(); 110 status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point); 111 if (status) { 112 CHECK_EQ("22250738585072014", buffer.start()); 113 CHECK_EQ(-307, point); 114 } 115 116 uint64_t largest_denormal64 = V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF); 117 v = Double(largest_denormal64).value(); 118 status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point); 119 if (status) { 120 CHECK_EQ("2225073858507201", buffer.start()); 121 CHECK_EQ(-307, point); 122 } 123 } 124 125 126 TEST(FastDtoaPrecisionVariousDoubles) { 127 char buffer_container[kBufferSize]; 128 Vector<char> buffer(buffer_container, kBufferSize); 129 int length; 130 int point; 131 int status; 132 133 status = FastDtoa(1.0, FAST_DTOA_PRECISION, 3, buffer, &length, &point); 134 CHECK(status); 135 CHECK_GE(3, length); 136 TrimRepresentation(buffer); 137 CHECK_EQ("1", buffer.start()); 138 CHECK_EQ(1, point); 139 140 status = FastDtoa(1.5, FAST_DTOA_PRECISION, 10, buffer, &length, &point); 141 if (status) { 142 CHECK_GE(10, length); 143 TrimRepresentation(buffer); 144 CHECK_EQ("15", buffer.start()); 145 CHECK_EQ(1, point); 146 } 147 148 double min_double = 5e-324; 149 status = FastDtoa(min_double, FAST_DTOA_PRECISION, 5, 150 buffer, &length, &point); 151 CHECK(status); 152 CHECK_EQ("49407", buffer.start()); 153 CHECK_EQ(-323, point); 154 155 double max_double = 1.7976931348623157e308; 156 status = FastDtoa(max_double, FAST_DTOA_PRECISION, 7, 157 buffer, &length, &point); 158 CHECK(status); 159 CHECK_EQ("1797693", buffer.start()); 160 CHECK_EQ(309, point); 161 162 status = FastDtoa(4294967272.0, FAST_DTOA_PRECISION, 14, 163 buffer, &length, &point); 164 if (status) { 165 CHECK_GE(14, length); 166 TrimRepresentation(buffer); 167 CHECK_EQ("4294967272", buffer.start()); 168 CHECK_EQ(10, point); 169 } 170 171 status = FastDtoa(4.1855804968213567e298, FAST_DTOA_PRECISION, 17, 172 buffer, &length, &point); 173 CHECK(status); 174 CHECK_EQ("41855804968213567", buffer.start()); 175 CHECK_EQ(299, point); 176 177 status = FastDtoa(5.5626846462680035e-309, FAST_DTOA_PRECISION, 1, 178 buffer, &length, &point); 179 CHECK(status); 180 CHECK_EQ("6", buffer.start()); 181 CHECK_EQ(-308, point); 182 183 status = FastDtoa(2147483648.0, FAST_DTOA_PRECISION, 5, 184 buffer, &length, &point); 185 CHECK(status); 186 CHECK_EQ("21475", buffer.start()); 187 CHECK_EQ(10, point); 188 189 status = FastDtoa(3.5844466002796428e+298, FAST_DTOA_PRECISION, 10, 190 buffer, &length, &point); 191 CHECK(status); 192 CHECK_GE(10, length); 193 TrimRepresentation(buffer); 194 CHECK_EQ("35844466", buffer.start()); 195 CHECK_EQ(299, point); 196 197 uint64_t smallest_normal64 = V8_2PART_UINT64_C(0x00100000, 00000000); 198 double v = Double(smallest_normal64).value(); 199 status = FastDtoa(v, FAST_DTOA_PRECISION, 17, buffer, &length, &point); 200 CHECK(status); 201 CHECK_EQ("22250738585072014", buffer.start()); 202 CHECK_EQ(-307, point); 203 204 uint64_t largest_denormal64 = V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF); 205 v = Double(largest_denormal64).value(); 206 status = FastDtoa(v, FAST_DTOA_PRECISION, 17, buffer, &length, &point); 207 CHECK(status); 208 CHECK_GE(20, length); 209 TrimRepresentation(buffer); 210 CHECK_EQ("22250738585072009", buffer.start()); 211 CHECK_EQ(-307, point); 212 213 v = 3.3161339052167390562200598e-237; 214 status = FastDtoa(v, FAST_DTOA_PRECISION, 18, buffer, &length, &point); 215 CHECK(status); 216 CHECK_EQ("331613390521673906", buffer.start()); 217 CHECK_EQ(-236, point); 218 219 v = 7.9885183916008099497815232e+191; 220 status = FastDtoa(v, FAST_DTOA_PRECISION, 4, buffer, &length, &point); 221 CHECK(status); 222 CHECK_EQ("7989", buffer.start()); 223 CHECK_EQ(192, point); 224 } 225 226 227 TEST(FastDtoaGayShortest) { 228 char buffer_container[kBufferSize]; 229 Vector<char> buffer(buffer_container, kBufferSize); 230 bool status; 231 int length; 232 int point; 233 int succeeded = 0; 234 int total = 0; 235 bool needed_max_length = false; 236 237 Vector<const PrecomputedShortest> precomputed = 238 PrecomputedShortestRepresentations(); 239 for (int i = 0; i < precomputed.length(); ++i) { 240 const PrecomputedShortest current_test = precomputed[i]; 241 total++; 242 double v = current_test.v; 243 status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point); 244 CHECK_GE(kFastDtoaMaximalLength, length); 245 if (!status) continue; 246 if (length == kFastDtoaMaximalLength) needed_max_length = true; 247 succeeded++; 248 CHECK_EQ(current_test.decimal_point, point); 249 CHECK_EQ(current_test.representation, buffer.start()); 250 } 251 CHECK_GT(succeeded*1.0/total, 0.99); 252 CHECK(needed_max_length); 253 } 254 255 256 TEST(FastDtoaGayPrecision) { 257 char buffer_container[kBufferSize]; 258 Vector<char> buffer(buffer_container, kBufferSize); 259 bool status; 260 int length; 261 int point; 262 int succeeded = 0; 263 int total = 0; 264 // Count separately for entries with less than 15 requested digits. 265 int succeeded_15 = 0; 266 int total_15 = 0; 267 268 Vector<const PrecomputedPrecision> precomputed = 269 PrecomputedPrecisionRepresentations(); 270 for (int i = 0; i < precomputed.length(); ++i) { 271 const PrecomputedPrecision current_test = precomputed[i]; 272 double v = current_test.v; 273 int number_digits = current_test.number_digits; 274 total++; 275 if (number_digits <= 15) total_15++; 276 status = FastDtoa(v, FAST_DTOA_PRECISION, number_digits, 277 buffer, &length, &point); 278 CHECK_GE(number_digits, length); 279 if (!status) continue; 280 succeeded++; 281 if (number_digits <= 15) succeeded_15++; 282 TrimRepresentation(buffer); 283 CHECK_EQ(current_test.decimal_point, point); 284 CHECK_EQ(current_test.representation, buffer.start()); 285 } 286 // The precomputed numbers contain many entries with many requested 287 // digits. These have a high failure rate and we therefore expect a lower 288 // success rate than for the shortest representation. 289 CHECK_GT(succeeded*1.0/total, 0.85); 290 // However with less than 15 digits almost the algorithm should almost always 291 // succeed. 292 CHECK_GT(succeeded_15*1.0/total_15, 0.9999); 293 } 294