mfbt/double-conversion/fixed-dtoa.cc

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 // Copyright 2010 the V8 project authors. All rights reserved.
michael@0 2 // Redistribution and use in source and binary forms, with or without
michael@0 3 // modification, are permitted provided that the following conditions are
michael@0 4 // met:
michael@0 5 //
michael@0 6 // * Redistributions of source code must retain the above copyright
michael@0 7 // notice, this list of conditions and the following disclaimer.
michael@0 8 // * Redistributions in binary form must reproduce the above
michael@0 9 // copyright notice, this list of conditions and the following
michael@0 10 // disclaimer in the documentation and/or other materials provided
michael@0 11 // with the distribution.
michael@0 12 // * Neither the name of Google Inc. nor the names of its
michael@0 13 // contributors may be used to endorse or promote products derived
michael@0 14 // from this software without specific prior written permission.
michael@0 15 //
michael@0 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
michael@0 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
michael@0 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
michael@0 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
michael@0 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@0 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@0 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
michael@0 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
michael@0 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
michael@0 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 27
michael@0 28 #include <math.h>
michael@0 29
michael@0 30 #include "fixed-dtoa.h"
michael@0 31 #include "ieee.h"
michael@0 32
michael@0 33 namespace double_conversion {
michael@0 34
michael@0 35 // Represents a 128bit type. This class should be replaced by a native type on
michael@0 36 // platforms that support 128bit integers.
michael@0 37 class UInt128 {
michael@0 38 public:
michael@0 39 UInt128() : high_bits_(0), low_bits_(0) { }
michael@0 40 UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) { }
michael@0 41
michael@0 42 void Multiply(uint32_t multiplicand) {
michael@0 43 uint64_t accumulator;
michael@0 44
michael@0 45 accumulator = (low_bits_ & kMask32) * multiplicand;
michael@0 46 uint32_t part = static_cast<uint32_t>(accumulator & kMask32);
michael@0 47 accumulator >>= 32;
michael@0 48 accumulator = accumulator + (low_bits_ >> 32) * multiplicand;
michael@0 49 low_bits_ = (accumulator << 32) + part;
michael@0 50 accumulator >>= 32;
michael@0 51 accumulator = accumulator + (high_bits_ & kMask32) * multiplicand;
michael@0 52 part = static_cast<uint32_t>(accumulator & kMask32);
michael@0 53 accumulator >>= 32;
michael@0 54 accumulator = accumulator + (high_bits_ >> 32) * multiplicand;
michael@0 55 high_bits_ = (accumulator << 32) + part;
michael@0 56 ASSERT((accumulator >> 32) == 0);
michael@0 57 }
michael@0 58
michael@0 59 void Shift(int shift_amount) {
michael@0 60 ASSERT(-64 <= shift_amount && shift_amount <= 64);
michael@0 61 if (shift_amount == 0) {
michael@0 62 return;
michael@0 63 } else if (shift_amount == -64) {
michael@0 64 high_bits_ = low_bits_;
michael@0 65 low_bits_ = 0;
michael@0 66 } else if (shift_amount == 64) {
michael@0 67 low_bits_ = high_bits_;
michael@0 68 high_bits_ = 0;
michael@0 69 } else if (shift_amount <= 0) {
michael@0 70 high_bits_ <<= -shift_amount;
michael@0 71 high_bits_ += low_bits_ >> (64 + shift_amount);
michael@0 72 low_bits_ <<= -shift_amount;
michael@0 73 } else {
michael@0 74 low_bits_ >>= shift_amount;
michael@0 75 low_bits_ += high_bits_ << (64 - shift_amount);
michael@0 76 high_bits_ >>= shift_amount;
michael@0 77 }
michael@0 78 }
michael@0 79
michael@0 80 // Modifies *this to *this MOD (2^power).
michael@0 81 // Returns *this DIV (2^power).
michael@0 82 int DivModPowerOf2(int power) {
michael@0 83 if (power >= 64) {
michael@0 84 int result = static_cast<int>(high_bits_ >> (power - 64));
michael@0 85 high_bits_ -= static_cast<uint64_t>(result) << (power - 64);
michael@0 86 return result;
michael@0 87 } else {
michael@0 88 uint64_t part_low = low_bits_ >> power;
michael@0 89 uint64_t part_high = high_bits_ << (64 - power);
michael@0 90 int result = static_cast<int>(part_low + part_high);
michael@0 91 high_bits_ = 0;
michael@0 92 low_bits_ -= part_low << power;
michael@0 93 return result;
michael@0 94 }
michael@0 95 }
michael@0 96
michael@0 97 bool IsZero() const {
michael@0 98 return high_bits_ == 0 && low_bits_ == 0;
michael@0 99 }
michael@0 100
michael@0 101 int BitAt(int position) {
michael@0 102 if (position >= 64) {
michael@0 103 return static_cast<int>(high_bits_ >> (position - 64)) & 1;
michael@0 104 } else {
michael@0 105 return static_cast<int>(low_bits_ >> position) & 1;
michael@0 106 }
michael@0 107 }
michael@0 108
michael@0 109 private:
michael@0 110 static const uint64_t kMask32 = 0xFFFFFFFF;
michael@0 111 // Value == (high_bits_ << 64) + low_bits_
michael@0 112 uint64_t high_bits_;
michael@0 113 uint64_t low_bits_;
michael@0 114 };
michael@0 115
michael@0 116
michael@0 117 static const int kDoubleSignificandSize = 53; // Includes the hidden bit.
michael@0 118
michael@0 119
michael@0 120 static void FillDigits32FixedLength(uint32_t number, int requested_length,
michael@0 121 Vector<char> buffer, int* length) {
michael@0 122 for (int i = requested_length - 1; i >= 0; --i) {
michael@0 123 buffer[(*length) + i] = '0' + number % 10;
michael@0 124 number /= 10;
michael@0 125 }
michael@0 126 *length += requested_length;
michael@0 127 }
michael@0 128
michael@0 129
michael@0 130 static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) {
michael@0 131 int number_length = 0;
michael@0 132 // We fill the digits in reverse order and exchange them afterwards.
michael@0 133 while (number != 0) {
michael@0 134 int digit = number % 10;
michael@0 135 number /= 10;
michael@0 136 buffer[(*length) + number_length] = '0' + digit;
michael@0 137 number_length++;
michael@0 138 }
michael@0 139 // Exchange the digits.
michael@0 140 int i = *length;
michael@0 141 int j = *length + number_length - 1;
michael@0 142 while (i < j) {
michael@0 143 char tmp = buffer[i];
michael@0 144 buffer[i] = buffer[j];
michael@0 145 buffer[j] = tmp;
michael@0 146 i++;
michael@0 147 j--;
michael@0 148 }
michael@0 149 *length += number_length;
michael@0 150 }
michael@0 151
michael@0 152
michael@0 153 static void FillDigits64FixedLength(uint64_t number, int requested_length,
michael@0 154 Vector<char> buffer, int* length) {
michael@0 155 const uint32_t kTen7 = 10000000;
michael@0 156 // For efficiency cut the number into 3 uint32_t parts, and print those.
michael@0 157 uint32_t part2 = static_cast<uint32_t>(number % kTen7);
michael@0 158 number /= kTen7;
michael@0 159 uint32_t part1 = static_cast<uint32_t>(number % kTen7);
michael@0 160 uint32_t part0 = static_cast<uint32_t>(number / kTen7);
michael@0 161
michael@0 162 FillDigits32FixedLength(part0, 3, buffer, length);
michael@0 163 FillDigits32FixedLength(part1, 7, buffer, length);
michael@0 164 FillDigits32FixedLength(part2, 7, buffer, length);
michael@0 165 }
michael@0 166
michael@0 167
michael@0 168 static void FillDigits64(uint64_t number, Vector<char> buffer, int* length) {
michael@0 169 const uint32_t kTen7 = 10000000;
michael@0 170 // For efficiency cut the number into 3 uint32_t parts, and print those.
michael@0 171 uint32_t part2 = static_cast<uint32_t>(number % kTen7);
michael@0 172 number /= kTen7;
michael@0 173 uint32_t part1 = static_cast<uint32_t>(number % kTen7);
michael@0 174 uint32_t part0 = static_cast<uint32_t>(number / kTen7);
michael@0 175
michael@0 176 if (part0 != 0) {
michael@0 177 FillDigits32(part0, buffer, length);
michael@0 178 FillDigits32FixedLength(part1, 7, buffer, length);
michael@0 179 FillDigits32FixedLength(part2, 7, buffer, length);
michael@0 180 } else if (part1 != 0) {
michael@0 181 FillDigits32(part1, buffer, length);
michael@0 182 FillDigits32FixedLength(part2, 7, buffer, length);
michael@0 183 } else {
michael@0 184 FillDigits32(part2, buffer, length);
michael@0 185 }
michael@0 186 }
michael@0 187
michael@0 188
michael@0 189 static void RoundUp(Vector<char> buffer, int* length, int* decimal_point) {
michael@0 190 // An empty buffer represents 0.
michael@0 191 if (*length == 0) {
michael@0 192 buffer[0] = '1';
michael@0 193 *decimal_point = 1;
michael@0 194 *length = 1;
michael@0 195 return;
michael@0 196 }
michael@0 197 // Round the last digit until we either have a digit that was not '9' or until
michael@0 198 // we reached the first digit.
michael@0 199 buffer[(*length) - 1]++;
michael@0 200 for (int i = (*length) - 1; i > 0; --i) {
michael@0 201 if (buffer[i] != '0' + 10) {
michael@0 202 return;
michael@0 203 }
michael@0 204 buffer[i] = '0';
michael@0 205 buffer[i - 1]++;
michael@0 206 }
michael@0 207 // If the first digit is now '0' + 10, we would need to set it to '0' and add
michael@0 208 // a '1' in front. However we reach the first digit only if all following
michael@0 209 // digits had been '9' before rounding up. Now all trailing digits are '0' and
michael@0 210 // we simply switch the first digit to '1' and update the decimal-point
michael@0 211 // (indicating that the point is now one digit to the right).
michael@0 212 if (buffer[0] == '0' + 10) {
michael@0 213 buffer[0] = '1';
michael@0 214 (*decimal_point)++;
michael@0 215 }
michael@0 216 }
michael@0 217
michael@0 218
michael@0 219 // The given fractionals number represents a fixed-point number with binary
michael@0 220 // point at bit (-exponent).
michael@0 221 // Preconditions:
michael@0 222 // -128 <= exponent <= 0.
michael@0 223 // 0 <= fractionals * 2^exponent < 1
michael@0 224 // The buffer holds the result.
michael@0 225 // The function will round its result. During the rounding-process digits not
michael@0 226 // generated by this function might be updated, and the decimal-point variable
michael@0 227 // might be updated. If this function generates the digits 99 and the buffer
michael@0 228 // already contained "199" (thus yielding a buffer of "19999") then a
michael@0 229 // rounding-up will change the contents of the buffer to "20000".
michael@0 230 static void FillFractionals(uint64_t fractionals, int exponent,
michael@0 231 int fractional_count, Vector<char> buffer,
michael@0 232 int* length, int* decimal_point) {
michael@0 233 ASSERT(-128 <= exponent && exponent <= 0);
michael@0 234 // 'fractionals' is a fixed-point number, with binary point at bit
michael@0 235 // (-exponent). Inside the function the non-converted remainder of fractionals
michael@0 236 // is a fixed-point number, with binary point at bit 'point'.
michael@0 237 if (-exponent <= 64) {
michael@0 238 // One 64 bit number is sufficient.
michael@0 239 ASSERT(fractionals >> 56 == 0);
michael@0 240 int point = -exponent;
michael@0 241 for (int i = 0; i < fractional_count; ++i) {
michael@0 242 if (fractionals == 0) break;
michael@0 243 // Instead of multiplying by 10 we multiply by 5 and adjust the point
michael@0 244 // location. This way the fractionals variable will not overflow.
michael@0 245 // Invariant at the beginning of the loop: fractionals < 2^point.
michael@0 246 // Initially we have: point <= 64 and fractionals < 2^56
michael@0 247 // After each iteration the point is decremented by one.
michael@0 248 // Note that 5^3 = 125 < 128 = 2^7.
michael@0 249 // Therefore three iterations of this loop will not overflow fractionals
michael@0 250 // (even without the subtraction at the end of the loop body). At this
michael@0 251 // time point will satisfy point <= 61 and therefore fractionals < 2^point
michael@0 252 // and any further multiplication of fractionals by 5 will not overflow.
michael@0 253 fractionals *= 5;
michael@0 254 point--;
michael@0 255 int digit = static_cast<int>(fractionals >> point);
michael@0 256 buffer[*length] = '0' + digit;
michael@0 257 (*length)++;
michael@0 258 fractionals -= static_cast<uint64_t>(digit) << point;
michael@0 259 }
michael@0 260 // If the first bit after the point is set we have to round up.
michael@0 261 if (((fractionals >> (point - 1)) & 1) == 1) {
michael@0 262 RoundUp(buffer, length, decimal_point);
michael@0 263 }
michael@0 264 } else { // We need 128 bits.
michael@0 265 ASSERT(64 < -exponent && -exponent <= 128);
michael@0 266 UInt128 fractionals128 = UInt128(fractionals, 0);
michael@0 267 fractionals128.Shift(-exponent - 64);
michael@0 268 int point = 128;
michael@0 269 for (int i = 0; i < fractional_count; ++i) {
michael@0 270 if (fractionals128.IsZero()) break;
michael@0 271 // As before: instead of multiplying by 10 we multiply by 5 and adjust the
michael@0 272 // point location.
michael@0 273 // This multiplication will not overflow for the same reasons as before.
michael@0 274 fractionals128.Multiply(5);
michael@0 275 point--;
michael@0 276 int digit = fractionals128.DivModPowerOf2(point);
michael@0 277 buffer[*length] = '0' + digit;
michael@0 278 (*length)++;
michael@0 279 }
michael@0 280 if (fractionals128.BitAt(point - 1) == 1) {
michael@0 281 RoundUp(buffer, length, decimal_point);
michael@0 282 }
michael@0 283 }
michael@0 284 }
michael@0 285
michael@0 286
michael@0 287 // Removes leading and trailing zeros.
michael@0 288 // If leading zeros are removed then the decimal point position is adjusted.
michael@0 289 static void TrimZeros(Vector<char> buffer, int* length, int* decimal_point) {
michael@0 290 while (*length > 0 && buffer[(*length) - 1] == '0') {
michael@0 291 (*length)--;
michael@0 292 }
michael@0 293 int first_non_zero = 0;
michael@0 294 while (first_non_zero < *length && buffer[first_non_zero] == '0') {
michael@0 295 first_non_zero++;
michael@0 296 }
michael@0 297 if (first_non_zero != 0) {
michael@0 298 for (int i = first_non_zero; i < *length; ++i) {
michael@0 299 buffer[i - first_non_zero] = buffer[i];
michael@0 300 }
michael@0 301 *length -= first_non_zero;
michael@0 302 *decimal_point -= first_non_zero;
michael@0 303 }
michael@0 304 }
michael@0 305
michael@0 306
michael@0 307 bool FastFixedDtoa(double v,
michael@0 308 int fractional_count,
michael@0 309 Vector<char> buffer,
michael@0 310 int* length,
michael@0 311 int* decimal_point) {
michael@0 312 const uint32_t kMaxUInt32 = 0xFFFFFFFF;
michael@0 313 uint64_t significand = Double(v).Significand();
michael@0 314 int exponent = Double(v).Exponent();
michael@0 315 // v = significand * 2^exponent (with significand a 53bit integer).
michael@0 316 // If the exponent is larger than 20 (i.e. we may have a 73bit number) then we
michael@0 317 // don't know how to compute the representation. 2^73 ~= 9.5*10^21.
michael@0 318 // If necessary this limit could probably be increased, but we don't need
michael@0 319 // more.
michael@0 320 if (exponent > 20) return false;
michael@0 321 if (fractional_count > 20) return false;
michael@0 322 *length = 0;
michael@0 323 // At most kDoubleSignificandSize bits of the significand are non-zero.
michael@0 324 // Given a 64 bit integer we have 11 0s followed by 53 potentially non-zero
michael@0 325 // bits: 0..11*..0xxx..53*..xx
michael@0 326 if (exponent + kDoubleSignificandSize > 64) {
michael@0 327 // The exponent must be > 11.
michael@0 328 //
michael@0 329 // We know that v = significand * 2^exponent.
michael@0 330 // And the exponent > 11.
michael@0 331 // We simplify the task by dividing v by 10^17.
michael@0 332 // The quotient delivers the first digits, and the remainder fits into a 64
michael@0 333 // bit number.
michael@0 334 // Dividing by 10^17 is equivalent to dividing by 5^17*2^17.
michael@0 335 const uint64_t kFive17 = UINT64_2PART_C(0xB1, A2BC2EC5); // 5^17
michael@0 336 uint64_t divisor = kFive17;
michael@0 337 int divisor_power = 17;
michael@0 338 uint64_t dividend = significand;
michael@0 339 uint32_t quotient;
michael@0 340 uint64_t remainder;
michael@0 341 // Let v = f * 2^e with f == significand and e == exponent.
michael@0 342 // Then need q (quotient) and r (remainder) as follows:
michael@0 343 // v = q * 10^17 + r
michael@0 344 // f * 2^e = q * 10^17 + r
michael@0 345 // f * 2^e = q * 5^17 * 2^17 + r
michael@0 346 // If e > 17 then
michael@0 347 // f * 2^(e-17) = q * 5^17 + r/2^17
michael@0 348 // else
michael@0 349 // f = q * 5^17 * 2^(17-e) + r/2^e
michael@0 350 if (exponent > divisor_power) {
michael@0 351 // We only allow exponents of up to 20 and therefore (17 - e) <= 3
michael@0 352 dividend <<= exponent - divisor_power;
michael@0 353 quotient = static_cast<uint32_t>(dividend / divisor);
michael@0 354 remainder = (dividend % divisor) << divisor_power;
michael@0 355 } else {
michael@0 356 divisor <<= divisor_power - exponent;
michael@0 357 quotient = static_cast<uint32_t>(dividend / divisor);
michael@0 358 remainder = (dividend % divisor) << exponent;
michael@0 359 }
michael@0 360 FillDigits32(quotient, buffer, length);
michael@0 361 FillDigits64FixedLength(remainder, divisor_power, buffer, length);
michael@0 362 *decimal_point = *length;
michael@0 363 } else if (exponent >= 0) {
michael@0 364 // 0 <= exponent <= 11
michael@0 365 significand <<= exponent;
michael@0 366 FillDigits64(significand, buffer, length);
michael@0 367 *decimal_point = *length;
michael@0 368 } else if (exponent > -kDoubleSignificandSize) {
michael@0 369 // We have to cut the number.
michael@0 370 uint64_t integrals = significand >> -exponent;
michael@0 371 uint64_t fractionals = significand - (integrals << -exponent);
michael@0 372 if (integrals > kMaxUInt32) {
michael@0 373 FillDigits64(integrals, buffer, length);
michael@0 374 } else {
michael@0 375 FillDigits32(static_cast<uint32_t>(integrals), buffer, length);
michael@0 376 }
michael@0 377 *decimal_point = *length;
michael@0 378 FillFractionals(fractionals, exponent, fractional_count,
michael@0 379 buffer, length, decimal_point);
michael@0 380 } else if (exponent < -128) {
michael@0 381 // This configuration (with at most 20 digits) means that all digits must be
michael@0 382 // 0.
michael@0 383 ASSERT(fractional_count <= 20);
michael@0 384 buffer[0] = '\0';
michael@0 385 *length = 0;
michael@0 386 *decimal_point = -fractional_count;
michael@0 387 } else {
michael@0 388 *decimal_point = 0;
michael@0 389 FillFractionals(significand, exponent, fractional_count,
michael@0 390 buffer, length, decimal_point);
michael@0 391 }
michael@0 392 TrimZeros(buffer, length, decimal_point);
michael@0 393 buffer[*length] = '\0';
michael@0 394 if ((*length) == 0) {
michael@0 395 // The string is empty and the decimal_point thus has no importance. Mimick
michael@0 396 // Gay's dtoa and and set it to -fractional_count.
michael@0 397 *decimal_point = -fractional_count;
michael@0 398 }
michael@0 399 return true;
michael@0 400 }
michael@0 401
michael@0 402 } // namespace double_conversion

mercurial