mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 14:58:30 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
26
third_party/double-conversion/LICENSE
vendored
Normal file
26
third_party/double-conversion/LICENSE
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
Copyright 2006-2011, the V8 project authors. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
1
third_party/double-conversion/README.cosmo
vendored
Normal file
1
third_party/double-conversion/README.cosmo
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
google/double-conversion@1dce44c4313a6f356fcfa4b3e8887f037ac0bf23
|
621
third_party/double-conversion/bignum-dtoa.cc
vendored
Normal file
621
third_party/double-conversion/bignum-dtoa.cc
vendored
Normal file
|
@ -0,0 +1,621 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "libc/macros.h"
|
||||
#include "libc/math.h"
|
||||
#include "third_party/double-conversion/bignum-dtoa.h"
|
||||
#include "third_party/double-conversion/bignum.h"
|
||||
#include "third_party/double-conversion/ieee.h"
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
double-conversion (BSD-3)\\n\
|
||||
Copyright 2010 the V8 project authors\"");
|
||||
asm(".include \"libc/disclaimer.inc\"");
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
static int NormalizedExponent(uint64_t significand, int exponent) {
|
||||
DOUBLE_CONVERSION_ASSERT(significand != 0);
|
||||
while ((significand & Double::kHiddenBit) == 0) {
|
||||
significand = significand << 1;
|
||||
exponent = exponent - 1;
|
||||
}
|
||||
return exponent;
|
||||
}
|
||||
|
||||
// Forward declarations:
|
||||
// Returns an estimation of k such that 10^(k-1) <= v < 10^k.
|
||||
static int EstimatePower(int exponent);
|
||||
// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
|
||||
// and denominator.
|
||||
static void InitialScaledStartValues(uint64_t significand, int exponent,
|
||||
bool lower_boundary_is_closer,
|
||||
int estimated_power,
|
||||
bool need_boundary_deltas,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus);
|
||||
// Multiplies numerator/denominator so that its values lies in the range 1-10.
|
||||
// Returns decimal_point s.t.
|
||||
// v = numerator'/denominator' * 10^(decimal_point-1)
|
||||
// where numerator' and denominator' are the values of numerator and
|
||||
// denominator after the call to this function.
|
||||
static void FixupMultiply10(int estimated_power, bool is_even,
|
||||
int* decimal_point, Bignum* numerator,
|
||||
Bignum* denominator, Bignum* delta_minus,
|
||||
Bignum* delta_plus);
|
||||
// Generates digits from the left to the right and stops when the generated
|
||||
// digits yield the shortest decimal representation of v.
|
||||
static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus,
|
||||
bool is_even, Vector<char> buffer,
|
||||
int* length);
|
||||
// Generates 'requested_digits' after the decimal point.
|
||||
static void BignumToFixed(int requested_digits, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char> buffer, int* length);
|
||||
// Generates 'count' digits of numerator/denominator.
|
||||
// Once 'count' digits have been produced rounds the result depending on the
|
||||
// remainder (remainders of exactly .5 round upwards). Might update the
|
||||
// decimal_point when rounding up (for example for 0.9999).
|
||||
static void GenerateCountedDigits(int count, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char> buffer, int* length);
|
||||
|
||||
void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
|
||||
Vector<char> buffer, int* length, int* decimal_point) {
|
||||
DOUBLE_CONVERSION_ASSERT(v > 0);
|
||||
DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial());
|
||||
uint64_t significand;
|
||||
int exponent;
|
||||
bool lower_boundary_is_closer;
|
||||
if (mode == BIGNUM_DTOA_SHORTEST_SINGLE) {
|
||||
float f = static_cast<float>(v);
|
||||
DOUBLE_CONVERSION_ASSERT(f == v);
|
||||
significand = Single(f).Significand();
|
||||
exponent = Single(f).Exponent();
|
||||
lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser();
|
||||
} else {
|
||||
significand = Double(v).Significand();
|
||||
exponent = Double(v).Exponent();
|
||||
lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser();
|
||||
}
|
||||
bool need_boundary_deltas =
|
||||
(mode == BIGNUM_DTOA_SHORTEST || mode == BIGNUM_DTOA_SHORTEST_SINGLE);
|
||||
|
||||
bool is_even = (significand & 1) == 0;
|
||||
int normalized_exponent = NormalizedExponent(significand, exponent);
|
||||
// estimated_power might be too low by 1.
|
||||
int estimated_power = EstimatePower(normalized_exponent);
|
||||
|
||||
// Shortcut for Fixed.
|
||||
// The requested digits correspond to the digits after the point. If the
|
||||
// number is much too small, then there is no need in trying to get any
|
||||
// digits.
|
||||
if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) {
|
||||
buffer[0] = '\0';
|
||||
*length = 0;
|
||||
// Set decimal-point to -requested_digits. This is what Gay does.
|
||||
// Note that it should not have any effect anyways since the string is
|
||||
// empty.
|
||||
*decimal_point = -requested_digits;
|
||||
return;
|
||||
}
|
||||
|
||||
Bignum numerator;
|
||||
Bignum denominator;
|
||||
Bignum delta_minus;
|
||||
Bignum delta_plus;
|
||||
// Make sure the bignum can grow large enough. The smallest double equals
|
||||
// 4e-324. In this case the denominator needs fewer than 324*4 binary digits.
|
||||
// The maximum double is 1.7976931348623157e308 which needs fewer than
|
||||
// 308*4 binary digits.
|
||||
DOUBLE_CONVERSION_ASSERT(Bignum::kMaxSignificantBits >= 324 * 4);
|
||||
InitialScaledStartValues(significand, exponent, lower_boundary_is_closer,
|
||||
estimated_power, need_boundary_deltas, &numerator,
|
||||
&denominator, &delta_minus, &delta_plus);
|
||||
// We now have v = (numerator / denominator) * 10^estimated_power.
|
||||
FixupMultiply10(estimated_power, is_even, decimal_point, &numerator,
|
||||
&denominator, &delta_minus, &delta_plus);
|
||||
// We now have v = (numerator / denominator) * 10^(decimal_point-1), and
|
||||
// 1 <= (numerator + delta_plus) / denominator < 10
|
||||
switch (mode) {
|
||||
case BIGNUM_DTOA_SHORTEST:
|
||||
case BIGNUM_DTOA_SHORTEST_SINGLE:
|
||||
GenerateShortestDigits(&numerator, &denominator, &delta_minus,
|
||||
&delta_plus, is_even, buffer, length);
|
||||
break;
|
||||
case BIGNUM_DTOA_FIXED:
|
||||
BignumToFixed(requested_digits, decimal_point, &numerator, &denominator,
|
||||
buffer, length);
|
||||
break;
|
||||
case BIGNUM_DTOA_PRECISION:
|
||||
GenerateCountedDigits(requested_digits, decimal_point, &numerator,
|
||||
&denominator, buffer, length);
|
||||
break;
|
||||
default:
|
||||
DOUBLE_CONVERSION_UNREACHABLE();
|
||||
}
|
||||
buffer[*length] = '\0';
|
||||
}
|
||||
|
||||
// The procedure starts generating digits from the left to the right and stops
|
||||
// when the generated digits yield the shortest decimal representation of v. A
|
||||
// decimal representation of v is a number lying closer to v than to any other
|
||||
// double, so it converts to v when read.
|
||||
//
|
||||
// This is true if d, the decimal representation, is between m- and m+, the
|
||||
// upper and lower boundaries. d must be strictly between them if !is_even.
|
||||
// m- := (numerator - delta_minus) / denominator
|
||||
// m+ := (numerator + delta_plus) / denominator
|
||||
//
|
||||
// Precondition: 0 <= (numerator+delta_plus) / denominator < 10.
|
||||
// If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit
|
||||
// will be produced. This should be the standard precondition.
|
||||
static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus,
|
||||
bool is_even, Vector<char> buffer,
|
||||
int* length) {
|
||||
// Small optimization: if delta_minus and delta_plus are the same just reuse
|
||||
// one of the two bignums.
|
||||
if (Bignum::Equal(*delta_minus, *delta_plus)) {
|
||||
delta_plus = delta_minus;
|
||||
}
|
||||
*length = 0;
|
||||
for (;;) {
|
||||
uint16_t digit;
|
||||
digit = numerator->DivideModuloIntBignum(*denominator);
|
||||
DOUBLE_CONVERSION_ASSERT(
|
||||
digit <= 9); // digit is a uint16_t and therefore always positive.
|
||||
// digit = numerator / denominator (integer division).
|
||||
// numerator = numerator % denominator.
|
||||
buffer[(*length)++] = static_cast<char>(digit + '0');
|
||||
|
||||
// Can we stop already?
|
||||
// If the remainder of the division is less than the distance to the lower
|
||||
// boundary we can stop. In this case we simply round down (discarding the
|
||||
// remainder).
|
||||
// Similarly we test if we can round up (using the upper boundary).
|
||||
bool in_delta_room_minus;
|
||||
bool in_delta_room_plus;
|
||||
if (is_even) {
|
||||
in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus);
|
||||
} else {
|
||||
in_delta_room_minus = Bignum::Less(*numerator, *delta_minus);
|
||||
}
|
||||
if (is_even) {
|
||||
in_delta_room_plus =
|
||||
Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
|
||||
} else {
|
||||
in_delta_room_plus =
|
||||
Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
|
||||
}
|
||||
if (!in_delta_room_minus && !in_delta_room_plus) {
|
||||
// Prepare for next iteration.
|
||||
numerator->Times10();
|
||||
delta_minus->Times10();
|
||||
// We optimized delta_plus to be equal to delta_minus (if they share the
|
||||
// same value). So don't multiply delta_plus if they point to the same
|
||||
// object.
|
||||
if (delta_minus != delta_plus) {
|
||||
delta_plus->Times10();
|
||||
}
|
||||
} else if (in_delta_room_minus && in_delta_room_plus) {
|
||||
// Let's see if 2*numerator < denominator.
|
||||
// If yes, then the next digit would be < 5 and we can round down.
|
||||
int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator);
|
||||
if (compare < 0) {
|
||||
// Remaining digits are less than .5. -> Round down (== do nothing).
|
||||
} else if (compare > 0) {
|
||||
// Remaining digits are more than .5 of denominator. -> Round up.
|
||||
// Note that the last digit could not be a '9' as otherwise the whole
|
||||
// loop would have stopped earlier.
|
||||
// We still have an assert here in case the preconditions were not
|
||||
// satisfied.
|
||||
DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9');
|
||||
buffer[(*length) - 1]++;
|
||||
} else {
|
||||
// Halfway case.
|
||||
// TODO(floitsch): need a way to solve half-way cases.
|
||||
// For now let's round towards even (since this is what Gay seems to
|
||||
// do).
|
||||
|
||||
if ((buffer[(*length) - 1] - '0') % 2 == 0) {
|
||||
// Round down => Do nothing.
|
||||
} else {
|
||||
DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9');
|
||||
buffer[(*length) - 1]++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (in_delta_room_minus) {
|
||||
// Round down (== do nothing).
|
||||
return;
|
||||
} else { // in_delta_room_plus
|
||||
// Round up.
|
||||
// Note again that the last digit could not be '9' since this would have
|
||||
// stopped the loop earlier.
|
||||
// We still have an DOUBLE_CONVERSION_ASSERT here, in case the
|
||||
// preconditions were not satisfied.
|
||||
DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9');
|
||||
buffer[(*length) - 1]++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Let v = numerator / denominator < 10.
|
||||
// Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)
|
||||
// from left to right. Once 'count' digits have been produced we decide wether
|
||||
// to round up or down. Remainders of exactly .5 round upwards. Numbers such
|
||||
// as 9.999999 propagate a carry all the way, and change the
|
||||
// exponent (decimal_point), when rounding upwards.
|
||||
static void GenerateCountedDigits(int count, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char> buffer, int* length) {
|
||||
DOUBLE_CONVERSION_ASSERT(count >= 0);
|
||||
for (int i = 0; i < count - 1; ++i) {
|
||||
uint16_t digit;
|
||||
digit = numerator->DivideModuloIntBignum(*denominator);
|
||||
DOUBLE_CONVERSION_ASSERT(
|
||||
digit <= 9); // digit is a uint16_t and therefore always positive.
|
||||
// digit = numerator / denominator (integer division).
|
||||
// numerator = numerator % denominator.
|
||||
buffer[i] = static_cast<char>(digit + '0');
|
||||
// Prepare for next iteration.
|
||||
numerator->Times10();
|
||||
}
|
||||
// Generate the last digit.
|
||||
uint16_t digit;
|
||||
digit = numerator->DivideModuloIntBignum(*denominator);
|
||||
if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
|
||||
digit++;
|
||||
}
|
||||
DOUBLE_CONVERSION_ASSERT(digit <= 10);
|
||||
buffer[count - 1] = static_cast<char>(digit + '0');
|
||||
// Correct bad digits (in case we had a sequence of '9's). Propagate the
|
||||
// carry until we hat a non-'9' or til we reach the first digit.
|
||||
for (int i = count - 1; i > 0; --i) {
|
||||
if (buffer[i] != '0' + 10) break;
|
||||
buffer[i] = '0';
|
||||
buffer[i - 1]++;
|
||||
}
|
||||
if (buffer[0] == '0' + 10) {
|
||||
// Propagate a carry past the top place.
|
||||
buffer[0] = '1';
|
||||
(*decimal_point)++;
|
||||
}
|
||||
*length = count;
|
||||
}
|
||||
|
||||
// Generates 'requested_digits' after the decimal point. It might omit
|
||||
// trailing '0's. If the input number is too small then no digits at all are
|
||||
// generated (ex.: 2 fixed digits for 0.00001).
|
||||
//
|
||||
// Input verifies: 1 <= (numerator + delta) / denominator < 10.
|
||||
static void BignumToFixed(int requested_digits, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char> buffer, int* length) {
|
||||
// Note that we have to look at more than just the requested_digits, since
|
||||
// a number could be rounded up. Example: v=0.5 with requested_digits=0.
|
||||
// Even though the power of v equals 0 we can't just stop here.
|
||||
if (-(*decimal_point) > requested_digits) {
|
||||
// The number is definitively too small.
|
||||
// Ex: 0.001 with requested_digits == 1.
|
||||
// Set decimal-point to -requested_digits. This is what Gay does.
|
||||
// Note that it should not have any effect anyways since the string is
|
||||
// empty.
|
||||
*decimal_point = -requested_digits;
|
||||
*length = 0;
|
||||
return;
|
||||
} else if (-(*decimal_point) == requested_digits) {
|
||||
// We only need to verify if the number rounds down or up.
|
||||
// Ex: 0.04 and 0.06 with requested_digits == 1.
|
||||
DOUBLE_CONVERSION_ASSERT(*decimal_point == -requested_digits);
|
||||
// Initially the fraction lies in range (1, 10]. Multiply the denominator
|
||||
// by 10 so that we can compare more easily.
|
||||
denominator->Times10();
|
||||
if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
|
||||
// If the fraction is >= 0.5 then we have to include the rounded
|
||||
// digit.
|
||||
buffer[0] = '1';
|
||||
*length = 1;
|
||||
(*decimal_point)++;
|
||||
} else {
|
||||
// Note that we caught most of similar cases earlier.
|
||||
*length = 0;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
// The requested digits correspond to the digits after the point.
|
||||
// The variable 'needed_digits' includes the digits before the point.
|
||||
int needed_digits = (*decimal_point) + requested_digits;
|
||||
GenerateCountedDigits(needed_digits, decimal_point, numerator, denominator,
|
||||
buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns an estimation of k such that 10^(k-1) <= v < 10^k where
|
||||
// v = f * 2^exponent and 2^52 <= f < 2^53.
|
||||
// v is hence a normalized double with the given exponent. The output is an
|
||||
// approximation for the exponent of the decimal approimation .digits * 10^k.
|
||||
//
|
||||
// The result might undershoot by 1 in which case 10^k <= v < 10^k+1.
|
||||
// Note: this property holds for v's upper boundary m+ too.
|
||||
// 10^k <= m+ < 10^k+1.
|
||||
// (see explanation below).
|
||||
//
|
||||
// Examples:
|
||||
// EstimatePower(0) => 16
|
||||
// EstimatePower(-52) => 0
|
||||
//
|
||||
// Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0.
|
||||
static int EstimatePower(int exponent) {
|
||||
// This function estimates log10 of v where v = f*2^e (with e == exponent).
|
||||
// Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)).
|
||||
// Note that f is bounded by its container size. Let p = 53 (the double's
|
||||
// significand size). Then 2^(p-1) <= f < 2^p.
|
||||
//
|
||||
// Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close
|
||||
// to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)).
|
||||
// The computed number undershoots by less than 0.631 (when we compute log3
|
||||
// and not log10).
|
||||
//
|
||||
// Optimization: since we only need an approximated result this computation
|
||||
// can be performed on 64 bit integers. On x86/x64 architecture the speedup is
|
||||
// not really measurable, though.
|
||||
//
|
||||
// Since we want to avoid overshooting we decrement by 1e10 so that
|
||||
// floating-point imprecisions don't affect us.
|
||||
//
|
||||
// Explanation for v's boundary m+: the computation takes advantage of
|
||||
// the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement
|
||||
// (even for denormals where the delta can be much more important).
|
||||
|
||||
const double k1Log10 = 0.30102999566398114; // 1/lg(10)
|
||||
|
||||
// For doubles len(f) == 53 (don't forget the hidden bit).
|
||||
const int kSignificandSize = Double::kSignificandSize;
|
||||
double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
|
||||
return static_cast<int>(estimate);
|
||||
}
|
||||
|
||||
// See comments for InitialScaledStartValues.
|
||||
static void InitialScaledStartValuesPositiveExponent(
|
||||
uint64_t significand, int exponent, int estimated_power,
|
||||
bool need_boundary_deltas, Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
// A positive exponent implies a positive power.
|
||||
DOUBLE_CONVERSION_ASSERT(estimated_power >= 0);
|
||||
// Since the estimated_power is positive we simply multiply the denominator
|
||||
// by 10^estimated_power.
|
||||
|
||||
// numerator = v.
|
||||
numerator->AssignUInt64(significand);
|
||||
numerator->ShiftLeft(exponent);
|
||||
// denominator = 10^estimated_power.
|
||||
denominator->AssignPowerUInt16(10, estimated_power);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Introduce a common denominator so that the deltas to the boundaries are
|
||||
// integers.
|
||||
denominator->ShiftLeft(1);
|
||||
numerator->ShiftLeft(1);
|
||||
// Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
|
||||
// denominator (of 2) delta_plus equals 2^e.
|
||||
delta_plus->AssignUInt16(1);
|
||||
delta_plus->ShiftLeft(exponent);
|
||||
// Same for delta_minus. The adjustments if f == 2^p-1 are done later.
|
||||
delta_minus->AssignUInt16(1);
|
||||
delta_minus->ShiftLeft(exponent);
|
||||
}
|
||||
}
|
||||
|
||||
// See comments for InitialScaledStartValues
|
||||
static void InitialScaledStartValuesNegativeExponentPositivePower(
|
||||
uint64_t significand, int exponent, int estimated_power,
|
||||
bool need_boundary_deltas, Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
// v = f * 2^e with e < 0, and with estimated_power >= 0.
|
||||
// This means that e is close to 0 (have a look at how estimated_power is
|
||||
// computed).
|
||||
|
||||
// numerator = significand
|
||||
// since v = significand * 2^exponent this is equivalent to
|
||||
// numerator = v * / 2^-exponent
|
||||
numerator->AssignUInt64(significand);
|
||||
// denominator = 10^estimated_power * 2^-exponent (with exponent < 0)
|
||||
denominator->AssignPowerUInt16(10, estimated_power);
|
||||
denominator->ShiftLeft(-exponent);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Introduce a common denominator so that the deltas to the boundaries are
|
||||
// integers.
|
||||
denominator->ShiftLeft(1);
|
||||
numerator->ShiftLeft(1);
|
||||
// Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
|
||||
// denominator (of 2) delta_plus equals 2^e.
|
||||
// Given that the denominator already includes v's exponent the distance
|
||||
// to the boundaries is simply 1.
|
||||
delta_plus->AssignUInt16(1);
|
||||
// Same for delta_minus. The adjustments if f == 2^p-1 are done later.
|
||||
delta_minus->AssignUInt16(1);
|
||||
}
|
||||
}
|
||||
|
||||
// See comments for InitialScaledStartValues
|
||||
static void InitialScaledStartValuesNegativeExponentNegativePower(
|
||||
uint64_t significand, int exponent, int estimated_power,
|
||||
bool need_boundary_deltas, Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
// Instead of multiplying the denominator with 10^estimated_power we
|
||||
// multiply all values (numerator and deltas) by 10^-estimated_power.
|
||||
|
||||
// Use numerator as temporary container for power_ten.
|
||||
Bignum* power_ten = numerator;
|
||||
power_ten->AssignPowerUInt16(10, -estimated_power);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Since power_ten == numerator we must make a copy of 10^estimated_power
|
||||
// before we complete the computation of the numerator.
|
||||
// delta_plus = delta_minus = 10^estimated_power
|
||||
delta_plus->AssignBignum(*power_ten);
|
||||
delta_minus->AssignBignum(*power_ten);
|
||||
}
|
||||
|
||||
// numerator = significand * 2 * 10^-estimated_power
|
||||
// since v = significand * 2^exponent this is equivalent to
|
||||
// numerator = v * 10^-estimated_power * 2 * 2^-exponent.
|
||||
// Remember: numerator has been abused as power_ten. So no need to assign it
|
||||
// to itself.
|
||||
DOUBLE_CONVERSION_ASSERT(numerator == power_ten);
|
||||
numerator->MultiplyByUInt64(significand);
|
||||
|
||||
// denominator = 2 * 2^-exponent with exponent < 0.
|
||||
denominator->AssignUInt16(1);
|
||||
denominator->ShiftLeft(-exponent);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Introduce a common denominator so that the deltas to the boundaries are
|
||||
// integers.
|
||||
numerator->ShiftLeft(1);
|
||||
denominator->ShiftLeft(1);
|
||||
// With this shift the boundaries have their correct value, since
|
||||
// delta_plus = 10^-estimated_power, and
|
||||
// delta_minus = 10^-estimated_power.
|
||||
// These assignments have been done earlier.
|
||||
// The adjustments if f == 2^p-1 (lower boundary is closer) are done later.
|
||||
}
|
||||
}
|
||||
|
||||
// Let v = significand * 2^exponent.
|
||||
// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
|
||||
// and denominator. The functions GenerateShortestDigits and
|
||||
// GenerateCountedDigits will then convert this ratio to its decimal
|
||||
// representation d, with the required accuracy.
|
||||
// Then d * 10^estimated_power is the representation of v.
|
||||
// (Note: the fraction and the estimated_power might get adjusted before
|
||||
// generating the decimal representation.)
|
||||
//
|
||||
// The initial start values consist of:
|
||||
// - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power.
|
||||
// - a scaled (common) denominator.
|
||||
// optionally (used by GenerateShortestDigits to decide if it has the shortest
|
||||
// decimal converting back to v):
|
||||
// - v - m-: the distance to the lower boundary.
|
||||
// - m+ - v: the distance to the upper boundary.
|
||||
//
|
||||
// v, m+, m-, and therefore v - m- and m+ - v all share the same denominator.
|
||||
//
|
||||
// Let ep == estimated_power, then the returned values will satisfy:
|
||||
// v / 10^ep = numerator / denominator.
|
||||
// v's boundarys m- and m+:
|
||||
// m- / 10^ep == v / 10^ep - delta_minus / denominator
|
||||
// m+ / 10^ep == v / 10^ep + delta_plus / denominator
|
||||
// Or in other words:
|
||||
// m- == v - delta_minus * 10^ep / denominator;
|
||||
// m+ == v + delta_plus * 10^ep / denominator;
|
||||
//
|
||||
// Since 10^(k-1) <= v < 10^k (with k == estimated_power)
|
||||
// or 10^k <= v < 10^(k+1)
|
||||
// we then have 0.1 <= numerator/denominator < 1
|
||||
// or 1 <= numerator/denominator < 10
|
||||
//
|
||||
// It is then easy to kickstart the digit-generation routine.
|
||||
//
|
||||
// The boundary-deltas are only filled if the mode equals BIGNUM_DTOA_SHORTEST
|
||||
// or BIGNUM_DTOA_SHORTEST_SINGLE.
|
||||
|
||||
static void InitialScaledStartValues(uint64_t significand, int exponent,
|
||||
bool lower_boundary_is_closer,
|
||||
int estimated_power,
|
||||
bool need_boundary_deltas,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
if (exponent >= 0) {
|
||||
InitialScaledStartValuesPositiveExponent(
|
||||
significand, exponent, estimated_power, need_boundary_deltas, numerator,
|
||||
denominator, delta_minus, delta_plus);
|
||||
} else if (estimated_power >= 0) {
|
||||
InitialScaledStartValuesNegativeExponentPositivePower(
|
||||
significand, exponent, estimated_power, need_boundary_deltas, numerator,
|
||||
denominator, delta_minus, delta_plus);
|
||||
} else {
|
||||
InitialScaledStartValuesNegativeExponentNegativePower(
|
||||
significand, exponent, estimated_power, need_boundary_deltas, numerator,
|
||||
denominator, delta_minus, delta_plus);
|
||||
}
|
||||
|
||||
if (need_boundary_deltas && lower_boundary_is_closer) {
|
||||
// The lower boundary is closer at half the distance of "normal" numbers.
|
||||
// Increase the common denominator and adapt all but the delta_minus.
|
||||
denominator->ShiftLeft(1); // *2
|
||||
numerator->ShiftLeft(1); // *2
|
||||
delta_plus->ShiftLeft(1); // *2
|
||||
}
|
||||
}
|
||||
|
||||
// This routine multiplies numerator/denominator so that its values lies in the
|
||||
// range 1-10. That is after a call to this function we have:
|
||||
// 1 <= (numerator + delta_plus) /denominator < 10.
|
||||
// Let numerator the input before modification and numerator' the argument
|
||||
// after modification, then the output-parameter decimal_point is such that
|
||||
// numerator / denominator * 10^estimated_power ==
|
||||
// numerator' / denominator' * 10^(decimal_point - 1)
|
||||
// In some cases estimated_power was too low, and this is already the case. We
|
||||
// then simply adjust the power so that 10^(k-1) <= v < 10^k (with k ==
|
||||
// estimated_power) but do not touch the numerator or denominator.
|
||||
// Otherwise the routine multiplies the numerator and the deltas by 10.
|
||||
static void FixupMultiply10(int estimated_power, bool is_even,
|
||||
int* decimal_point, Bignum* numerator,
|
||||
Bignum* denominator, Bignum* delta_minus,
|
||||
Bignum* delta_plus) {
|
||||
bool in_range;
|
||||
if (is_even) {
|
||||
// For IEEE doubles half-way cases (in decimal system numbers ending with 5)
|
||||
// are rounded to the closest floating-point number with even significand.
|
||||
in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
|
||||
} else {
|
||||
in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
|
||||
}
|
||||
if (in_range) {
|
||||
// Since numerator + delta_plus >= denominator we already have
|
||||
// 1 <= numerator/denominator < 10. Simply update the estimated_power.
|
||||
*decimal_point = estimated_power + 1;
|
||||
} else {
|
||||
*decimal_point = estimated_power;
|
||||
numerator->Times10();
|
||||
if (Bignum::Equal(*delta_minus, *delta_plus)) {
|
||||
delta_minus->Times10();
|
||||
delta_plus->AssignBignum(*delta_minus);
|
||||
} else {
|
||||
delta_minus->Times10();
|
||||
delta_plus->Times10();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
84
third_party/double-conversion/bignum-dtoa.h
vendored
Normal file
84
third_party/double-conversion/bignum-dtoa.h
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_BIGNUM_DTOA_H_
|
||||
#define DOUBLE_CONVERSION_BIGNUM_DTOA_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
enum BignumDtoaMode {
|
||||
// Return the shortest correct representation.
|
||||
// For example the output of 0.299999999999999988897 is (the less accurate but
|
||||
// correct) 0.3.
|
||||
BIGNUM_DTOA_SHORTEST,
|
||||
// Same as BIGNUM_DTOA_SHORTEST but for single-precision floats.
|
||||
BIGNUM_DTOA_SHORTEST_SINGLE,
|
||||
// Return a fixed number of digits after the decimal point.
|
||||
// For instance fixed(0.1, 4) becomes 0.1000
|
||||
// If the input number is big, the output will be big.
|
||||
BIGNUM_DTOA_FIXED,
|
||||
// Return a fixed number of digits, no matter what the exponent is.
|
||||
BIGNUM_DTOA_PRECISION
|
||||
};
|
||||
|
||||
// Converts the given double 'v' to ascii.
|
||||
// The result should be interpreted as buffer * 10^(point-length).
|
||||
// The buffer will be null-terminated.
|
||||
//
|
||||
// The input v must be > 0 and different from NaN, and Infinity.
|
||||
//
|
||||
// The output depends on the given mode:
|
||||
// - SHORTEST: produce the least amount of digits for which the internal
|
||||
// identity requirement is still satisfied. If the digits are printed
|
||||
// (together with the correct exponent) then reading this number will give
|
||||
// 'v' again. The buffer will choose the representation that is closest to
|
||||
// 'v'. If there are two at the same distance, than the number is round up.
|
||||
// In this mode the 'requested_digits' parameter is ignored.
|
||||
// - FIXED: produces digits necessary to print a given number with
|
||||
// 'requested_digits' digits after the decimal point. The produced digits
|
||||
// might be too short in which case the caller has to fill the gaps with '0's.
|
||||
// Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
|
||||
// Halfway cases are rounded up. The call toFixed(0.15, 2) thus returns
|
||||
// buffer="2", point=0.
|
||||
// Note: the length of the returned buffer has no meaning wrt the significance
|
||||
// of its digits. That is, just because it contains '0's does not mean that
|
||||
// any other digit would not satisfy the internal identity requirement.
|
||||
// - PRECISION: produces 'requested_digits' where the first digit is not '0'.
|
||||
// Even though the length of produced digits usually equals
|
||||
// 'requested_digits', the function is allowed to return fewer digits, in
|
||||
// which case the caller has to fill the missing digits with '0's.
|
||||
// Halfway cases are again rounded up.
|
||||
// 'BignumDtoa' expects the given buffer to be big enough to hold all digits
|
||||
// and a terminating null-character.
|
||||
void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
|
||||
Vector<char> buffer, int* length, int* point);
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_BIGNUM_DTOA_H_
|
775
third_party/double-conversion/bignum.cc
vendored
Normal file
775
third_party/double-conversion/bignum.cc
vendored
Normal file
|
@ -0,0 +1,775 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "libc/macros.h"
|
||||
#include "third_party/double-conversion/bignum.h"
|
||||
#include "third_party/double-conversion/utils.h"
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
double-conversion (BSD-3)\\n\
|
||||
Copyright 2010 the V8 project authors\"");
|
||||
asm(".include \"libc/disclaimer.inc\"");
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
Bignum::Chunk& Bignum::RawBigit(const int index) {
|
||||
DOUBLE_CONVERSION_ASSERT(static_cast<unsigned>(index) < kBigitCapacity);
|
||||
return bigits_buffer_[index];
|
||||
}
|
||||
|
||||
const Bignum::Chunk& Bignum::RawBigit(const int index) const {
|
||||
DOUBLE_CONVERSION_ASSERT(static_cast<unsigned>(index) < kBigitCapacity);
|
||||
return bigits_buffer_[index];
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
static int BitSize(const S value) {
|
||||
(void)value; // Mark variable as used.
|
||||
return 8 * sizeof(value);
|
||||
}
|
||||
|
||||
// Guaranteed to lie in one Bigit.
|
||||
void Bignum::AssignUInt16(const uint16_t value) {
|
||||
DOUBLE_CONVERSION_ASSERT(kBigitSize >= BitSize(value));
|
||||
Zero();
|
||||
if (value > 0) {
|
||||
RawBigit(0) = value;
|
||||
used_bigits_ = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Bignum::AssignUInt64(uint64_t value) {
|
||||
Zero();
|
||||
for (int i = 0; value > 0; ++i) {
|
||||
RawBigit(i) = value & kBigitMask;
|
||||
value >>= kBigitSize;
|
||||
++used_bigits_;
|
||||
}
|
||||
}
|
||||
|
||||
void Bignum::AssignBignum(const Bignum& other) {
|
||||
exponent_ = other.exponent_;
|
||||
for (int i = 0; i < other.used_bigits_; ++i) {
|
||||
RawBigit(i) = other.RawBigit(i);
|
||||
}
|
||||
used_bigits_ = other.used_bigits_;
|
||||
}
|
||||
|
||||
static uint64_t ReadUInt64(const Vector<const char> buffer, const int from,
|
||||
const int digits_to_read) {
|
||||
uint64_t result = 0;
|
||||
for (int i = from; i < from + digits_to_read; ++i) {
|
||||
const int digit = buffer[i] - '0';
|
||||
DOUBLE_CONVERSION_ASSERT(0 <= digit && digit <= 9);
|
||||
result = result * 10 + digit;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Bignum::AssignDecimalString(const Vector<const char> value) {
|
||||
// 2^64 = 18446744073709551616 > 10^19
|
||||
static const int kMaxUint64DecimalDigits = 19;
|
||||
Zero();
|
||||
int length = value.length();
|
||||
unsigned pos = 0;
|
||||
// Let's just say that each digit needs 4 bits.
|
||||
while (length >= kMaxUint64DecimalDigits) {
|
||||
const uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
|
||||
pos += kMaxUint64DecimalDigits;
|
||||
length -= kMaxUint64DecimalDigits;
|
||||
MultiplyByPowerOfTen(kMaxUint64DecimalDigits);
|
||||
AddUInt64(digits);
|
||||
}
|
||||
const uint64_t digits = ReadUInt64(value, pos, length);
|
||||
MultiplyByPowerOfTen(length);
|
||||
AddUInt64(digits);
|
||||
Clamp();
|
||||
}
|
||||
|
||||
static uint64_t HexCharValue(const int c) {
|
||||
if ('0' <= c && c <= '9') {
|
||||
return c - '0';
|
||||
}
|
||||
if ('a' <= c && c <= 'f') {
|
||||
return 10 + c - 'a';
|
||||
}
|
||||
DOUBLE_CONVERSION_ASSERT('A' <= c && c <= 'F');
|
||||
return 10 + c - 'A';
|
||||
}
|
||||
|
||||
// Unlike AssignDecimalString(), this function is "only" used
|
||||
// for unit-tests and therefore not performance critical.
|
||||
void Bignum::AssignHexString(Vector<const char> value) {
|
||||
Zero();
|
||||
// Required capacity could be reduced by ignoring leading zeros.
|
||||
EnsureCapacity(((value.length() * 4) + kBigitSize - 1) / kBigitSize);
|
||||
DOUBLE_CONVERSION_ASSERT(sizeof(uint64_t) * 8 >=
|
||||
kBigitSize + 4); // TODO: static_assert
|
||||
// Accumulates converted hex digits until at least kBigitSize bits.
|
||||
// Works with non-factor-of-four kBigitSizes.
|
||||
uint64_t tmp = 0; // Accumulates converted hex digits until at least
|
||||
for (int cnt = 0; !value.is_empty(); value.pop_back()) {
|
||||
tmp |= (HexCharValue(value.last()) << cnt);
|
||||
if ((cnt += 4) >= kBigitSize) {
|
||||
RawBigit(used_bigits_++) = (tmp & kBigitMask);
|
||||
cnt -= kBigitSize;
|
||||
tmp >>= kBigitSize;
|
||||
}
|
||||
}
|
||||
if (tmp > 0) {
|
||||
RawBigit(used_bigits_++) = tmp;
|
||||
}
|
||||
Clamp();
|
||||
}
|
||||
|
||||
void Bignum::AddUInt64(const uint64_t operand) {
|
||||
if (operand == 0) {
|
||||
return;
|
||||
}
|
||||
Bignum other;
|
||||
other.AssignUInt64(operand);
|
||||
AddBignum(other);
|
||||
}
|
||||
|
||||
void Bignum::AddBignum(const Bignum& other) {
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(other.IsClamped());
|
||||
|
||||
// If this has a greater exponent than other append zero-bigits to this.
|
||||
// After this call exponent_ <= other.exponent_.
|
||||
Align(other);
|
||||
|
||||
// There are two possibilities:
|
||||
// aaaaaaaaaaa 0000 (where the 0s represent a's exponent)
|
||||
// bbbbb 00000000
|
||||
// ----------------
|
||||
// ccccccccccc 0000
|
||||
// or
|
||||
// aaaaaaaaaa 0000
|
||||
// bbbbbbbbb 0000000
|
||||
// -----------------
|
||||
// cccccccccccc 0000
|
||||
// In both cases we might need a carry bigit.
|
||||
|
||||
EnsureCapacity(1 + MAX(BigitLength(), other.BigitLength()) - exponent_);
|
||||
Chunk carry = 0;
|
||||
int bigit_pos = other.exponent_ - exponent_;
|
||||
DOUBLE_CONVERSION_ASSERT(bigit_pos >= 0);
|
||||
for (int i = used_bigits_; i < bigit_pos; ++i) {
|
||||
RawBigit(i) = 0;
|
||||
}
|
||||
for (int i = 0; i < other.used_bigits_; ++i) {
|
||||
const Chunk my = (bigit_pos < used_bigits_) ? RawBigit(bigit_pos) : 0;
|
||||
const Chunk sum = my + other.RawBigit(i) + carry;
|
||||
RawBigit(bigit_pos) = sum & kBigitMask;
|
||||
carry = sum >> kBigitSize;
|
||||
++bigit_pos;
|
||||
}
|
||||
while (carry != 0) {
|
||||
const Chunk my = (bigit_pos < used_bigits_) ? RawBigit(bigit_pos) : 0;
|
||||
const Chunk sum = my + carry;
|
||||
RawBigit(bigit_pos) = sum & kBigitMask;
|
||||
carry = sum >> kBigitSize;
|
||||
++bigit_pos;
|
||||
}
|
||||
used_bigits_ = MAX(bigit_pos, static_cast<int>(used_bigits_));
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
}
|
||||
|
||||
void Bignum::SubtractBignum(const Bignum& other) {
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(other.IsClamped());
|
||||
// We require this to be bigger than other.
|
||||
DOUBLE_CONVERSION_ASSERT(LessEqual(other, *this));
|
||||
|
||||
Align(other);
|
||||
|
||||
const int offset = other.exponent_ - exponent_;
|
||||
Chunk borrow = 0;
|
||||
int i;
|
||||
for (i = 0; i < other.used_bigits_; ++i) {
|
||||
DOUBLE_CONVERSION_ASSERT((borrow == 0) || (borrow == 1));
|
||||
const Chunk difference = RawBigit(i + offset) - other.RawBigit(i) - borrow;
|
||||
RawBigit(i + offset) = difference & kBigitMask;
|
||||
borrow = difference >> (kChunkSize - 1);
|
||||
}
|
||||
while (borrow != 0) {
|
||||
const Chunk difference = RawBigit(i + offset) - borrow;
|
||||
RawBigit(i + offset) = difference & kBigitMask;
|
||||
borrow = difference >> (kChunkSize - 1);
|
||||
++i;
|
||||
}
|
||||
Clamp();
|
||||
}
|
||||
|
||||
void Bignum::ShiftLeft(const int shift_amount) {
|
||||
if (used_bigits_ == 0) {
|
||||
return;
|
||||
}
|
||||
exponent_ += (shift_amount / kBigitSize);
|
||||
const int local_shift = shift_amount % kBigitSize;
|
||||
EnsureCapacity(used_bigits_ + 1);
|
||||
BigitsShiftLeft(local_shift);
|
||||
}
|
||||
|
||||
void Bignum::MultiplyByUInt32(const uint32_t factor) {
|
||||
if (factor == 1) {
|
||||
return;
|
||||
}
|
||||
if (factor == 0) {
|
||||
Zero();
|
||||
return;
|
||||
}
|
||||
if (used_bigits_ == 0) {
|
||||
return;
|
||||
}
|
||||
// The product of a bigit with the factor is of size kBigitSize + 32.
|
||||
// Assert that this number + 1 (for the carry) fits into double chunk.
|
||||
DOUBLE_CONVERSION_ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1);
|
||||
DoubleChunk carry = 0;
|
||||
for (int i = 0; i < used_bigits_; ++i) {
|
||||
const DoubleChunk product =
|
||||
static_cast<DoubleChunk>(factor) * RawBigit(i) + carry;
|
||||
RawBigit(i) = static_cast<Chunk>(product & kBigitMask);
|
||||
carry = (product >> kBigitSize);
|
||||
}
|
||||
while (carry != 0) {
|
||||
EnsureCapacity(used_bigits_ + 1);
|
||||
RawBigit(used_bigits_) = carry & kBigitMask;
|
||||
used_bigits_++;
|
||||
carry >>= kBigitSize;
|
||||
}
|
||||
}
|
||||
|
||||
void Bignum::MultiplyByUInt64(const uint64_t factor) {
|
||||
if (factor == 1) {
|
||||
return;
|
||||
}
|
||||
if (factor == 0) {
|
||||
Zero();
|
||||
return;
|
||||
}
|
||||
if (used_bigits_ == 0) {
|
||||
return;
|
||||
}
|
||||
DOUBLE_CONVERSION_ASSERT(kBigitSize < 32);
|
||||
uint64_t carry = 0;
|
||||
const uint64_t low = factor & 0xFFFFFFFF;
|
||||
const uint64_t high = factor >> 32;
|
||||
for (int i = 0; i < used_bigits_; ++i) {
|
||||
const uint64_t product_low = low * RawBigit(i);
|
||||
const uint64_t product_high = high * RawBigit(i);
|
||||
const uint64_t tmp = (carry & kBigitMask) + product_low;
|
||||
RawBigit(i) = tmp & kBigitMask;
|
||||
carry = (carry >> kBigitSize) + (tmp >> kBigitSize) +
|
||||
(product_high << (32 - kBigitSize));
|
||||
}
|
||||
while (carry != 0) {
|
||||
EnsureCapacity(used_bigits_ + 1);
|
||||
RawBigit(used_bigits_) = carry & kBigitMask;
|
||||
used_bigits_++;
|
||||
carry >>= kBigitSize;
|
||||
}
|
||||
}
|
||||
|
||||
void Bignum::MultiplyByPowerOfTen(const int exponent) {
|
||||
static const uint64_t kFive27 =
|
||||
DOUBLE_CONVERSION_UINT64_2PART_C(0x6765c793, fa10079d);
|
||||
static const uint16_t kFive1 = 5;
|
||||
static const uint16_t kFive2 = kFive1 * 5;
|
||||
static const uint16_t kFive3 = kFive2 * 5;
|
||||
static const uint16_t kFive4 = kFive3 * 5;
|
||||
static const uint16_t kFive5 = kFive4 * 5;
|
||||
static const uint16_t kFive6 = kFive5 * 5;
|
||||
static const uint32_t kFive7 = kFive6 * 5;
|
||||
static const uint32_t kFive8 = kFive7 * 5;
|
||||
static const uint32_t kFive9 = kFive8 * 5;
|
||||
static const uint32_t kFive10 = kFive9 * 5;
|
||||
static const uint32_t kFive11 = kFive10 * 5;
|
||||
static const uint32_t kFive12 = kFive11 * 5;
|
||||
static const uint32_t kFive13 = kFive12 * 5;
|
||||
static const uint32_t kFive1_to_12[] = {kFive1, kFive2, kFive3, kFive4,
|
||||
kFive5, kFive6, kFive7, kFive8,
|
||||
kFive9, kFive10, kFive11, kFive12};
|
||||
|
||||
DOUBLE_CONVERSION_ASSERT(exponent >= 0);
|
||||
|
||||
if (exponent == 0) {
|
||||
return;
|
||||
}
|
||||
if (used_bigits_ == 0) {
|
||||
return;
|
||||
}
|
||||
// We shift by exponent at the end just before returning.
|
||||
int remaining_exponent = exponent;
|
||||
while (remaining_exponent >= 27) {
|
||||
MultiplyByUInt64(kFive27);
|
||||
remaining_exponent -= 27;
|
||||
}
|
||||
while (remaining_exponent >= 13) {
|
||||
MultiplyByUInt32(kFive13);
|
||||
remaining_exponent -= 13;
|
||||
}
|
||||
if (remaining_exponent > 0) {
|
||||
MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]);
|
||||
}
|
||||
ShiftLeft(exponent);
|
||||
}
|
||||
|
||||
void Bignum::Square() {
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
const int product_length = 2 * used_bigits_;
|
||||
EnsureCapacity(product_length);
|
||||
|
||||
// Comba multiplication: compute each column separately.
|
||||
// Example: r = a2a1a0 * b2b1b0.
|
||||
// r = 1 * a0b0 +
|
||||
// 10 * (a1b0 + a0b1) +
|
||||
// 100 * (a2b0 + a1b1 + a0b2) +
|
||||
// 1000 * (a2b1 + a1b2) +
|
||||
// 10000 * a2b2
|
||||
//
|
||||
// In the worst case we have to accumulate nb-digits products of digit*digit.
|
||||
//
|
||||
// Assert that the additional number of bits in a DoubleChunk are enough to
|
||||
// sum up used_digits of Bigit*Bigit.
|
||||
if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_bigits_) {
|
||||
DOUBLE_CONVERSION_UNIMPLEMENTED();
|
||||
}
|
||||
DoubleChunk accumulator = 0;
|
||||
// First shift the digits so we don't overwrite them.
|
||||
const int copy_offset = used_bigits_;
|
||||
for (int i = 0; i < used_bigits_; ++i) {
|
||||
RawBigit(copy_offset + i) = RawBigit(i);
|
||||
}
|
||||
// We have two loops to avoid some 'if's in the loop.
|
||||
for (int i = 0; i < used_bigits_; ++i) {
|
||||
// Process temporary digit i with power i.
|
||||
// The sum of the two indices must be equal to i.
|
||||
int bigit_index1 = i;
|
||||
int bigit_index2 = 0;
|
||||
// Sum all of the sub-products.
|
||||
while (bigit_index1 >= 0) {
|
||||
const Chunk chunk1 = RawBigit(copy_offset + bigit_index1);
|
||||
const Chunk chunk2 = RawBigit(copy_offset + bigit_index2);
|
||||
accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
|
||||
bigit_index1--;
|
||||
bigit_index2++;
|
||||
}
|
||||
RawBigit(i) = static_cast<Chunk>(accumulator) & kBigitMask;
|
||||
accumulator >>= kBigitSize;
|
||||
}
|
||||
for (int i = used_bigits_; i < product_length; ++i) {
|
||||
int bigit_index1 = used_bigits_ - 1;
|
||||
int bigit_index2 = i - bigit_index1;
|
||||
// Invariant: sum of both indices is again equal to i.
|
||||
// Inner loop runs 0 times on last iteration, emptying accumulator.
|
||||
while (bigit_index2 < used_bigits_) {
|
||||
const Chunk chunk1 = RawBigit(copy_offset + bigit_index1);
|
||||
const Chunk chunk2 = RawBigit(copy_offset + bigit_index2);
|
||||
accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
|
||||
bigit_index1--;
|
||||
bigit_index2++;
|
||||
}
|
||||
// The overwritten RawBigit(i) will never be read in further loop
|
||||
// iterations, because bigit_index1 and bigit_index2 are always greater than
|
||||
// i - used_bigits_.
|
||||
RawBigit(i) = static_cast<Chunk>(accumulator) & kBigitMask;
|
||||
accumulator >>= kBigitSize;
|
||||
}
|
||||
// Since the result was guaranteed to lie inside the number the
|
||||
// accumulator must be 0 now.
|
||||
DOUBLE_CONVERSION_ASSERT(accumulator == 0);
|
||||
|
||||
// Don't forget to update the used_digits and the exponent.
|
||||
used_bigits_ = product_length;
|
||||
exponent_ *= 2;
|
||||
Clamp();
|
||||
}
|
||||
|
||||
void Bignum::AssignPowerUInt16(uint16_t base, const int power_exponent) {
|
||||
DOUBLE_CONVERSION_ASSERT(base != 0);
|
||||
DOUBLE_CONVERSION_ASSERT(power_exponent >= 0);
|
||||
if (power_exponent == 0) {
|
||||
AssignUInt16(1);
|
||||
return;
|
||||
}
|
||||
Zero();
|
||||
int shifts = 0;
|
||||
// We expect base to be in range 2-32, and most often to be 10.
|
||||
// It does not make much sense to implement different algorithms for counting
|
||||
// the bits.
|
||||
while ((base & 1) == 0) {
|
||||
base >>= 1;
|
||||
shifts++;
|
||||
}
|
||||
int bit_size = 0;
|
||||
int tmp_base = base;
|
||||
while (tmp_base != 0) {
|
||||
tmp_base >>= 1;
|
||||
bit_size++;
|
||||
}
|
||||
const int final_size = bit_size * power_exponent;
|
||||
// 1 extra bigit for the shifting, and one for rounded final_size.
|
||||
EnsureCapacity(final_size / kBigitSize + 2);
|
||||
|
||||
// Left to Right exponentiation.
|
||||
int mask = 1;
|
||||
while (power_exponent >= mask) mask <<= 1;
|
||||
|
||||
// The mask is now pointing to the bit above the most significant 1-bit of
|
||||
// power_exponent.
|
||||
// Get rid of first 1-bit;
|
||||
mask >>= 2;
|
||||
uint64_t this_value = base;
|
||||
|
||||
bool delayed_multiplication = false;
|
||||
const uint64_t max_32bits = 0xFFFFFFFF;
|
||||
while (mask != 0 && this_value <= max_32bits) {
|
||||
this_value = this_value * this_value;
|
||||
// Verify that there is enough space in this_value to perform the
|
||||
// multiplication. The first bit_size bits must be 0.
|
||||
if ((power_exponent & mask) != 0) {
|
||||
DOUBLE_CONVERSION_ASSERT(bit_size > 0);
|
||||
const uint64_t base_bits_mask =
|
||||
~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
|
||||
const bool high_bits_zero = (this_value & base_bits_mask) == 0;
|
||||
if (high_bits_zero) {
|
||||
this_value *= base;
|
||||
} else {
|
||||
delayed_multiplication = true;
|
||||
}
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
AssignUInt64(this_value);
|
||||
if (delayed_multiplication) {
|
||||
MultiplyByUInt32(base);
|
||||
}
|
||||
|
||||
// Now do the same thing as a bignum.
|
||||
while (mask != 0) {
|
||||
Square();
|
||||
if ((power_exponent & mask) != 0) {
|
||||
MultiplyByUInt32(base);
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
// And finally add the saved shifts.
|
||||
ShiftLeft(shifts * power_exponent);
|
||||
}
|
||||
|
||||
// Precondition: this/other < 16bit.
|
||||
uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(other.IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(other.used_bigits_ > 0);
|
||||
|
||||
// Easy case: if we have less digits than the divisor than the result is 0.
|
||||
// Note: this handles the case where this == 0, too.
|
||||
if (BigitLength() < other.BigitLength()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Align(other);
|
||||
|
||||
uint16_t result = 0;
|
||||
|
||||
// Start by removing multiples of 'other' until both numbers have the same
|
||||
// number of digits.
|
||||
while (BigitLength() > other.BigitLength()) {
|
||||
// This naive approach is extremely inefficient if `this` divided by other
|
||||
// is big. This function is implemented for doubleToString where
|
||||
// the result should be small (less than 10).
|
||||
DOUBLE_CONVERSION_ASSERT(other.RawBigit(other.used_bigits_ - 1) >=
|
||||
((1 << kBigitSize) / 16));
|
||||
DOUBLE_CONVERSION_ASSERT(RawBigit(used_bigits_ - 1) < 0x10000);
|
||||
// Remove the multiples of the first digit.
|
||||
// Example this = 23 and other equals 9. -> Remove 2 multiples.
|
||||
result += static_cast<uint16_t>(RawBigit(used_bigits_ - 1));
|
||||
SubtractTimes(other, RawBigit(used_bigits_ - 1));
|
||||
}
|
||||
|
||||
DOUBLE_CONVERSION_ASSERT(BigitLength() == other.BigitLength());
|
||||
|
||||
// Both bignums are at the same length now.
|
||||
// Since other has more than 0 digits we know that the access to
|
||||
// RawBigit(used_bigits_ - 1) is safe.
|
||||
const Chunk this_bigit = RawBigit(used_bigits_ - 1);
|
||||
const Chunk other_bigit = other.RawBigit(other.used_bigits_ - 1);
|
||||
|
||||
if (other.used_bigits_ == 1) {
|
||||
// Shortcut for easy (and common) case.
|
||||
int quotient = this_bigit / other_bigit;
|
||||
RawBigit(used_bigits_ - 1) = this_bigit - other_bigit * quotient;
|
||||
DOUBLE_CONVERSION_ASSERT(quotient < 0x10000);
|
||||
result += static_cast<uint16_t>(quotient);
|
||||
Clamp();
|
||||
return result;
|
||||
}
|
||||
|
||||
const int division_estimate = this_bigit / (other_bigit + 1);
|
||||
DOUBLE_CONVERSION_ASSERT(division_estimate < 0x10000);
|
||||
result += static_cast<uint16_t>(division_estimate);
|
||||
SubtractTimes(other, division_estimate);
|
||||
|
||||
if (other_bigit * (division_estimate + 1) > this_bigit) {
|
||||
// No need to even try to subtract. Even if other's remaining digits were 0
|
||||
// another subtraction would be too much.
|
||||
return result;
|
||||
}
|
||||
|
||||
while (LessEqual(other, *this)) {
|
||||
SubtractBignum(other);
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
static int SizeInHexChars(S number) {
|
||||
DOUBLE_CONVERSION_ASSERT(number > 0);
|
||||
int result = 0;
|
||||
while (number != 0) {
|
||||
number >>= 4;
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static char HexCharOfValue(const int value) {
|
||||
DOUBLE_CONVERSION_ASSERT(0 <= value && value <= 16);
|
||||
if (value < 10) {
|
||||
return static_cast<char>(value + '0');
|
||||
}
|
||||
return static_cast<char>(value - 10 + 'A');
|
||||
}
|
||||
|
||||
bool Bignum::ToHexString(char* buffer, const int buffer_size) const {
|
||||
DOUBLE_CONVERSION_ASSERT(IsClamped());
|
||||
// Each bigit must be printable as separate hex-character.
|
||||
DOUBLE_CONVERSION_ASSERT(kBigitSize % 4 == 0);
|
||||
static const int kHexCharsPerBigit = kBigitSize / 4;
|
||||
|
||||
if (used_bigits_ == 0) {
|
||||
if (buffer_size < 2) {
|
||||
return false;
|
||||
}
|
||||
buffer[0] = '0';
|
||||
buffer[1] = '\0';
|
||||
return true;
|
||||
}
|
||||
// We add 1 for the terminating '\0' character.
|
||||
const int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit +
|
||||
SizeInHexChars(RawBigit(used_bigits_ - 1)) + 1;
|
||||
if (needed_chars > buffer_size) {
|
||||
return false;
|
||||
}
|
||||
int string_index = needed_chars - 1;
|
||||
buffer[string_index--] = '\0';
|
||||
for (int i = 0; i < exponent_; ++i) {
|
||||
for (int j = 0; j < kHexCharsPerBigit; ++j) {
|
||||
buffer[string_index--] = '0';
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < used_bigits_ - 1; ++i) {
|
||||
Chunk current_bigit = RawBigit(i);
|
||||
for (int j = 0; j < kHexCharsPerBigit; ++j) {
|
||||
buffer[string_index--] = HexCharOfValue(current_bigit & 0xF);
|
||||
current_bigit >>= 4;
|
||||
}
|
||||
}
|
||||
// And finally the last bigit.
|
||||
Chunk most_significant_bigit = RawBigit(used_bigits_ - 1);
|
||||
while (most_significant_bigit != 0) {
|
||||
buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF);
|
||||
most_significant_bigit >>= 4;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Bignum::Chunk Bignum::BigitOrZero(const int index) const {
|
||||
if (index >= BigitLength()) {
|
||||
return 0;
|
||||
}
|
||||
if (index < exponent_) {
|
||||
return 0;
|
||||
}
|
||||
return RawBigit(index - exponent_);
|
||||
}
|
||||
|
||||
int Bignum::Compare(const Bignum& a, const Bignum& b) {
|
||||
DOUBLE_CONVERSION_ASSERT(a.IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(b.IsClamped());
|
||||
const int bigit_length_a = a.BigitLength();
|
||||
const int bigit_length_b = b.BigitLength();
|
||||
if (bigit_length_a < bigit_length_b) {
|
||||
return -1;
|
||||
}
|
||||
if (bigit_length_a > bigit_length_b) {
|
||||
return +1;
|
||||
}
|
||||
for (int i = bigit_length_a - 1; i >= MIN(a.exponent_, b.exponent_); --i) {
|
||||
const Chunk bigit_a = a.BigitOrZero(i);
|
||||
const Chunk bigit_b = b.BigitOrZero(i);
|
||||
if (bigit_a < bigit_b) {
|
||||
return -1;
|
||||
}
|
||||
if (bigit_a > bigit_b) {
|
||||
return +1;
|
||||
}
|
||||
// Otherwise they are equal up to this digit. Try the next digit.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) {
|
||||
DOUBLE_CONVERSION_ASSERT(a.IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(b.IsClamped());
|
||||
DOUBLE_CONVERSION_ASSERT(c.IsClamped());
|
||||
if (a.BigitLength() < b.BigitLength()) {
|
||||
return PlusCompare(b, a, c);
|
||||
}
|
||||
if (a.BigitLength() + 1 < c.BigitLength()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.BigitLength() > c.BigitLength()) {
|
||||
return +1;
|
||||
}
|
||||
// The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than
|
||||
// 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one
|
||||
// of 'a'.
|
||||
if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Chunk borrow = 0;
|
||||
// Starting at min_exponent all digits are == 0. So no need to compare them.
|
||||
const int min_exponent = MIN(MIN(a.exponent_, b.exponent_), c.exponent_);
|
||||
for (int i = c.BigitLength() - 1; i >= min_exponent; --i) {
|
||||
const Chunk chunk_a = a.BigitOrZero(i);
|
||||
const Chunk chunk_b = b.BigitOrZero(i);
|
||||
const Chunk chunk_c = c.BigitOrZero(i);
|
||||
const Chunk sum = chunk_a + chunk_b;
|
||||
if (sum > chunk_c + borrow) {
|
||||
return +1;
|
||||
} else {
|
||||
borrow = chunk_c + borrow - sum;
|
||||
if (borrow > 1) {
|
||||
return -1;
|
||||
}
|
||||
borrow <<= kBigitSize;
|
||||
}
|
||||
}
|
||||
if (borrow == 0) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Bignum::Clamp() {
|
||||
while (used_bigits_ > 0 && RawBigit(used_bigits_ - 1) == 0) {
|
||||
used_bigits_--;
|
||||
}
|
||||
if (used_bigits_ == 0) {
|
||||
// Zero.
|
||||
exponent_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Bignum::Align(const Bignum& other) {
|
||||
if (exponent_ > other.exponent_) {
|
||||
// If "X" represents a "hidden" bigit (by the exponent) then we are in the
|
||||
// following case (a == this, b == other):
|
||||
// a: aaaaaaXXXX or a: aaaaaXXX
|
||||
// b: bbbbbbX b: bbbbbbbbXX
|
||||
// We replace some of the hidden digits (X) of a with 0 digits.
|
||||
// a: aaaaaa000X or a: aaaaa0XX
|
||||
const int zero_bigits = exponent_ - other.exponent_;
|
||||
EnsureCapacity(used_bigits_ + zero_bigits);
|
||||
for (int i = used_bigits_ - 1; i >= 0; --i) {
|
||||
RawBigit(i + zero_bigits) = RawBigit(i);
|
||||
}
|
||||
for (int i = 0; i < zero_bigits; ++i) {
|
||||
RawBigit(i) = 0;
|
||||
}
|
||||
used_bigits_ += zero_bigits;
|
||||
exponent_ -= zero_bigits;
|
||||
|
||||
DOUBLE_CONVERSION_ASSERT(used_bigits_ >= 0);
|
||||
DOUBLE_CONVERSION_ASSERT(exponent_ >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Bignum::BigitsShiftLeft(const int shift_amount) {
|
||||
DOUBLE_CONVERSION_ASSERT(shift_amount < kBigitSize);
|
||||
DOUBLE_CONVERSION_ASSERT(shift_amount >= 0);
|
||||
Chunk carry = 0;
|
||||
for (int i = 0; i < used_bigits_; ++i) {
|
||||
const Chunk new_carry = RawBigit(i) >> (kBigitSize - shift_amount);
|
||||
RawBigit(i) = ((RawBigit(i) << shift_amount) + carry) & kBigitMask;
|
||||
carry = new_carry;
|
||||
}
|
||||
if (carry != 0) {
|
||||
RawBigit(used_bigits_) = carry;
|
||||
used_bigits_++;
|
||||
}
|
||||
}
|
||||
|
||||
void Bignum::SubtractTimes(const Bignum& other, const int factor) {
|
||||
DOUBLE_CONVERSION_ASSERT(exponent_ <= other.exponent_);
|
||||
if (factor < 3) {
|
||||
for (int i = 0; i < factor; ++i) {
|
||||
SubtractBignum(other);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Chunk borrow = 0;
|
||||
const int exponent_diff = other.exponent_ - exponent_;
|
||||
for (int i = 0; i < other.used_bigits_; ++i) {
|
||||
const DoubleChunk product =
|
||||
static_cast<DoubleChunk>(factor) * other.RawBigit(i);
|
||||
const DoubleChunk remove = borrow + product;
|
||||
const Chunk difference =
|
||||
RawBigit(i + exponent_diff) - (remove & kBigitMask);
|
||||
RawBigit(i + exponent_diff) = difference & kBigitMask;
|
||||
borrow = static_cast<Chunk>((difference >> (kChunkSize - 1)) +
|
||||
(remove >> kBigitSize));
|
||||
}
|
||||
for (int i = other.used_bigits_ + exponent_diff; i < used_bigits_; ++i) {
|
||||
if (borrow == 0) {
|
||||
return;
|
||||
}
|
||||
const Chunk difference = RawBigit(i) - borrow;
|
||||
RawBigit(i) = difference & kBigitMask;
|
||||
borrow = difference >> (kChunkSize - 1);
|
||||
}
|
||||
Clamp();
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
153
third_party/double-conversion/bignum.h
vendored
Normal file
153
third_party/double-conversion/bignum.h
vendored
Normal file
|
@ -0,0 +1,153 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_BIGNUM_H_
|
||||
#define DOUBLE_CONVERSION_BIGNUM_H_
|
||||
|
||||
#include "third_party/double-conversion/utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
class Bignum {
|
||||
public:
|
||||
// 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately.
|
||||
// This bignum can encode much bigger numbers, since it contains an
|
||||
// exponent.
|
||||
static const int kMaxSignificantBits = 3584;
|
||||
|
||||
Bignum() : used_bigits_(0), exponent_(0) {}
|
||||
|
||||
void AssignUInt16(const uint16_t value);
|
||||
void AssignUInt64(uint64_t value);
|
||||
void AssignBignum(const Bignum& other);
|
||||
|
||||
void AssignDecimalString(const Vector<const char> value);
|
||||
void AssignHexString(const Vector<const char> value);
|
||||
|
||||
void AssignPowerUInt16(uint16_t base, const int exponent);
|
||||
|
||||
void AddUInt64(const uint64_t operand);
|
||||
void AddBignum(const Bignum& other);
|
||||
// Precondition: this >= other.
|
||||
void SubtractBignum(const Bignum& other);
|
||||
|
||||
void Square();
|
||||
void ShiftLeft(const int shift_amount);
|
||||
void MultiplyByUInt32(const uint32_t factor);
|
||||
void MultiplyByUInt64(const uint64_t factor);
|
||||
void MultiplyByPowerOfTen(const int exponent);
|
||||
void Times10() { return MultiplyByUInt32(10); }
|
||||
// Pseudocode:
|
||||
// int result = this / other;
|
||||
// this = this % other;
|
||||
// In the worst case this function is in O(this/other).
|
||||
uint16_t DivideModuloIntBignum(const Bignum& other);
|
||||
|
||||
bool ToHexString(char* buffer, const int buffer_size) const;
|
||||
|
||||
// Returns
|
||||
// -1 if a < b,
|
||||
// 0 if a == b, and
|
||||
// +1 if a > b.
|
||||
static int Compare(const Bignum& a, const Bignum& b);
|
||||
static bool Equal(const Bignum& a, const Bignum& b) {
|
||||
return Compare(a, b) == 0;
|
||||
}
|
||||
static bool LessEqual(const Bignum& a, const Bignum& b) {
|
||||
return Compare(a, b) <= 0;
|
||||
}
|
||||
static bool Less(const Bignum& a, const Bignum& b) {
|
||||
return Compare(a, b) < 0;
|
||||
}
|
||||
// Returns Compare(a + b, c);
|
||||
static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c);
|
||||
// Returns a + b == c
|
||||
static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) {
|
||||
return PlusCompare(a, b, c) == 0;
|
||||
}
|
||||
// Returns a + b <= c
|
||||
static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) {
|
||||
return PlusCompare(a, b, c) <= 0;
|
||||
}
|
||||
// Returns a + b < c
|
||||
static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) {
|
||||
return PlusCompare(a, b, c) < 0;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef uint32_t Chunk;
|
||||
typedef uint64_t DoubleChunk;
|
||||
|
||||
static const int kChunkSize = sizeof(Chunk) * 8;
|
||||
static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8;
|
||||
// With bigit size of 28 we loose some bits, but a double still fits easily
|
||||
// into two chunks, and more importantly we can use the Comba multiplication.
|
||||
static const int kBigitSize = 28;
|
||||
static const Chunk kBigitMask = (1 << kBigitSize) - 1;
|
||||
// Every instance allocates kBigitLength chunks on the stack. Bignums cannot
|
||||
// grow. There are no checks if the stack-allocated space is sufficient.
|
||||
static const int kBigitCapacity = kMaxSignificantBits / kBigitSize;
|
||||
|
||||
static void EnsureCapacity(const int size) {
|
||||
if (size > kBigitCapacity) {
|
||||
DOUBLE_CONVERSION_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
void Align(const Bignum& other);
|
||||
void Clamp();
|
||||
bool IsClamped() const {
|
||||
return used_bigits_ == 0 || RawBigit(used_bigits_ - 1) != 0;
|
||||
}
|
||||
void Zero() {
|
||||
used_bigits_ = 0;
|
||||
exponent_ = 0;
|
||||
}
|
||||
// Requires this to have enough capacity (no tests done).
|
||||
// Updates used_bigits_ if necessary.
|
||||
// shift_amount must be < kBigitSize.
|
||||
void BigitsShiftLeft(const int shift_amount);
|
||||
// BigitLength includes the "hidden" bigits encoded in the exponent.
|
||||
int BigitLength() const { return used_bigits_ + exponent_; }
|
||||
Chunk& RawBigit(const int index);
|
||||
const Chunk& RawBigit(const int index) const;
|
||||
Chunk BigitOrZero(const int index) const;
|
||||
void SubtractTimes(const Bignum& other, const int factor);
|
||||
|
||||
// The Bignum's value is value(bigits_buffer_) * 2^(exponent_ * kBigitSize),
|
||||
// where the value of the buffer consists of the lower kBigitSize bits of
|
||||
// the first used_bigits_ Chunks in bigits_buffer_, first chunk has lowest
|
||||
// significant bits.
|
||||
int16_t used_bigits_;
|
||||
int16_t exponent_;
|
||||
Chunk bigits_buffer_[kBigitCapacity];
|
||||
|
||||
DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Bignum);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_BIGNUM_H_
|
140
third_party/double-conversion/diy-fp.h
vendored
Normal file
140
third_party/double-conversion/diy-fp.h
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_DIY_FP_H_
|
||||
#define DOUBLE_CONVERSION_DIY_FP_H_
|
||||
|
||||
#include "third_party/double-conversion/utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
// This "Do It Yourself Floating Point" class implements a floating-point number
|
||||
// with a uint64 significand and an int exponent. Normalized DiyFp numbers will
|
||||
// have the most significant bit of the significand set.
|
||||
// Multiplication and Subtraction do not normalize their results.
|
||||
// DiyFp store only non-negative numbers and are not designed to contain special
|
||||
// doubles (NaN and Infinity).
|
||||
class DiyFp {
|
||||
public:
|
||||
static const int kSignificandSize = 64;
|
||||
|
||||
DiyFp() : f_(0), e_(0) {}
|
||||
DiyFp(const uint64_t significand, const int32_t exponent)
|
||||
: f_(significand), e_(exponent) {}
|
||||
|
||||
// this -= other.
|
||||
// The exponents of both numbers must be the same and the significand of this
|
||||
// must be greater or equal than the significand of other.
|
||||
// The result will not be normalized.
|
||||
void Subtract(const DiyFp& other) {
|
||||
DOUBLE_CONVERSION_ASSERT(e_ == other.e_);
|
||||
DOUBLE_CONVERSION_ASSERT(f_ >= other.f_);
|
||||
f_ -= other.f_;
|
||||
}
|
||||
|
||||
// Returns a - b.
|
||||
// The exponents of both numbers must be the same and a must be greater
|
||||
// or equal than b. The result will not be normalized.
|
||||
static DiyFp Minus(const DiyFp& a, const DiyFp& b) {
|
||||
DiyFp result = a;
|
||||
result.Subtract(b);
|
||||
return result;
|
||||
}
|
||||
|
||||
// this *= other.
|
||||
void Multiply(const DiyFp& other) {
|
||||
// Simply "emulates" a 128 bit multiplication.
|
||||
// However: the resulting number only contains 64 bits. The least
|
||||
// significant 64 bits are only used for rounding the most significant 64
|
||||
// bits.
|
||||
const uint64_t kM32 = 0xFFFFFFFFU;
|
||||
const uint64_t a = f_ >> 32;
|
||||
const uint64_t b = f_ & kM32;
|
||||
const uint64_t c = other.f_ >> 32;
|
||||
const uint64_t d = other.f_ & kM32;
|
||||
const uint64_t ac = a * c;
|
||||
const uint64_t bc = b * c;
|
||||
const uint64_t ad = a * d;
|
||||
const uint64_t bd = b * d;
|
||||
// By adding 1U << 31 to tmp we round the final result.
|
||||
// Halfway cases will be rounded up.
|
||||
const uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32) + (1U << 31);
|
||||
e_ += other.e_ + 64;
|
||||
f_ = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
|
||||
}
|
||||
|
||||
// returns a * b;
|
||||
static DiyFp Times(const DiyFp& a, const DiyFp& b) {
|
||||
DiyFp result = a;
|
||||
result.Multiply(b);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Normalize() {
|
||||
DOUBLE_CONVERSION_ASSERT(f_ != 0);
|
||||
uint64_t significand = f_;
|
||||
int32_t exponent = e_;
|
||||
|
||||
// This method is mainly called for normalizing boundaries. In general,
|
||||
// boundaries need to be shifted by 10 bits, and we optimize for this case.
|
||||
const uint64_t k10MSBits =
|
||||
DOUBLE_CONVERSION_UINT64_2PART_C(0xFFC00000, 00000000);
|
||||
while ((significand & k10MSBits) == 0) {
|
||||
significand <<= 10;
|
||||
exponent -= 10;
|
||||
}
|
||||
while ((significand & kUint64MSB) == 0) {
|
||||
significand <<= 1;
|
||||
exponent--;
|
||||
}
|
||||
f_ = significand;
|
||||
e_ = exponent;
|
||||
}
|
||||
|
||||
static DiyFp Normalize(const DiyFp& a) {
|
||||
DiyFp result = a;
|
||||
result.Normalize();
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t f() const { return f_; }
|
||||
int32_t e() const { return e_; }
|
||||
|
||||
void set_f(uint64_t new_value) { f_ = new_value; }
|
||||
void set_e(int32_t new_value) { e_ = new_value; }
|
||||
|
||||
private:
|
||||
static const uint64_t kUint64MSB =
|
||||
DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000000);
|
||||
|
||||
uint64_t f_;
|
||||
int32_t e_;
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_DIY_FP_H_
|
54
third_party/double-conversion/double-conversion.mk
vendored
Normal file
54
third_party/double-conversion/double-conversion.mk
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += THIRD_PARTY_DOUBLE_CONVERSION
|
||||
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_ARTIFACTS += THIRD_PARTY_DOUBLE_CONVERSION_A
|
||||
THIRD_PARTY_DOUBLE_CONVERSION = $(THIRD_PARTY_DOUBLE_CONVERSION_A_DEPS) $(THIRD_PARTY_DOUBLE_CONVERSION_A)
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_A = o/$(MODE)/third_party/double-conversion/double-conversion.a
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_A_FILES := $(wildcard third_party/double-conversion/*)
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_A_HDRS = $(filter %.h,$(THIRD_PARTY_DOUBLE_CONVERSION_A_FILES))
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_A_SRCS_CC = $(filter %.cc,$(THIRD_PARTY_DOUBLE_CONVERSION_A_FILES))
|
||||
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_A_SRCS = \
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_A_SRCS_CC)
|
||||
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_A_OBJS = \
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_A_SRCS_CC:%.cc=o/$(MODE)/%.o)
|
||||
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_A_CHECKS = \
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_A).pkg \
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_A_DIRECTDEPS = \
|
||||
LIBC_STUBS
|
||||
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(THIRD_PARTY_DOUBLE_CONVERSION_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_A): \
|
||||
third_party/double-conversion/ \
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_A).pkg \
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_A_OBJS)
|
||||
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_A).pkg: \
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_A_OBJS) \
|
||||
$(foreach x,$(THIRD_PARTY_DOUBLE_CONVERSION_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_A_OBJS): \
|
||||
OVERRIDE_CXXFLAGS += \
|
||||
$(IEEE_MATH) \
|
||||
-fvisibility=hidden \
|
||||
-ffunction-sections \
|
||||
-fdata-sections
|
||||
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_LIBS = $(foreach x,$(THIRD_PARTY_DOUBLE_CONVERSION_ARTIFACTS),$($(x)))
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_SRCS = $(foreach x,$(THIRD_PARTY_DOUBLE_CONVERSION_ARTIFACTS),$($(x)_SRCS))
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_HDRS = $(foreach x,$(THIRD_PARTY_DOUBLE_CONVERSION_ARTIFACTS),$($(x)_HDRS))
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_CHECKS = $(foreach x,$(THIRD_PARTY_DOUBLE_CONVERSION_ARTIFACTS),$($(x)_CHECKS))
|
||||
THIRD_PARTY_DOUBLE_CONVERSION_OBJS = $(foreach x,$(THIRD_PARTY_DOUBLE_CONVERSION_ARTIFACTS),$($(x)_OBJS))
|
||||
$(THIRD_PARTY_DOUBLE_CONVERSION_OBJS): $(BUILD_FILES) third_party/double-conversion/double-conversion.mk
|
||||
|
||||
.PHONY: o/$(MODE)/third_party/double-conversion
|
||||
o/$(MODE)/third_party/double-conversion: $(THIRD_PARTY_DOUBLE_CONVERSION_CHECKS)
|
395
third_party/double-conversion/ieee.h
vendored
Normal file
395
third_party/double-conversion/ieee.h
vendored
Normal file
|
@ -0,0 +1,395 @@
|
|||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_DOUBLE_H_
|
||||
#define DOUBLE_CONVERSION_DOUBLE_H_
|
||||
|
||||
#include "third_party/double-conversion/diy-fp.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
// We assume that doubles and uint64_t have the same endianness.
|
||||
static uint64_t double_to_uint64(double d) { return BitCast<uint64_t>(d); }
|
||||
static double uint64_to_double(uint64_t d64) { return BitCast<double>(d64); }
|
||||
static uint32_t float_to_uint32(float f) { return BitCast<uint32_t>(f); }
|
||||
static float uint32_to_float(uint32_t d32) { return BitCast<float>(d32); }
|
||||
|
||||
// Helper functions for doubles.
|
||||
class Double {
|
||||
public:
|
||||
static const uint64_t kSignMask =
|
||||
DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000000);
|
||||
static const uint64_t kExponentMask =
|
||||
DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF00000, 00000000);
|
||||
static const uint64_t kSignificandMask =
|
||||
DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
|
||||
static const uint64_t kHiddenBit =
|
||||
DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000);
|
||||
static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
|
||||
static const int kSignificandSize = 53;
|
||||
static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
|
||||
static const int kMaxExponent = 0x7FF - kExponentBias;
|
||||
|
||||
Double() : d64_(0) {}
|
||||
explicit Double(double d) : d64_(double_to_uint64(d)) {}
|
||||
explicit Double(uint64_t d64) : d64_(d64) {}
|
||||
explicit Double(DiyFp diy_fp) : d64_(DiyFpToUint64(diy_fp)) {}
|
||||
|
||||
// The value encoded by this Double must be greater or equal to +0.0.
|
||||
// It must not be special (infinity, or NaN).
|
||||
DiyFp AsDiyFp() const {
|
||||
DOUBLE_CONVERSION_ASSERT(Sign() > 0);
|
||||
DOUBLE_CONVERSION_ASSERT(!IsSpecial());
|
||||
return DiyFp(Significand(), Exponent());
|
||||
}
|
||||
|
||||
// The value encoded by this Double must be strictly greater than 0.
|
||||
DiyFp AsNormalizedDiyFp() const {
|
||||
DOUBLE_CONVERSION_ASSERT(value() > 0.0);
|
||||
uint64_t f = Significand();
|
||||
int e = Exponent();
|
||||
|
||||
// The current double could be a denormal.
|
||||
while ((f & kHiddenBit) == 0) {
|
||||
f <<= 1;
|
||||
e--;
|
||||
}
|
||||
// Do the final shifts in one go.
|
||||
f <<= DiyFp::kSignificandSize - kSignificandSize;
|
||||
e -= DiyFp::kSignificandSize - kSignificandSize;
|
||||
return DiyFp(f, e);
|
||||
}
|
||||
|
||||
// Returns the double's bit as uint64.
|
||||
uint64_t AsUint64() const { return d64_; }
|
||||
|
||||
// Returns the next greater double. Returns +infinity on input +infinity.
|
||||
double NextDouble() const {
|
||||
if (d64_ == kInfinity) return Double(kInfinity).value();
|
||||
if (Sign() < 0 && Significand() == 0) {
|
||||
// -0.0
|
||||
return 0.0;
|
||||
}
|
||||
if (Sign() < 0) {
|
||||
return Double(d64_ - 1).value();
|
||||
} else {
|
||||
return Double(d64_ + 1).value();
|
||||
}
|
||||
}
|
||||
|
||||
double PreviousDouble() const {
|
||||
if (d64_ == (kInfinity | kSignMask)) return -Infinity();
|
||||
if (Sign() < 0) {
|
||||
return Double(d64_ + 1).value();
|
||||
} else {
|
||||
if (Significand() == 0) return -0.0;
|
||||
return Double(d64_ - 1).value();
|
||||
}
|
||||
}
|
||||
|
||||
int Exponent() const {
|
||||
if (IsDenormal()) return kDenormalExponent;
|
||||
|
||||
uint64_t d64 = AsUint64();
|
||||
int biased_e =
|
||||
static_cast<int>((d64 & kExponentMask) >> kPhysicalSignificandSize);
|
||||
return biased_e - kExponentBias;
|
||||
}
|
||||
|
||||
uint64_t Significand() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
uint64_t significand = d64 & kSignificandMask;
|
||||
if (!IsDenormal()) {
|
||||
return significand + kHiddenBit;
|
||||
} else {
|
||||
return significand;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the double is a denormal.
|
||||
bool IsDenormal() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
return (d64 & kExponentMask) == 0;
|
||||
}
|
||||
|
||||
// We consider denormals not to be special.
|
||||
// Hence only Infinity and NaN are special.
|
||||
bool IsSpecial() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
return (d64 & kExponentMask) == kExponentMask;
|
||||
}
|
||||
|
||||
bool IsNan() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
return ((d64 & kExponentMask) == kExponentMask) &&
|
||||
((d64 & kSignificandMask) != 0);
|
||||
}
|
||||
|
||||
bool IsInfinite() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
return ((d64 & kExponentMask) == kExponentMask) &&
|
||||
((d64 & kSignificandMask) == 0);
|
||||
}
|
||||
|
||||
int Sign() const {
|
||||
uint64_t d64 = AsUint64();
|
||||
return (d64 & kSignMask) == 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
// Precondition: the value encoded by this Double must be greater or equal
|
||||
// than +0.0.
|
||||
DiyFp UpperBoundary() const {
|
||||
DOUBLE_CONVERSION_ASSERT(Sign() > 0);
|
||||
return DiyFp(Significand() * 2 + 1, Exponent() - 1);
|
||||
}
|
||||
|
||||
// Computes the two boundaries of this.
|
||||
// The bigger boundary (m_plus) is normalized. The lower boundary has the same
|
||||
// exponent as m_plus.
|
||||
// Precondition: the value encoded by this Double must be greater than 0.
|
||||
void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
|
||||
DOUBLE_CONVERSION_ASSERT(value() > 0.0);
|
||||
DiyFp v = this->AsDiyFp();
|
||||
DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
|
||||
DiyFp m_minus;
|
||||
if (LowerBoundaryIsCloser()) {
|
||||
m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
|
||||
} else {
|
||||
m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
|
||||
}
|
||||
m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
|
||||
m_minus.set_e(m_plus.e());
|
||||
*out_m_plus = m_plus;
|
||||
*out_m_minus = m_minus;
|
||||
}
|
||||
|
||||
bool LowerBoundaryIsCloser() const {
|
||||
// The boundary is closer if the significand is of the form f == 2^p-1 then
|
||||
// the lower boundary is closer.
|
||||
// Think of v = 1000e10 and v- = 9999e9.
|
||||
// Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
|
||||
// at a distance of 1e8.
|
||||
// The only exception is for the smallest normal: the largest denormal is
|
||||
// at the same distance as its successor.
|
||||
// Note: denormals have the same exponent as the smallest normals.
|
||||
bool physical_significand_is_zero = ((AsUint64() & kSignificandMask) == 0);
|
||||
return physical_significand_is_zero && (Exponent() != kDenormalExponent);
|
||||
}
|
||||
|
||||
double value() const { return uint64_to_double(d64_); }
|
||||
|
||||
// Returns the significand size for a given order of magnitude.
|
||||
// If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude.
|
||||
// This function returns the number of significant binary digits v will have
|
||||
// once it's encoded into a double. In almost all cases this is equal to
|
||||
// kSignificandSize. The only exceptions are denormals. They start with
|
||||
// leading zeroes and their effective significand-size is hence smaller.
|
||||
static int SignificandSizeForOrderOfMagnitude(int order) {
|
||||
if (order >= (kDenormalExponent + kSignificandSize)) {
|
||||
return kSignificandSize;
|
||||
}
|
||||
if (order <= kDenormalExponent) return 0;
|
||||
return order - kDenormalExponent;
|
||||
}
|
||||
|
||||
static double Infinity() { return Double(kInfinity).value(); }
|
||||
|
||||
static double NaN() { return Double(kNaN).value(); }
|
||||
|
||||
private:
|
||||
static const int kDenormalExponent = -kExponentBias + 1;
|
||||
static const uint64_t kInfinity =
|
||||
DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF00000, 00000000);
|
||||
static const uint64_t kNaN =
|
||||
DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF80000, 00000000);
|
||||
|
||||
const uint64_t d64_;
|
||||
|
||||
static uint64_t DiyFpToUint64(DiyFp diy_fp) {
|
||||
uint64_t significand = diy_fp.f();
|
||||
int exponent = diy_fp.e();
|
||||
while (significand > kHiddenBit + kSignificandMask) {
|
||||
significand >>= 1;
|
||||
exponent++;
|
||||
}
|
||||
if (exponent >= kMaxExponent) {
|
||||
return kInfinity;
|
||||
}
|
||||
if (exponent < kDenormalExponent) {
|
||||
return 0;
|
||||
}
|
||||
while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) {
|
||||
significand <<= 1;
|
||||
exponent--;
|
||||
}
|
||||
uint64_t biased_exponent;
|
||||
if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) {
|
||||
biased_exponent = 0;
|
||||
} else {
|
||||
biased_exponent = static_cast<uint64_t>(exponent + kExponentBias);
|
||||
}
|
||||
return (significand & kSignificandMask) |
|
||||
(biased_exponent << kPhysicalSignificandSize);
|
||||
}
|
||||
|
||||
DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Double);
|
||||
};
|
||||
|
||||
class Single {
|
||||
public:
|
||||
static const uint32_t kSignMask = 0x80000000;
|
||||
static const uint32_t kExponentMask = 0x7F800000;
|
||||
static const uint32_t kSignificandMask = 0x007FFFFF;
|
||||
static const uint32_t kHiddenBit = 0x00800000;
|
||||
static const int kPhysicalSignificandSize = 23; // Excludes the hidden bit.
|
||||
static const int kSignificandSize = 24;
|
||||
|
||||
Single() : d32_(0) {}
|
||||
explicit Single(float f) : d32_(float_to_uint32(f)) {}
|
||||
explicit Single(uint32_t d32) : d32_(d32) {}
|
||||
|
||||
// The value encoded by this Single must be greater or equal to +0.0.
|
||||
// It must not be special (infinity, or NaN).
|
||||
DiyFp AsDiyFp() const {
|
||||
DOUBLE_CONVERSION_ASSERT(Sign() > 0);
|
||||
DOUBLE_CONVERSION_ASSERT(!IsSpecial());
|
||||
return DiyFp(Significand(), Exponent());
|
||||
}
|
||||
|
||||
// Returns the single's bit as uint64.
|
||||
uint32_t AsUint32() const { return d32_; }
|
||||
|
||||
int Exponent() const {
|
||||
if (IsDenormal()) return kDenormalExponent;
|
||||
|
||||
uint32_t d32 = AsUint32();
|
||||
int biased_e =
|
||||
static_cast<int>((d32 & kExponentMask) >> kPhysicalSignificandSize);
|
||||
return biased_e - kExponentBias;
|
||||
}
|
||||
|
||||
uint32_t Significand() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
uint32_t significand = d32 & kSignificandMask;
|
||||
if (!IsDenormal()) {
|
||||
return significand + kHiddenBit;
|
||||
} else {
|
||||
return significand;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the single is a denormal.
|
||||
bool IsDenormal() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
return (d32 & kExponentMask) == 0;
|
||||
}
|
||||
|
||||
// We consider denormals not to be special.
|
||||
// Hence only Infinity and NaN are special.
|
||||
bool IsSpecial() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
return (d32 & kExponentMask) == kExponentMask;
|
||||
}
|
||||
|
||||
bool IsNan() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
return ((d32 & kExponentMask) == kExponentMask) &&
|
||||
((d32 & kSignificandMask) != 0);
|
||||
}
|
||||
|
||||
bool IsInfinite() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
return ((d32 & kExponentMask) == kExponentMask) &&
|
||||
((d32 & kSignificandMask) == 0);
|
||||
}
|
||||
|
||||
int Sign() const {
|
||||
uint32_t d32 = AsUint32();
|
||||
return (d32 & kSignMask) == 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
// Computes the two boundaries of this.
|
||||
// The bigger boundary (m_plus) is normalized. The lower boundary has the same
|
||||
// exponent as m_plus.
|
||||
// Precondition: the value encoded by this Single must be greater than 0.
|
||||
void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
|
||||
DOUBLE_CONVERSION_ASSERT(value() > 0.0);
|
||||
DiyFp v = this->AsDiyFp();
|
||||
DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
|
||||
DiyFp m_minus;
|
||||
if (LowerBoundaryIsCloser()) {
|
||||
m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
|
||||
} else {
|
||||
m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
|
||||
}
|
||||
m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
|
||||
m_minus.set_e(m_plus.e());
|
||||
*out_m_plus = m_plus;
|
||||
*out_m_minus = m_minus;
|
||||
}
|
||||
|
||||
// Precondition: the value encoded by this Single must be greater or equal
|
||||
// than +0.0.
|
||||
DiyFp UpperBoundary() const {
|
||||
DOUBLE_CONVERSION_ASSERT(Sign() > 0);
|
||||
return DiyFp(Significand() * 2 + 1, Exponent() - 1);
|
||||
}
|
||||
|
||||
bool LowerBoundaryIsCloser() const {
|
||||
// The boundary is closer if the significand is of the form f == 2^p-1 then
|
||||
// the lower boundary is closer.
|
||||
// Think of v = 1000e10 and v- = 9999e9.
|
||||
// Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
|
||||
// at a distance of 1e8.
|
||||
// The only exception is for the smallest normal: the largest denormal is
|
||||
// at the same distance as its successor.
|
||||
// Note: denormals have the same exponent as the smallest normals.
|
||||
bool physical_significand_is_zero = ((AsUint32() & kSignificandMask) == 0);
|
||||
return physical_significand_is_zero && (Exponent() != kDenormalExponent);
|
||||
}
|
||||
|
||||
float value() const { return uint32_to_float(d32_); }
|
||||
|
||||
static float Infinity() { return Single(kInfinity).value(); }
|
||||
|
||||
static float NaN() { return Single(kNaN).value(); }
|
||||
|
||||
private:
|
||||
static const int kExponentBias = 0x7F + kPhysicalSignificandSize;
|
||||
static const int kDenormalExponent = -kExponentBias + 1;
|
||||
static const int kMaxExponent = 0xFF - kExponentBias;
|
||||
static const uint32_t kInfinity = 0x7F800000;
|
||||
static const uint32_t kNaN = 0x7FC00000;
|
||||
|
||||
const uint32_t d32_;
|
||||
|
||||
DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(Single);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_DOUBLE_H_
|
308
third_party/double-conversion/utils.h
vendored
Normal file
308
third_party/double-conversion/utils.h
vendored
Normal file
|
@ -0,0 +1,308 @@
|
|||
#ifndef DOUBLE_CONVERSION_UTILS_H_
|
||||
#define DOUBLE_CONVERSION_UTILS_H_
|
||||
#include "libc/assert.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_ASSERT
|
||||
#define DOUBLE_CONVERSION_ASSERT(condition) assert(condition);
|
||||
#endif
|
||||
#ifndef DOUBLE_CONVERSION_UNIMPLEMENTED
|
||||
#define DOUBLE_CONVERSION_UNIMPLEMENTED() (abort())
|
||||
#endif
|
||||
#ifndef DOUBLE_CONVERSION_NO_RETURN
|
||||
#ifdef _MSC_VER
|
||||
#define DOUBLE_CONVERSION_NO_RETURN __declspec(noreturn)
|
||||
#else
|
||||
#define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn))
|
||||
#endif
|
||||
#endif
|
||||
#ifndef DOUBLE_CONVERSION_UNREACHABLE
|
||||
#ifdef _MSC_VER
|
||||
void DOUBLE_CONVERSION_NO_RETURN abort_noreturn();
|
||||
inline void abort_noreturn() { abort(); }
|
||||
#define DOUBLE_CONVERSION_UNREACHABLE() (abort_noreturn())
|
||||
#else
|
||||
#define DOUBLE_CONVERSION_UNREACHABLE() (abort())
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_UNUSED
|
||||
#ifdef __GNUC__
|
||||
#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
|
||||
#else
|
||||
#define DOUBLE_CONVERSION_UNUSED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Double operations detection based on target architecture.
|
||||
// Linux uses a 80bit wide floating point stack on x86. This induces double
|
||||
// rounding, which in turn leads to wrong results.
|
||||
// An easy way to test if the floating-point operations are correct is to
|
||||
// evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then
|
||||
// the result is equal to 89255e-22.
|
||||
// The best way to test this, is to create a division-function and to compare
|
||||
// the output of the division with the expected result. (Inlining must be
|
||||
// disabled.)
|
||||
// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
|
||||
//
|
||||
// For example:
|
||||
/*
|
||||
// -- in div.c
|
||||
double Div_double(double x, double y) { return x / y; }
|
||||
|
||||
// -- in main.c
|
||||
double Div_double(double x, double y); // Forward declaration.
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return Div_double(89255.0, 1e22) == 89255e-22;
|
||||
}
|
||||
*/
|
||||
// Run as follows ./main || echo "correct"
|
||||
//
|
||||
// If it prints "correct" then the architecture should be here, in the "correct"
|
||||
// section.
|
||||
#if defined(_M_X64) || defined(__x86_64__) || defined(__ARMEL__) || \
|
||||
defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
|
||||
defined(__hppa__) || defined(__ia64__) || defined(__mips__) || \
|
||||
defined(__nios2__) || defined(__powerpc__) || defined(__ppc__) || \
|
||||
defined(__ppc64__) || defined(_POWER) || defined(_ARCH_PPC) || \
|
||||
defined(_ARCH_PPC64) || defined(__sparc__) || defined(__sparc) || \
|
||||
defined(__s390__) || defined(__SH4__) || defined(__alpha__) || \
|
||||
defined(_MIPS_ARCH_MIPS32R2) || defined(__ARMEB__) || \
|
||||
defined(__AARCH64EL__) || defined(__aarch64__) || \
|
||||
defined(__AARCH64EB__) || defined(__riscv) || defined(__e2k__) || \
|
||||
defined(__or1k__) || defined(__arc__) || defined(__microblaze__) || \
|
||||
defined(__XTENSA__) || defined(__EMSCRIPTEN__) || defined(__wasm32__)
|
||||
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
|
||||
#elif defined(__mc68000__) || defined(__pnacl__) || defined(__native_client__)
|
||||
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
|
||||
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
|
||||
#if defined(_WIN32)
|
||||
// Windows uses a 64bit wide floating point stack.
|
||||
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
|
||||
#else
|
||||
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
|
||||
#endif // _WIN32
|
||||
#else
|
||||
#error Target architecture was not detected as supported by Double-Conversion.
|
||||
#endif
|
||||
|
||||
typedef uint16_t uc16;
|
||||
|
||||
// The following macro works on both 32 and 64-bit platforms.
|
||||
// Usage: instead of writing 0x1234567890123456
|
||||
// write DOUBLE_CONVERSION_UINT64_2PART_C(0x12345678,90123456);
|
||||
#define DOUBLE_CONVERSION_UINT64_2PART_C(a, b) \
|
||||
(((static_cast<uint64_t>(a) << 32) + 0x##b##u))
|
||||
|
||||
// The expression DOUBLE_CONVERSION_ARRAY_SIZE(a) is a compile-time constant of
|
||||
// type size_t which represents the number of elements of the given array. You
|
||||
// should only use DOUBLE_CONVERSION_ARRAY_SIZE on statically allocated arrays.
|
||||
#ifndef DOUBLE_CONVERSION_ARRAY_SIZE
|
||||
#define DOUBLE_CONVERSION_ARRAY_SIZE(a) \
|
||||
((sizeof(a) / sizeof(*(a))) / \
|
||||
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
|
||||
#endif
|
||||
|
||||
// A macro to disallow the evil copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#ifndef DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN
|
||||
#define DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
#endif
|
||||
|
||||
// A macro to disallow all the implicit constructors, namely the
|
||||
// default constructor, copy constructor and operator= functions.
|
||||
//
|
||||
// This should be used in the private: declarations for a class
|
||||
// that wants to prevent anyone from instantiating it. This is
|
||||
// especially useful for classes containing only static methods.
|
||||
#ifndef DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
#define DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName(); \
|
||||
DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
#endif
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
inline int StrLength(const char* string) {
|
||||
size_t length = strlen(string);
|
||||
DOUBLE_CONVERSION_ASSERT(length ==
|
||||
static_cast<size_t>(static_cast<int>(length)));
|
||||
return static_cast<int>(length);
|
||||
}
|
||||
|
||||
// This is a simplified version of V8's Vector class.
|
||||
template <typename T>
|
||||
class Vector {
|
||||
public:
|
||||
Vector() : start_(NULL), length_(0) {}
|
||||
Vector(T* data, int len) : start_(data), length_(len) {
|
||||
DOUBLE_CONVERSION_ASSERT(len == 0 || (len > 0 && data != NULL));
|
||||
}
|
||||
|
||||
// Returns a vector using the same backing storage as this one,
|
||||
// spanning from and including 'from', to but not including 'to'.
|
||||
Vector<T> SubVector(int from, int to) {
|
||||
DOUBLE_CONVERSION_ASSERT(to <= length_);
|
||||
DOUBLE_CONVERSION_ASSERT(from < to);
|
||||
DOUBLE_CONVERSION_ASSERT(0 <= from);
|
||||
return Vector<T>(start() + from, to - from);
|
||||
}
|
||||
|
||||
// Returns the length of the vector.
|
||||
int length() const { return length_; }
|
||||
|
||||
// Returns whether or not the vector is empty.
|
||||
bool is_empty() const { return length_ == 0; }
|
||||
|
||||
// Returns the pointer to the start of the data in the vector.
|
||||
T* start() const { return start_; }
|
||||
|
||||
// Access individual vector elements - checks bounds in debug mode.
|
||||
T& operator[](int index) const {
|
||||
DOUBLE_CONVERSION_ASSERT(0 <= index && index < length_);
|
||||
return start_[index];
|
||||
}
|
||||
|
||||
T& first() { return start_[0]; }
|
||||
|
||||
T& last() { return start_[length_ - 1]; }
|
||||
|
||||
void pop_back() {
|
||||
DOUBLE_CONVERSION_ASSERT(!is_empty());
|
||||
--length_;
|
||||
}
|
||||
|
||||
private:
|
||||
T* start_;
|
||||
int length_;
|
||||
};
|
||||
|
||||
// Helper class for building result strings in a character buffer. The
|
||||
// purpose of the class is to use safe operations that checks the
|
||||
// buffer bounds on all operations in debug mode.
|
||||
class StringBuilder {
|
||||
public:
|
||||
StringBuilder(char* buffer, int buffer_size)
|
||||
: buffer_(buffer, buffer_size), position_(0) {}
|
||||
|
||||
~StringBuilder() {
|
||||
if (!is_finalized()) Finalize();
|
||||
}
|
||||
|
||||
int size() const { return buffer_.length(); }
|
||||
|
||||
// Get the current position in the builder.
|
||||
int position() const {
|
||||
DOUBLE_CONVERSION_ASSERT(!is_finalized());
|
||||
return position_;
|
||||
}
|
||||
|
||||
// Reset the position.
|
||||
void Reset() { position_ = 0; }
|
||||
|
||||
// Add a single character to the builder. It is not allowed to add
|
||||
// 0-characters; use the Finalize() method to terminate the string
|
||||
// instead.
|
||||
void AddCharacter(char c) {
|
||||
DOUBLE_CONVERSION_ASSERT(c != '\0');
|
||||
DOUBLE_CONVERSION_ASSERT(!is_finalized() && position_ < buffer_.length());
|
||||
buffer_[position_++] = c;
|
||||
}
|
||||
|
||||
// Add an entire string to the builder. Uses strlen() internally to
|
||||
// compute the length of the input string.
|
||||
void AddString(const char* s) { AddSubstring(s, StrLength(s)); }
|
||||
|
||||
// Add the first 'n' characters of the given string 's' to the
|
||||
// builder. The input string must have enough characters.
|
||||
void AddSubstring(const char* s, int n) {
|
||||
DOUBLE_CONVERSION_ASSERT(!is_finalized() &&
|
||||
position_ + n < buffer_.length());
|
||||
DOUBLE_CONVERSION_ASSERT(static_cast<size_t>(n) <= strlen(s));
|
||||
__builtin_memmove(&buffer_[position_], s, n);
|
||||
position_ += n;
|
||||
}
|
||||
|
||||
// Add character padding to the builder. If count is non-positive,
|
||||
// nothing is added to the builder.
|
||||
void AddPadding(char c, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
AddCharacter(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize the string by 0-terminating it and returning the buffer.
|
||||
char* Finalize() {
|
||||
DOUBLE_CONVERSION_ASSERT(!is_finalized() && position_ < buffer_.length());
|
||||
buffer_[position_] = '\0';
|
||||
// Make sure nobody managed to add a 0-character to the
|
||||
// buffer while building the string.
|
||||
DOUBLE_CONVERSION_ASSERT(strlen(buffer_.start()) ==
|
||||
static_cast<size_t>(position_));
|
||||
position_ = -1;
|
||||
DOUBLE_CONVERSION_ASSERT(is_finalized());
|
||||
return buffer_.start();
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<char> buffer_;
|
||||
int position_;
|
||||
|
||||
bool is_finalized() const { return position_ < 0; }
|
||||
|
||||
DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
|
||||
};
|
||||
|
||||
// The type-based aliasing rule allows the compiler to assume that pointers of
|
||||
// different types (for some definition of different) never alias each other.
|
||||
// Thus the following code does not work:
|
||||
//
|
||||
// float f = foo();
|
||||
// int fbits = *(int*)(&f);
|
||||
//
|
||||
// The compiler 'knows' that the int pointer can't refer to f since the types
|
||||
// don't match, so the compiler may cache f in a register, leaving random data
|
||||
// in fbits. Using C++ style casts makes no difference, however a pointer to
|
||||
// char data is assumed to alias any other pointer. This is the 'memcpy
|
||||
// exception'.
|
||||
//
|
||||
// Bit_cast uses the memcpy exception to move the bits from a variable of one
|
||||
// type of a variable of another type. Of course the end result is likely to
|
||||
// be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005)
|
||||
// will completely optimize BitCast away.
|
||||
//
|
||||
// There is an additional use for BitCast.
|
||||
// Recent gccs will warn when they see casts that may result in breakage due to
|
||||
// the type-based aliasing rule. If you have checked that there is no breakage
|
||||
// you can use BitCast to cast one pointer type to another. This confuses gcc
|
||||
// enough that it can no longer see that you have cast one pointer type to
|
||||
// another thus avoiding the warning.
|
||||
template <class Dest, class Source>
|
||||
Dest BitCast(const Source& source) {
|
||||
// Compile time assertion: sizeof(Dest) == sizeof(Source)
|
||||
// A compile error here means your Dest and Source have different sizes.
|
||||
#if __cplusplus >= 201103L
|
||||
static_assert(sizeof(Dest) == sizeof(Source));
|
||||
#else
|
||||
DOUBLE_CONVERSION_UNUSED
|
||||
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
|
||||
#endif
|
||||
|
||||
Dest dest;
|
||||
memmove(&dest, &source, sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
|
||||
template <class Dest, class Source>
|
||||
Dest BitCast(Source* source) {
|
||||
return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_UTILS_H_
|
Loading…
Add table
Add a link
Reference in a new issue