Home | History | Annotate | Download | only in cctest
      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 "v8.h"
     31 
     32 #include "platform.h"
     33 #include "cctest.h"
     34 #include "diy-fp.h"
     35 #include "double.h"
     36 #include "fast-dtoa.h"
     37 #include "gay-precision.h"
     38 #include "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