/** @file
* @brief Conversion between Coord and strings
*//*
* Authors:
* Krzysztof KosiĆski <tweenk.pl@gmail.com>
*
* Copyright 2014 Authors
*
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*/
// Most of the code in this file is derived from:
// The copyright notice for that code is attached below.
//
// 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
// 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 <stdint.h>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <climits>
#include <cstdarg>
#include <cmath>
#ifndef ASSERT
#endif
#ifndef UNIMPLEMENTED
#endif
#ifndef UNREACHABLE
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) \
((sizeof(a) / sizeof(*(a))) / \
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
#endif
#ifndef DISALLOW_COPY_AND_ASSIGN
void operator=(const TypeName&)
#endif
#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
TypeName(); \
#endif
#if defined(__GNUC__)
#else
#define DOUBLE_CONVERSION_UNUSED
#endif
namespace Geom {
namespace {
template <typename T>
class Vector {
public:
}
}
T& operator[](int index) const {
}
private:
T* start_;
int length_;
};
return dest;
}
}
// We assume that doubles and uint64_t have the same endianness.
// This "Do It Yourself Floating Point" class
class DiyFp {
public:
static const int kSignificandSize = 64;
}
return result;
}
// By adding 1U << 31 to tmp we round the final result.
// Halfway cases will be round up.
}
return result;
}
void Normalize() {
int e = e_;
while ((f & k10MSBits) == 0) {
f <<= 10;
e -= 10;
}
while ((f & kUint64MSB) == 0) {
f <<= 1;
e--;
}
f_ = f;
e_ = e;
}
return result;
}
int e() const { return e_; }
private:
int e_;
};
class Double {
public:
static const int kSignificandSize = 53;
}
DiyFp AsNormalizedDiyFp() const {
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.
return DiyFp(f, e);
}
return d64_;
}
double NextDouble() const {
if (Sign() < 0 && Significand() == 0) {
// -0.0
return 0.0;
}
if (Sign() < 0) {
} else {
}
}
double PreviousDouble() const {
if (Sign() < 0) {
} else {
if (Significand() == 0) return -0.0;
}
}
int Exponent() const {
if (IsDenormal()) return kDenormalExponent;
int biased_e =
return biased_e - kExponentBias;
}
uint64_t Significand() const {
if (!IsDenormal()) {
return significand + kHiddenBit;
} else {
return significand;
}
}
bool IsDenormal() const {
return (d64 & kExponentMask) == 0;
}
// We consider denormals not to be special.
// Hence only Infinity and NaN are special.
bool IsSpecial() const {
}
bool IsNan() const {
((d64 & kSignificandMask) != 0);
}
bool IsInfinite() const {
((d64 & kSignificandMask) == 0);
}
int Sign() const {
}
DiyFp UpperBoundary() const {
}
if (LowerBoundaryIsCloser()) {
} else {
}
*out_m_plus = m_plus;
*out_m_minus = m_minus;
}
bool LowerBoundaryIsCloser() const {
}
static int SignificandSizeForOrderOfMagnitude(int order) {
return kSignificandSize;
}
if (order <= kDenormalExponent) return 0;
return order - kDenormalExponent;
}
static double Infinity() {
}
static double NaN() {
}
private:
significand >>= 1;
exponent++;
}
if (exponent >= kMaxExponent) {
return kInfinity;
}
if (exponent < kDenormalExponent) {
return 0;
}
significand <<= 1;
exponent--;
}
biased_exponent = 0;
} else {
}
return (significand & kSignificandMask) |
}
};
template<typename S>
(void) value; // Mark variable as used.
return 8 * sizeof(value);
}
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()
{
for (int i = 0; i < kBigitCapacity; ++i) {
bigits_[i] = 0;
}
}
Zero();
if (value == 0) return;
EnsureCapacity(1);
used_digits_ = 1;
}
const int kUInt64Size = 64;
Zero();
if (value == 0) return;
for (int i = 0; i < needed_bigits; ++i) {
}
Clamp();
}
for (int i = 0; i < other.used_digits_; ++i) {
}
// Clear the excess digits (if there were any).
bigits_[i] = 0;
}
}
// Precondition: this >= other.
void Square();
void ShiftLeft(int shift_amount);
void MultiplyByPowerOfTen(int exponent);
// Pseudocode:
// int result = this / other;
// this = this % other;
// Returns
// -1 if a < b,
// 0 if a == b, and
// +1 if a > b.
return Compare(a, b) == 0;
}
return Compare(a, b) <= 0;
}
return Compare(a, b) < 0;
}
// Returns Compare(a + b, c);
// Returns a + b == c
return PlusCompare(a, b, c) == 0;
}
// Returns a + b <= c
return PlusCompare(a, b, c) <= 0;
}
// Returns a + b < c
return PlusCompare(a, b, c) < 0;
}
private:
typedef uint64_t DoubleChunk;
// 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;
// Every instance allocates kBigitLength chunks on the stack. Bignums cannot
// grow. There are no checks if the stack-allocated space is sufficient.
void EnsureCapacity(int size) {
if (size > kBigitCapacity) {
UNREACHABLE();
}
}
void Clamp();
bool IsClamped() const;
void Zero();
// Requires this to have enough capacity (no tests done).
// Updates used_digits_ if necessary.
// shift_amount must be < kBigitSize.
void BigitsShiftLeft(int shift_amount);
// BigitLength includes the "hidden" digits encoded in the exponent.
// A vector backed by bigits_buffer_. This way accesses to the array are
// checked for out-of-bounds errors.
int used_digits_;
// The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
int exponent_;
};
int from,
int digits_to_read) {
}
return result;
}
// 2^64 = 18446744073709551616 > 10^19
const int kMaxUint64DecimalDigits = 19;
Zero();
int pos = 0;
// Let's just say that each digit needs 4 bits.
while (length >= kMaxUint64DecimalDigits) {
}
Clamp();
}
static int HexCharValue(char c) {
if ('0' <= c && c <= '9') return c - '0';
if ('a' <= c && c <= 'f') return 10 + c - 'a';
return 10 + c - 'A';
}
Zero();
for (int i = 0; i < needed_bigits - 1; ++i) {
// These bigits are guaranteed to be "full".
Chunk current_bigit = 0;
for (int j = 0; j < kBigitSize / 4; j++) {
}
bigits_[i] = current_bigit;
}
for (int j = 0; j <= string_index; ++j) {
most_significant_bigit <<= 4;
}
if (most_significant_bigit != 0) {
used_digits_++;
}
Clamp();
}
if (operand == 0) return;
}
for (int i = 0; i < other.used_digits_; ++i) {
bigit_pos++;
}
while (carry != 0) {
bigit_pos++;
}
}
// We require this to be bigger than other.
int i;
for (i = 0; i < other.used_digits_; ++i) {
}
while (borrow != 0) {
++i;
}
Clamp();
}
if (used_digits_ == 0) return;
}
if (factor == 1) return;
if (factor == 0) {
Zero();
return;
}
if (used_digits_ == 0) return;
DoubleChunk carry = 0;
for (int i = 0; i < used_digits_; ++i) {
}
while (carry != 0) {
used_digits_++;
carry >>= kBigitSize;
}
}
if (factor == 1) return;
if (factor == 0) {
Zero();
return;
}
for (int i = 0; i < used_digits_; ++i) {
}
while (carry != 0) {
used_digits_++;
carry >>= kBigitSize;
}
}
const uint32_t kFive1_to_12[] =
if (exponent == 0) return;
if (used_digits_ == 0) return;
int remaining_exponent = exponent;
while (remaining_exponent >= 27) {
remaining_exponent -= 27;
}
while (remaining_exponent >= 13) {
remaining_exponent -= 13;
}
if (remaining_exponent > 0) {
}
}
}
DoubleChunk accumulator = 0;
// First shift the digits so we don't overwrite them.
int copy_offset = used_digits_;
for (int i = 0; i < used_digits_; ++i) {
}
// We have two loops to avoid some 'if's in the loop.
for (int i = 0; i < used_digits_; ++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) {
bigit_index1--;
bigit_index2++;
}
accumulator >>= kBigitSize;
}
for (int i = used_digits_; i < product_length; ++i) {
int bigit_index2 = i - bigit_index1;
while (bigit_index2 < used_digits_) {
bigit_index1--;
bigit_index2++;
}
accumulator >>= kBigitSize;
}
ASSERT(accumulator == 0);
exponent_ *= 2;
Clamp();
}
ASSERT(power_exponent >= 0);
if (power_exponent == 0) {
AssignUInt16(1);
return;
}
Zero();
int shifts = 0;
while ((base & 1) == 0) {
base >>= 1;
shifts++;
}
int bit_size = 0;
while (tmp_base != 0) {
tmp_base >>= 1;
bit_size++;
}
// Left to Right exponentiation.
int mask = 1;
mask >>= 2;
bool delayed_multipliciation = false;
// 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) {
if (high_bits_zero) {
this_value *= base;
} else {
delayed_multipliciation = true;
}
}
mask >>= 1;
}
if (delayed_multipliciation) {
}
// Now do the same thing as a bignum.
while (mask != 0) {
Square();
if ((power_exponent & mask) != 0) {
}
mask >>= 1;
}
// And finally add the saved shifts.
}
return 0;
}
}
Clamp();
return result;
}
return result;
}
result++;
}
return result;
}
template<typename S>
static int SizeInHexChars(S number) {
int result = 0;
while (number != 0) {
number >>= 4;
result++;
}
return result;
}
static char HexCharOfValue(int value) {
}
// Each bigit must be printable as separate hex-character.
if (used_digits_ == 0) {
if (buffer_size < 2) return false;
buffer[0] = '0';
return true;
}
// We add 1 for the terminating '\0' character.
if (needed_chars > buffer_size) return false;
for (int i = 0; i < exponent_; ++i) {
for (int j = 0; j < kHexCharsPerBigit; ++j) {
}
}
for (int i = 0; i < used_digits_ - 1; ++i) {
for (int j = 0; j < kHexCharsPerBigit; ++j) {
current_bigit >>= 4;
}
}
// And finally the last bigit.
while (most_significant_bigit != 0) {
most_significant_bigit >>= 4;
}
return true;
}
if (index >= BigitLength()) return 0;
}
int bigit_length_a = a.BigitLength();
int bigit_length_b = b.BigitLength();
}
return 0;
}
if (a.BigitLength() < b.BigitLength()) {
return PlusCompare(b, a, c);
}
return -1;
}
// Starting at min_exponent all digits are == 0. So no need to compare them.
return +1;
} else {
borrow <<= kBigitSize;
}
}
if (borrow == 0) return 0;
return -1;
}
used_digits_--;
}
if (used_digits_ == 0) {
// Zero.
exponent_ = 0;
}
}
}
for (int i = 0; i < used_digits_; ++i) {
bigits_[i] = 0;
}
used_digits_ = 0;
exponent_ = 0;
}
for (int i = used_digits_ - 1; i >= 0; --i) {
}
for (int i = 0; i < zero_digits; ++i) {
bigits_[i] = 0;
}
exponent_ -= zero_digits;
ASSERT(used_digits_ >= 0);
}
}
ASSERT(shift_amount >= 0);
for (int i = 0; i < used_digits_; ++i) {
}
if (carry != 0) {
used_digits_++;
}
}
if (factor < 3) {
for (int i = 0; i < factor; ++i) {
}
return;
}
for (int i = 0; i < other.used_digits_; ++i) {
(remove >> kBigitSize));
}
if (borrow == 0) return;
}
Clamp();
}
class PowersOfTenCache {
public:
static const int kDecimalExponentDistance;
static const int kMinDecimalExponent;
static const int kMaxDecimalExponent;
static void GetCachedPowerForBinaryExponentRange(int min_exponent,
int max_exponent,
int* decimal_exponent);
static void GetCachedPowerForDecimalExponent(int requested_exponent,
int* found_exponent);
};
struct CachedPower {
};
static const CachedPower kCachedPowers[] = {
};
// Difference between the decimal exponents in the table above.
int min_exponent,
int max_exponent,
int* decimal_exponent) {
int foo = kCachedPowersOffset;
int index =
(void) max_exponent; // Mark variable as used.
}
int* found_exponent) {
int index =
}
enum BignumDtoaMode {
};
ASSERT(significand != 0);
}
return exponent;
}
static int EstimatePower(int exponent);
int exponent,
bool lower_boundary_is_closer,
int estimated_power,
bool need_boundary_deltas,
Bignum* delta_plus);
int* decimal_point,
bool is_even,
ASSERT(v > 0);
int exponent;
bool lower_boundary_is_closer;
bool need_boundary_deltas =
(mode == BIGNUM_DTOA_SHORTEST);
// estimated_power might be too low by 1.
buffer[0] = '\0';
*length = 0;
return;
}
&numerator, &denominator,
&delta_minus, &delta_plus);
&numerator, &denominator,
&delta_minus, &delta_plus);
switch (mode) {
case BIGNUM_DTOA_SHORTEST:
break;
case BIGNUM_DTOA_FIXED:
&numerator, &denominator,
break;
case BIGNUM_DTOA_PRECISION:
&numerator, &denominator,
break;
default:
UNREACHABLE();
}
}
bool is_even,
}
*length = 0;
for (;;) {
bool in_delta_room_minus;
bool in_delta_room_plus;
if (is_even) {
} else {
}
if (is_even) {
} else {
}
if (!in_delta_room_minus && !in_delta_room_plus) {
delta_minus->Times10();
if (delta_minus != delta_plus) {
delta_plus->Times10();
}
} else if (in_delta_room_minus && in_delta_room_plus) {
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.
} else {
// Round down => Do nothing.
} else {
}
}
return;
} else if (in_delta_room_minus) {
return;
} else { // in_delta_room_plus
// Round up
return;
}
}
}
for (int i = 0; i < count - 1; ++i) {
}
digit++;
}
for (int i = count - 1; i > 0; --i) {
buffer[i] = '0';
buffer[i - 1]++;
}
buffer[0] = '1';
(*decimal_point)++;
}
}
{
if (-(*decimal_point) > requested_digits) {
*length = 0;
return;
} else if (-(*decimal_point) == requested_digits) {
denominator->Times10();
buffer[0] = '1';
*length = 1;
(*decimal_point)++;
} else {
*length = 0;
}
return;
} else {
}
}
static int EstimatePower(int exponent) {
// For doubles len(f) == 53 (don't forget the hidden bit).
}
static void InitialScaledStartValuesPositiveExponent(
int estimated_power, bool need_boundary_deltas,
{
ASSERT(estimated_power >= 0);
if (need_boundary_deltas) {
}
}
int estimated_power, bool need_boundary_deltas,
{
if (need_boundary_deltas) {
}
}
int estimated_power, bool need_boundary_deltas,
{
if (need_boundary_deltas) {
}
if (need_boundary_deltas) {
}
}
int exponent,
bool lower_boundary_is_closer,
int estimated_power,
bool need_boundary_deltas,
{
if (exponent >= 0) {
} else if (estimated_power >= 0) {
} else {
}
if (need_boundary_deltas && lower_boundary_is_closer) {
}
}
int* decimal_point,
bool in_range;
if (is_even) {
} else {
}
if (in_range) {
} else {
delta_minus->Times10();
} else {
delta_minus->Times10();
delta_plus->Times10();
}
}
}
enum FastDtoaMode {
};
bool FastDtoa(double d,
int requested_digits,
int* length,
int* decimal_point);
static const int kMinimalTargetExponent = -60;
static const int kMaximalTargetExponent = -32;
{
}
if (rest < big_distance &&
return false;
}
}
int* kappa)
{
return true;
}
for (int i = length - 1; i > 0; --i) {
buffer[i] = '0';
buffer[i - 1]++;
}
buffer[0] = '1';
(*kappa) += 1;
}
return true;
}
return false;
}
static unsigned int const kSmallPowersOfTen[] =
{0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,
1000000000};
int number_bits,
int* exponent_plus_one) {
}
}
{
*length = 0;
while (*kappa > 0) {
(*length)++;
(*kappa)--;
if (rest < unsafe_interval.f()) {
unsafe_interval.f(), rest,
}
divisor /= 10;
}
for (;;) {
fractionals *= 10;
unit *= 10;
// Integer division by one.
(*length)++;
(*kappa)--;
if (fractionals < unsafe_interval.f()) {
}
}
}
{
*length = 0;
while (*kappa > 0) {
(*length)++;
(*kappa)--;
if (requested_digits == 0) break;
divisor /= 10;
}
if (requested_digits == 0) {
kappa);
}
fractionals *= 10;
w_error *= 10;
// Integer division by one.
(*length)++;
(*kappa)--;
}
if (requested_digits != 0) return false;
kappa);
}
int* length, int* decimal_exponent)
{
ASSERT(boundary_plus.e() == w.e());
int mk; // -k
DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() +
int kappa;
return result;
}
int* length, int* decimal_exponent)
{
int mk; // -k
DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() +
int kappa;
return result;
}
bool FastDtoa(double v,
int requested_digits,
int* length,
int* decimal_point) {
ASSERT(v > 0);
bool result = false;
int decimal_exponent = 0;
switch (mode) {
case FAST_DTOA_SHORTEST:
break;
case FAST_DTOA_PRECISION:
break;
default:
UNREACHABLE();
}
if (result) {
}
return result;
}
// Represents a 128bit type. This class should be replaced by a native type on
// platforms that support 128bit integers.
class UInt128 {
public:
accumulator >>= 32;
accumulator >>= 32;
accumulator >>= 32;
}
void Shift(int shift_amount) {
if (shift_amount == 0) {
return;
} else if (shift_amount == -64) {
low_bits_ = 0;
} else if (shift_amount == 64) {
high_bits_ = 0;
} else if (shift_amount <= 0) {
high_bits_ <<= -shift_amount;
low_bits_ <<= -shift_amount;
} else {
low_bits_ >>= shift_amount;
high_bits_ >>= shift_amount;
}
}
// Modifies *this to *this MOD (2^power).
// Returns *this DIV (2^power).
int DivModPowerOf2(int power) {
if (power >= 64) {
return result;
} else {
high_bits_ = 0;
return result;
}
}
bool IsZero() const {
return high_bits_ == 0 && low_bits_ == 0;
}
if (position >= 64) {
} else {
}
}
private:
// Value == (high_bits_ << 64) + low_bits_
};
for (int i = requested_length - 1; i >= 0; --i) {
number /= 10;
}
*length += requested_length;
}
int number_length = 0;
// We fill the digits in reverse order and exchange them afterwards.
while (number != 0) {
number /= 10;
}
// Exchange the digits.
int i = *length;
while (i < j) {
i++;
j--;
}
*length += number_length;
}
// For efficiency cut the number into 3 uint32_t parts, and print those.
}
// For efficiency cut the number into 3 uint32_t parts, and print those.
if (part0 != 0) {
} else if (part1 != 0) {
} else {
}
}
// An empty buffer represents 0.
if (*length == 0) {
buffer[0] = '1';
*decimal_point = 1;
*length = 1;
return;
}
for (int i = (*length) - 1; i > 0; --i) {
return;
}
buffer[i] = '0';
buffer[i - 1]++;
}
buffer[0] = '1';
(*decimal_point)++;
}
}
int* length, int* decimal_point)
{
if (-exponent <= 64) {
for (int i = 0; i < fractional_count; ++i) {
if (fractionals == 0) break;
fractionals *= 5;
point--;
(*length)++;
}
}
} else { // We need 128 bits.
int point = 128;
for (int i = 0; i < fractional_count; ++i) {
if (fractionals128.IsZero()) break;
point--;
(*length)++;
}
}
}
}
// Removes leading and trailing zeros.
// If leading zeros are removed then the decimal point position is adjusted.
(*length)--;
}
int first_non_zero = 0;
}
if (first_non_zero != 0) {
for (int i = first_non_zero; i < *length; ++i) {
}
*length -= first_non_zero;
}
}
bool FastFixedDtoa(double v,
int fractional_count,
int* length,
int* decimal_point) {
if (exponent > 20) return false;
if (fractional_count > 20) return false;
*length = 0;
int divisor_power = 17;
if (exponent > divisor_power) {
} else {
}
*decimal_point = *length;
} else if (exponent >= 0) {
// 0 <= exponent <= 11
significand <<= exponent;
*decimal_point = *length;
} else if (exponent > -kDoubleSignificandSize) {
if (integrals > kMaxUInt32) {
} else {
}
*decimal_point = *length;
} else if (exponent < -128) {
// This configuration (with at most 20 digits) means that all digits must be
// 0.
buffer[0] = '\0';
*length = 0;
} else {
*decimal_point = 0;
}
if ((*length) == 0) {
}
return true;
}
static const int kMaxUint64DecimalDigits = 19;
static const int kMaxDecimalPower = 309;
static const int kMinDecimalPower = -324;
// 2^64 = 18446744073709551616
static const int kMaxSignificantDecimalDigits = 780;
if (buffer[i] != '0') {
}
}
}
if (buffer[i] != '0') {
}
}
}
int exponent,
char* significant_buffer,
int* significant_exponent) {
for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) {
significant_buffer[i] = buffer[i];
}
}
char* buffer_copy_space, int space_size,
(void) space_size; // Mark variable as used.
} else {
*trimmed = right_trimmed;
}
}
int* number_of_read_digits) {
int i = 0;
}
*number_of_read_digits = i;
return result;
}
int* remaining_decimals) {
int read_digits;
*remaining_decimals = 0;
} else {
// Round the significand.
significand++;
}
// Compute the binary exponent.
int exponent = 0;
}
}
// Simply hardcode the remaining powers for the given decimal exponent
// distance.
switch (exponent) {
default:
UNREACHABLE();
}
}
int exponent,
double* result) {
int remaining_decimals;
const int kDenominatorLog = 3;
// Move the remaining decimals into the exponent.
*result = 0.0;
return true;
}
if (cached_decimal_exponent != exponent) {
// The product of input with the adjustment power fits into a 64 bit
// integer.
} else {
// The adjustment power is exact. There is hence only an error of 0.5.
}
}
int precision_digits_count =
}
half_way *= kDenominator;
input.e() + precision_digits_count);
}
return false;
} else {
return true;
}
}
int exponent,
if (exponent >= 0) {
} else {
}
if (diy_fp.e() > 0) {
} else {
}
}
double* guess)
{
*guess = 0.0;
return true;
}
return true;
}
*guess = 0.0;
return true;
}
return true;
}
return true;
}
return false;
}
{
int updated_exponent;
&trimmed, &updated_exponent);
double guess;
if (is_correct) return guess;
if (comparison < 0) {
return guess;
} else if (comparison > 0) {
// Round towards even.
return guess;
} else {
}
}
class DoubleToStringConverter {
public:
static const int kMaxFixedDigitsBeforePoint = 60;
static const int kMaxFixedDigitsAfterPoint = 60;
static const int kMaxExponentialDigits = 120;
static const int kMinPrecisionDigits = 1;
static const int kMaxPrecisionDigits = 120;
enum Flags {
NO_FLAGS = 0,
UNIQUE_ZERO = 8
};
const char* infinity_symbol,
const char* nan_symbol,
char exponent_character,
// When 'trailing zero after the point' is set, then 'trailing point'
// must be set too.
!((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0));
}
}
int requested_digits,
bool ToExponential(double value,
int requested_digits,
bool ToPrecision(double value,
int precision,
enum DtoaMode {
FIXED, // Produce a fixed number of digits after the decimal point
PRECISION // Fixed number of digits (independent of the decimal point)
};
static const int kBase10MaximalLength = 17;
// The result should be interpreted as buffer * 10^(point-length).
static void DoubleToAscii(double v,
int requested_digits,
char* buffer,
int buffer_length,
bool* sign,
int* length,
int* point);
private:
// Implementation for ToShortest.
bool ToShortestIeeeNumber(double value,
void CreateExponentialRepresentation(const char* decimal_digits,
int length,
int exponent,
void CreateDecimalRepresentation(const char* decimal_digits,
int length,
int decimal_point,
int digits_after_point,
const int flags_;
const char* const infinity_symbol_;
const char* const nan_symbol_;
const char exponent_character_;
const int decimal_in_shortest_low_;
const int decimal_in_shortest_high_;
};
class StringToDoubleConverter {
public:
enum Flags {
NO_FLAGS = 0,
ALLOW_HEX = 1,
ALLOW_OCTALS = 2,
ALLOW_TRAILING_JUNK = 4,
ALLOW_LEADING_SPACES = 8,
ALLOW_TRAILING_SPACES = 16,
};
double empty_string_value,
double junk_string_value,
const char* infinity_symbol,
const char* nan_symbol)
}
double StringToDouble(const char* buffer,
int length,
int* processed_characters_count) const;
private:
const int flags_;
const double empty_string_value_;
const double junk_string_value_;
const char* const infinity_symbol_;
const char* const nan_symbol_;
double StringToIeee(const char *start_pointer,
int length,
int* processed_characters_count) const;
};
double value,
if (double_inspect.IsInfinite()) {
if (infinity_symbol_ == NULL) return false;
if (value < 0) {
result += '-';
}
return true;
}
if (double_inspect.IsNan()) {
if (nan_symbol_ == NULL) return false;
return true;
}
return false;
}
const char* decimal_digits,
int length,
int exponent,
result += decimal_digits[0];
if (length != 1) {
result += '.';
}
if (exponent < 0) {
result += '-';
} else {
if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
result += '+';
}
}
if (exponent == 0) {
result += '0';
return;
}
const int kMaxExponentLength = 5;
int first_char_pos = kMaxExponentLength;
while (exponent > 0) {
exponent /= 10;
}
}
const char* decimal_digits,
int length,
int decimal_point,
int digits_after_point,
// Create a representation that is padded with zeros if needed.
if (decimal_point <= 0) {
// "0.00000decimal_rep".
result += '0';
if (digits_after_point > 0) {
result += '.';
}
} else if (decimal_point >= length) {
// "decimal_rep0000.00000" or "decimal_rep.0000"
if (digits_after_point > 0) {
result += '.';
}
} else {
// "decima.l_rep000"
ASSERT(digits_after_point > 0);
result += '.';
}
if (digits_after_point == 0) {
if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
result += '.';
}
if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
result += '0';
}
}
}
double value,
}
int decimal_point;
bool sign;
char decimal_rep[kDecimalRepCapacity];
int decimal_rep_length;
result += '-';
}
if ((decimal_in_shortest_low_ <= exponent) &&
result);
} else {
}
return true;
}
int requested_digits,
{
const double kFirstNonFixed = 1e60;
}
if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
// Find a sufficiently precise decimal representation of n.
int decimal_point;
bool sign;
// Add space for the '\0' byte.
const int kDecimalRepCapacity =
char decimal_rep[kDecimalRepCapacity];
int decimal_rep_length;
result += '-';
}
return true;
}
double value,
int requested_digits,
}
if (requested_digits < -1) return false;
if (requested_digits > kMaxExponentialDigits) return false;
int decimal_point;
bool sign;
// Add space for digit before the decimal point and the '\0' character.
char decimal_rep[kDecimalRepCapacity];
int decimal_rep_length;
if (requested_digits == -1) {
} else {
decimal_rep[i] = '0';
}
}
result += '-';
}
return true;
}
int precision,
}
return false;
}
// Find a sufficiently precise decimal representation of n.
int decimal_point;
bool sign;
// Add one for the terminating null character.
char decimal_rep[kDecimalRepCapacity];
int decimal_rep_length;
result += '-';
}
// The exponent if we print the number as x.xxeyyy. That is with the
// decimal point after the first digit.
for (int i = decimal_rep_length; i < precision; ++i) {
decimal_rep[i] = '0';
}
result);
} else {
result);
}
return true;
}
static BignumDtoaMode DtoaToBignumDtoaMode(
switch (dtoa_mode) {
default:
UNREACHABLE();
}
}
char* buffer, int buffer_length,
{
*sign = true;
v = -v;
} else {
*sign = false;
}
vector[0] = '\0';
*length = 0;
return;
}
if (v == 0) {
vector[0] = '0';
*length = 1;
*point = 1;
return;
}
bool fast_worked;
switch (mode) {
case SHORTEST:
break;
case FIXED:
break;
case PRECISION:
break;
default:
fast_worked = false;
UNREACHABLE();
}
if (fast_worked) return;
// If the fast dtoa didn't succeed use the slower bignum version.
}
template <class Iterator>
const char* substring) {
++*current;
}
++*current;
return true;
}
const int kMaxSignificantDigits = 772;
static bool isWhitespace(int x) {
if (x < 128) {
for (int i = 0; i < kWhitespaceTable7Length; i++) {
if (kWhitespaceTable7[i] == x) return true;
}
}
return false;
}
// Returns true if a nonspace found and false if the end has reached.
template <class Iterator>
if (!isWhitespace(**current)) return true;
++*current;
}
return false;
}
}
static double SignedZero(bool sign) {
}
static bool IsDecimalDigitForRadix(int c, int radix) {
}
}
template <int radix_log_2, class Iterator>
bool* result_is_junk)
{
*result_is_junk = true;
// Skip leading 0s.
while (**current == '0') {
++(*current);
*result_is_junk = false;
return SignedZero(sign);
}
}
int exponent = 0;
do {
int digit;
} else {
break;
} else {
return junk_string_value;
}
}
if (overflow != 0) {
// Overflow occurred. Need to determine which direction to round the
// result.
int overflow_bits_count = 1;
while (overflow > 1) {
overflow >>= 1;
}
bool zero_tail = true;
for (;;) {
++(*current);
exponent += radix_log_2;
}
return junk_string_value;
}
if (dropped_bits > middle_value) {
number++; // Rounding up.
} else if (dropped_bits == middle_value) {
// Rounding to even to consistency with decimals: half-way case rounds
// up if significant part is odd and down otherwise.
number++; // Rounding up.
}
}
// Rounding up may cause overflow.
exponent++;
number >>= 1;
}
break;
}
++(*current);
*result_is_junk = false;
if (exponent == 0) {
if (sign) {
if (number == 0) return -0.0;
}
}
}
double StringToDoubleConverter::StringToIeee(
const char *input,
int length,
int* processed_characters_count) const {
if (allow_leading_spaces || allow_trailing_spaces) {
return empty_string_value_;
}
return junk_string_value_;
}
}
int buffer_pos = 0;
int exponent = 0;
int significant_digits = 0;
int insignificant_digits = 0;
bool nonzero_digit_dropped = false;
bool sign = false;
++current;
const char *next_non_space = current;
return junk_string_value_;
}
}
if (infinity_symbol_ != NULL) {
if (*current == infinity_symbol_[0]) {
return junk_string_value_;
}
return junk_string_value_;
}
return junk_string_value_;
}
ASSERT(buffer_pos == 0);
}
}
if (nan_symbol_ != NULL) {
if (*current == nan_symbol_[0]) {
return junk_string_value_;
}
return junk_string_value_;
}
return junk_string_value_;
}
ASSERT(buffer_pos == 0);
}
}
bool leading_zero = false;
if (*current == '0') {
++current;
return SignedZero(sign);
}
leading_zero = true;
// It could be hexadecimal value.
++current;
return junk_string_value_; // "0x".
}
bool result_is_junk;
end,
sign,
if (!result_is_junk) {
}
return result;
}
// Ignore leading zeros in the integer part.
while (*current == '0') {
++current;
return SignedZero(sign);
}
}
}
// Copy significant digits of the integer part (if any) to the buffer.
if (significant_digits < kMaxSignificantDigits) {
// Will later check if it's an octal in the buffer.
} else {
insignificant_digits++; // Move the digit into the exponential part.
}
++current;
}
if (significant_digits == 0) {
octal = false;
}
if (*current == '.') {
if (octal) goto parsing_done;
++current;
if (significant_digits == 0 && !leading_zero) {
return junk_string_value_;
} else {
goto parsing_done;
}
}
if (significant_digits == 0) {
// octal = false;
// Integer part consists of 0 or is absent. Significant digits start after
// leading zeros (if any).
while (*current == '0') {
++current;
return SignedZero(sign);
}
exponent--; // Move this 0 into the exponent.
}
}
// There is a fractional part.
// We don't emit a '.', but adjust the exponent instead.
if (significant_digits < kMaxSignificantDigits) {
exponent--;
} else {
// Ignore insignificant digits in the fractional part.
}
++current;
}
}
// If leading_zeros is true then the string contains zeros.
// If exponent < 0 then string was [+-]\.0*...
// If significant_digits != 0 the string is not equal to 0.
// Otherwise there are no digits in the string.
return junk_string_value_;
}
// Parse exponential part.
if (octal) goto parsing_done;
++current;
if (allow_trailing_junk) {
goto parsing_done;
} else {
return junk_string_value_;
}
}
char sign = '+';
++current;
if (allow_trailing_junk) {
goto parsing_done;
} else {
return junk_string_value_;
}
}
}
if (allow_trailing_junk) {
goto parsing_done;
} else {
return junk_string_value_;
}
}
int num = 0;
do {
// Check overflow.
num = max_exponent;
} else {
}
++current;
}
return junk_string_value_;
}
return junk_string_value_;
}
if (allow_trailing_spaces) {
}
if (octal) {
double result;
bool result_is_junk;
buffer + buffer_pos,
sign,
return result;
}
if (nonzero_digit_dropped) {
exponent--;
}
}
double StringToDoubleConverter::StringToDouble(
const char* buffer,
int length,
int* processed_characters_count) const {
}
} // end anonymous namespace
{
char buf[20];
bool sign;
if (sign) {
ret += '-';
}
if (exponent == 0) {
// return digits without any changes
// insert decimal point
ret += '.';
// add trailing zeroes
// add leading zeroes
ret += '.';
} else {
// exponential form
ret += 'e';
if (exponent < 0) {
ret += '-';
}
/* Convert exponent by hand.
* Using ostringstream is ~3x slower */
int const buflen = 6;
int i = 0;
exponent /= 10;
}
}
return ret;
}
{
static DoubleToStringConverter conv(
"inf", "NaN", 'e', -6, 21, 0, 0);
return ret;
}
{
static StringToDoubleConverter conv(
int dummy;
}
} // namespace Geom
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :