coord.cpp revision e4369b05aaa20df73a37f4d319ce456865cc74f3
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński/** @file
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * @brief Conversion between Coord and strings
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *//*
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * Authors:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * Krzysztof Kosiński <tweenk.pl@gmail.com>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * Copyright 2014 Authors
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * This library is free software; you can redistribute it and/or
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * modify it either under the terms of the GNU Lesser General Public
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * License version 2.1 as published by the Free Software Foundation
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * (the "LGPL") or, at your option, under the terms of the Mozilla
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * Public License Version 1.1 (the "MPL"). If you do not alter this
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * notice, a recipient may use your version of this file under either
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * the MPL or the LGPL.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * You should have received a copy of the LGPL along with this library
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * in the file COPYING-LGPL-2.1; if not, write to the Free Software
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * You should have received a copy of the MPL along with this library
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * in the file COPYING-MPL-1.1
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * The contents of this file are subject to the Mozilla Public License
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * Version 1.1 (the "License"); you may not use this file except in
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * compliance with the License. You may obtain a copy of the License at
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * http://www.mozilla.org/MPL/
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * OF ANY KIND, either express or implied. See the LGPL or the MPL for
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * the specific language governing rights and limitations.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński */
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// Most of the code in this file is derived from:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// https://code.google.com/p/double-conversion/
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// The copyright notice for that code is attached below.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński//
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// Copyright 2010 the V8 project authors. All rights reserved.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// Redistribution and use in source and binary forms, with or without
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// modification, are permitted provided that the following conditions are
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// met:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński//
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// * Redistributions of source code must retain the above copyright
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// notice, this list of conditions and the following disclaimer.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// * Redistributions in binary form must reproduce the above
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// copyright notice, this list of conditions and the following
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// disclaimer in the documentation and/or other materials provided
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// with the distribution.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// * Neither the name of Google Inc. nor the names of its
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// contributors may be used to endorse or promote products derived
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// from this software without specific prior written permission.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński//
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#include <2geom/coord.h>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#include <stdint.h>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#include <cstdlib>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#include <cassert>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#include <cstring>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#include <climits>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#include <cstdarg>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#include <cmath>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#ifndef ASSERT
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#define ASSERT(condition) \
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński assert(condition);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#endif
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#ifndef UNIMPLEMENTED
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#define UNIMPLEMENTED() (abort())
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#endif
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#ifndef UNREACHABLE
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#define UNREACHABLE() (abort())
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#endif
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#define UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#ifndef ARRAY_SIZE
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#define ARRAY_SIZE(a) \
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ((sizeof(a) / sizeof(*(a))) / \
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#endif
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#ifndef DISALLOW_COPY_AND_ASSIGN
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński TypeName(const TypeName&); \
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void operator=(const TypeName&)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#endif
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński TypeName(); \
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DISALLOW_COPY_AND_ASSIGN(TypeName)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#endif
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#if defined(__GNUC__)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#else
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#define DOUBLE_CONVERSION_UNUSED
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński#endif
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskinamespace Geom {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskinamespace {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiinline int StrLength(const char* string) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński size_t length = strlen(string);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(length == static_cast<size_t>(static_cast<int>(length)));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return static_cast<int>(length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskitemplate <typename T>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiclass Vector {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński public:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector() : start_(NULL), length_(0) {}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector(T* data, int length) : start_(data), length_(length) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(length == 0 || (length > 0 && data != NULL));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<T> SubVector(int from, int to) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(to <= length_);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(from < to);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(0 <= from);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Vector<T>(start() + from, to - from);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length() const { return length_; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool is_empty() const { return length_ == 0; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński T* start() const { return start_; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński T& operator[](int index) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(0 <= index && index < length_);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return start_[index];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński T& first() { return start_[0]; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński T& last() { return start_[length_ - 1]; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński private:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński T* start_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskitemplate <class Dest, class Source>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiinline Dest BitCast(const Source& source) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DOUBLE_CONVERSION_UNUSED
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Dest dest;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński memmove(&dest, &source, sizeof(dest));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return dest;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskitemplate <class Dest, class Source>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiinline Dest BitCast(Source* source) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// We assume that doubles and uint64_t have the same endianness.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic uint64_t double_to_uint64(double d) { return BitCast<uint64_t>(d); }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic double uint64_to_double(uint64_t d64) { return BitCast<double>(d64); }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// This "Do It Yourself Floating Point" class
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiclass DiyFp {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński public:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kSignificandSize = 64;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp() : f_(0), e_(0) {}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp(uint64_t f, int e) : f_(f), e_(e) {}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void Subtract(const DiyFp& other) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(e_ == other.e_);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(f_ >= other.f_);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński f_ -= other.f_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static DiyFp Minus(const DiyFp& a, const DiyFp& b) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp result = a;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.Subtract(b);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void Multiply(const DiyFp& other) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint64_t kM32 = 0xFFFFFFFFU;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t a = f_ >> 32;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t b = f_ & kM32;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t c = other.f_ >> 32;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t d = other.f_ & kM32;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t ac = a * c;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t bc = b * c;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t ad = a * d;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t bd = b * d;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // By adding 1U << 31 to tmp we round the final result.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Halfway cases will be round up.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński tmp += 1U << 31;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński e_ += other.e_ + 64;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński f_ = result_f;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static DiyFp Times(const DiyFp& a, const DiyFp& b) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp result = a;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.Multiply(b);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void Normalize() {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(f_ != 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t f = f_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int e = e_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while ((f & k10MSBits) == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński f <<= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński e -= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while ((f & kUint64MSB) == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński f <<= 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński e--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński f_ = f;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński e_ = e;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static DiyFp Normalize(const DiyFp& a) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp result = a;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.Normalize();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t f() const { return f_; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int e() const { return e_; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void set_f(uint64_t new_value) { f_ = new_value; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void set_e(int new_value) { e_ = new_value; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński private:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t f_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int e_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiclass Double {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński public:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kSignificandSize = 53;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Double() : d64_(0) {}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński explicit Double(double d) : d64_(double_to_uint64(d)) {}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński explicit Double(uint64_t d64) : d64_(d64) {}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński explicit Double(DiyFp diy_fp)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński : d64_(DiyFpToUint64(diy_fp)) {}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp AsDiyFp() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(Sign() > 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(!IsSpecial());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return DiyFp(Significand(), Exponent());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp AsNormalizedDiyFp() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(value() > 0.0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t f = Significand();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int e = Exponent();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // The current double could be a denormal.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while ((f & kHiddenBit) == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński f <<= 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński e--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Do the final shifts in one go.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński f <<= DiyFp::kSignificandSize - kSignificandSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński e -= DiyFp::kSignificandSize - kSignificandSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return DiyFp(f, e);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t AsUint64() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return d64_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double NextDouble() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (d64_ == kInfinity) return Double(kInfinity).value();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Sign() < 0 && Significand() == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // -0.0
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return 0.0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Sign() < 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Double(d64_ - 1).value();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Double(d64_ + 1).value();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double PreviousDouble() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (d64_ == (kInfinity | kSignMask)) return -Double::Infinity();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Sign() < 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Double(d64_ + 1).value();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Significand() == 0) return -0.0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Double(d64_ - 1).value();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int Exponent() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (IsDenormal()) return kDenormalExponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t d64 = AsUint64();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int biased_e =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static_cast<int>((d64 & kExponentMask) >> kPhysicalSignificandSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return biased_e - kExponentBias;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t Significand() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t d64 = AsUint64();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t significand = d64 & kSignificandMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!IsDenormal()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return significand + kHiddenBit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return significand;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool IsDenormal() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t d64 = AsUint64();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return (d64 & kExponentMask) == 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // We consider denormals not to be special.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Hence only Infinity and NaN are special.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool IsSpecial() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t d64 = AsUint64();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return (d64 & kExponentMask) == kExponentMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool IsNan() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t d64 = AsUint64();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return ((d64 & kExponentMask) == kExponentMask) &&
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ((d64 & kSignificandMask) != 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool IsInfinite() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t d64 = AsUint64();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return ((d64 & kExponentMask) == kExponentMask) &&
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ((d64 & kSignificandMask) == 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int Sign() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t d64 = AsUint64();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return (d64 & kSignMask) == 0? 1: -1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp UpperBoundary() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(Sign() > 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return DiyFp(Significand() * 2 + 1, Exponent() - 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(value() > 0.0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp v = this->AsDiyFp();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp m_minus;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (LowerBoundaryIsCloser()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński m_minus.set_e(m_plus.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *out_m_plus = m_plus;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *out_m_minus = m_minus;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool LowerBoundaryIsCloser() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool physical_significand_is_zero = ((AsUint64() & kSignificandMask) == 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return physical_significand_is_zero && (Exponent() != kDenormalExponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double value() const { return uint64_to_double(d64_); }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static int SignificandSizeForOrderOfMagnitude(int order) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (order >= (kDenormalExponent + kSignificandSize)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return kSignificandSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (order <= kDenormalExponent) return 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return order - kDenormalExponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static double Infinity() {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Double(kInfinity).value();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static double NaN() {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Double(kNaN).value();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński private:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kDenormalExponent = -kExponentBias + 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kMaxExponent = 0x7FF - kExponentBias;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint64_t d64_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static uint64_t DiyFpToUint64(DiyFp diy_fp) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t significand = diy_fp.f();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent = diy_fp.e();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (significand > kHiddenBit + kSignificandMask) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significand >>= 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent >= kMaxExponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return kInfinity;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent < kDenormalExponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significand <<= 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t biased_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński biased_exponent = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński biased_exponent = static_cast<uint64_t>(exponent + kExponentBias);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return (significand & kSignificandMask) |
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (biased_exponent << kPhysicalSignificandSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DISALLOW_COPY_AND_ASSIGN(Double);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskitemplate<typename S>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic int BitSize(S value) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (void) value; // Mark variable as used.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return 8 * sizeof(value);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiclass Bignum {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński public:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // This bignum can encode much bigger numbers, since it contains an
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // exponent.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kMaxSignificantBits = 3584;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum()
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński : bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < kBigitCapacity; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void AssignUInt16(uint16_t value) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(kBigitSize >= BitSize(value));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Zero();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (value == 0) return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EnsureCapacity(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[0] = value;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_ = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void AssignUInt64(uint64_t value) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kUInt64Size = 64;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Zero();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (value == 0) return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int needed_bigits = kUInt64Size / kBigitSize + 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EnsureCapacity(needed_bigits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < needed_bigits; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = value & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński value = value >> kBigitSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_ = needed_bigits;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Clamp();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void AssignBignum(const Bignum& other) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent_ = other.exponent_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < other.used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = other.bigits_[i];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Clear the excess digits (if there were any).
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = other.used_digits_; i < used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_ = other.used_digits_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void AssignDecimalString(Vector<const char> value);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void AssignHexString(Vector<const char> value);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void AssignPowerUInt16(uint16_t base, int exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void AddUInt16(uint16_t operand);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void AddUInt64(uint64_t operand);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void AddBignum(const Bignum& other);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Precondition: this >= other.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void SubtractBignum(const Bignum& other);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void Square();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void ShiftLeft(int shift_amount);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void MultiplyByUInt32(uint32_t factor);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void MultiplyByUInt64(uint64_t factor);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void MultiplyByPowerOfTen(int exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void Times10() { return MultiplyByUInt32(10); }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Pseudocode:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // int result = this / other;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // this = this % other;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // In the worst case this function is in O(this/other).
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint16_t DivideModuloIntBignum(const Bignum& other);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool ToHexString(char* buffer, int buffer_size) const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Returns
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // -1 if a < b,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // 0 if a == b, and
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // +1 if a > b.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static int Compare(const Bignum& a, const Bignum& b);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static bool Equal(const Bignum& a, const Bignum& b) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Compare(a, b) == 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static bool LessEqual(const Bignum& a, const Bignum& b) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Compare(a, b) <= 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static bool Less(const Bignum& a, const Bignum& b) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Compare(a, b) < 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Returns Compare(a + b, c);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Returns a + b == c
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return PlusCompare(a, b, c) == 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Returns a + b <= c
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return PlusCompare(a, b, c) <= 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Returns a + b < c
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return PlusCompare(a, b, c) < 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński private:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński typedef uint32_t Chunk;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński typedef uint64_t DoubleChunk;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kChunkSize = sizeof(Chunk) * 8;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // With bigit size of 28 we loose some bits, but a double still fits easily
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // into two chunks, and more importantly we can use the Comba multiplication.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kBigitSize = 28;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const Chunk kBigitMask = (1 << kBigitSize) - 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Every instance allocates kBigitLength chunks on the stack. Bignums cannot
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // grow. There are no checks if the stack-allocated space is sufficient.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kBigitCapacity = kMaxSignificantBits / kBigitSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void EnsureCapacity(int size) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (size > kBigitCapacity) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński UNREACHABLE();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void Align(const Bignum& other);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void Clamp();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool IsClamped() const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void Zero();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Requires this to have enough capacity (no tests done).
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Updates used_digits_ if necessary.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // shift_amount must be < kBigitSize.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void BigitsShiftLeft(int shift_amount);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // BigitLength includes the "hidden" digits encoded in the exponent.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int BigitLength() const { return used_digits_ + exponent_; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk BigitAt(int index) const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void SubtractTimes(const Bignum& other, int factor);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk bigits_buffer_[kBigitCapacity];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // A vector backed by bigits_buffer_. This way accesses to the array are
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // checked for out-of-bounds errors.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<Chunk> bigits_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int used_digits_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DISALLOW_COPY_AND_ASSIGN(Bignum);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic uint64_t ReadUInt64(Vector<const char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int from,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digits_to_read) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t result = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = from; i < from + digits_to_read; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digit = buffer[i] - '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(0 <= digit && digit <= 9);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result = result * 10 + digit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::AssignDecimalString(Vector<const char> value) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // 2^64 = 18446744073709551616 > 10^19
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kMaxUint64DecimalDigits = 19;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Zero();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length = value.length();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int pos = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Let's just say that each digit needs 4 bits.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (length >= kMaxUint64DecimalDigits) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński pos += kMaxUint64DecimalDigits;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński length -= kMaxUint64DecimalDigits;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński MultiplyByPowerOfTen(kMaxUint64DecimalDigits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński AddUInt64(digits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t digits = ReadUInt64(value, pos, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński MultiplyByPowerOfTen(length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński AddUInt64(digits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Clamp();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic int HexCharValue(char c) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ('0' <= c && c <= '9') return c - '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ('a' <= c && c <= 'f') return 10 + c - 'a';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT('A' <= c && c <= 'F');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return 10 + c - 'A';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::AssignHexString(Vector<const char> value) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Zero();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length = value.length();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int needed_bigits = length * 4 / kBigitSize + 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EnsureCapacity(needed_bigits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int string_index = length - 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < needed_bigits - 1; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // These bigits are guaranteed to be "full".
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk current_bigit = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int j = 0; j < kBigitSize / 4; j++) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński current_bigit += HexCharValue(value[string_index--]) << (j * 4);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = current_bigit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_ = needed_bigits - 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk most_significant_bigit = 0; // Could be = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int j = 0; j <= string_index; ++j) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński most_significant_bigit <<= 4;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński most_significant_bigit += HexCharValue(value[j]);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (most_significant_bigit != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[used_digits_] = most_significant_bigit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Clamp();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::AddUInt64(uint64_t operand) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (operand == 0) return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum other;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński other.AssignUInt64(operand);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński AddBignum(other);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::AddBignum(const Bignum& other) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(other.IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Align(other);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EnsureCapacity(1 + std::max(BigitLength(), other.BigitLength()) - exponent_);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk carry = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int bigit_pos = other.exponent_ - exponent_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(bigit_pos >= 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < other.used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[bigit_pos] = sum & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński carry = sum >> kBigitSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigit_pos++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (carry != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk sum = bigits_[bigit_pos] + carry;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[bigit_pos] = sum & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński carry = sum >> kBigitSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigit_pos++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_ = std::max(bigit_pos, used_digits_);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::SubtractBignum(const Bignum& other) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(other.IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // We require this to be bigger than other.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(LessEqual(other, *this));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Align(other);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int offset = other.exponent_ - exponent_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk borrow = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int i;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (i = 0; i < other.used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT((borrow == 0) || (borrow == 1));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i + offset] = difference & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński borrow = difference >> (kChunkSize - 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (borrow != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk difference = bigits_[i + offset] - borrow;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i + offset] = difference & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński borrow = difference >> (kChunkSize - 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++i;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Clamp();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::ShiftLeft(int shift_amount) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (used_digits_ == 0) return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent_ += shift_amount / kBigitSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int local_shift = shift_amount % kBigitSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EnsureCapacity(used_digits_ + 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński BigitsShiftLeft(local_shift);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::MultiplyByUInt32(uint32_t factor) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (factor == 1) return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (factor == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Zero();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (used_digits_ == 0) return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleChunk carry = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleChunk product = static_cast<DoubleChunk>(factor) * bigits_[i] + carry;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = static_cast<Chunk>(product & kBigitMask);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński carry = (product >> kBigitSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (carry != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EnsureCapacity(used_digits_ + 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[used_digits_] = carry & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński carry >>= kBigitSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::MultiplyByUInt64(uint64_t factor) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (factor == 1) return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (factor == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Zero();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(kBigitSize < 32);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t carry = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t low = factor & 0xFFFFFFFF;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t high = factor >> 32;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t product_low = low * bigits_[i];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t product_high = high * bigits_[i];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t tmp = (carry & kBigitMask) + product_low;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = tmp & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński carry = (carry >> kBigitSize) + (tmp >> kBigitSize) +
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (product_high << (32 - kBigitSize));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (carry != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EnsureCapacity(used_digits_ + 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[used_digits_] = carry & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński carry >>= kBigitSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::MultiplyByPowerOfTen(int exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint16_t kFive1 = 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint16_t kFive2 = kFive1 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint16_t kFive3 = kFive2 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint16_t kFive4 = kFive3 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint16_t kFive5 = kFive4 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint16_t kFive6 = kFive5 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint32_t kFive7 = kFive6 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint32_t kFive8 = kFive7 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint32_t kFive9 = kFive8 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint32_t kFive10 = kFive9 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint32_t kFive11 = kFive10 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint32_t kFive12 = kFive11 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint32_t kFive13 = kFive12 * 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint32_t kFive1_to_12[] =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 };
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(exponent >= 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent == 0) return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (used_digits_ == 0) return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int remaining_exponent = exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (remaining_exponent >= 27) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński MultiplyByUInt64(kFive27);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński remaining_exponent -= 27;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (remaining_exponent >= 13) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński MultiplyByUInt32(kFive13);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński remaining_exponent -= 13;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (remaining_exponent > 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ShiftLeft(exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::Square() {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int product_length = 2 * used_digits_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EnsureCapacity(product_length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński UNIMPLEMENTED();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleChunk accumulator = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // First shift the digits so we don't overwrite them.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int copy_offset = used_digits_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[copy_offset + i] = bigits_[i];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // We have two loops to avoid some 'if's in the loop.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Process temporary digit i with power i.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // The sum of the two indices must be equal to i.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int bigit_index1 = i;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int bigit_index2 = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Sum all of the sub-products.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (bigit_index1 >= 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk chunk1 = bigits_[copy_offset + bigit_index1];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk chunk2 = bigits_[copy_offset + bigit_index2];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigit_index1--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigit_index2++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński accumulator >>= kBigitSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = used_digits_; i < product_length; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int bigit_index1 = used_digits_ - 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int bigit_index2 = i - bigit_index1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (bigit_index2 < used_digits_) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk chunk1 = bigits_[copy_offset + bigit_index1];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk chunk2 = bigits_[copy_offset + bigit_index2];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigit_index1--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigit_index2++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński accumulator >>= kBigitSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(accumulator == 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_ = product_length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent_ *= 2;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Clamp();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(base != 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(power_exponent >= 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (power_exponent == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński AssignUInt16(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Zero();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int shifts = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while ((base & 1) == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński base >>= 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński shifts++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int bit_size = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int tmp_base = base;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (tmp_base != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński tmp_base >>= 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bit_size++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int final_size = bit_size * power_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EnsureCapacity(final_size / kBigitSize + 2);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Left to Right exponentiation.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int mask = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (power_exponent >= mask) mask <<= 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński mask >>= 2;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t this_value = base;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool delayed_multipliciation = false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint64_t max_32bits = 0xFFFFFFFF;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (mask != 0 && this_value <= max_32bits) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński this_value = this_value * this_value;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Verify that there is enough space in this_value to perform the
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // multiplication. The first bit_size bits must be 0.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((power_exponent & mask) != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t base_bits_mask =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool high_bits_zero = (this_value & base_bits_mask) == 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (high_bits_zero) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński this_value *= base;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delayed_multipliciation = true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński mask >>= 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński AssignUInt64(this_value);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (delayed_multipliciation) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński MultiplyByUInt32(base);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Now do the same thing as a bignum.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (mask != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Square();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((power_exponent & mask) != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński MultiplyByUInt32(base);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński mask >>= 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // And finally add the saved shifts.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ShiftLeft(shifts * power_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiuint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(other.IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(other.used_digits_ > 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (BigitLength() < other.BigitLength()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Align(other);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint16_t result = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (BigitLength() > other.BigitLength()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(bigits_[used_digits_ - 1] < 0x10000);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += static_cast<uint16_t>(bigits_[used_digits_ - 1]);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński SubtractTimes(other, bigits_[used_digits_ - 1]);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(BigitLength() == other.BigitLength());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk this_bigit = bigits_[used_digits_ - 1];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk other_bigit = other.bigits_[other.used_digits_ - 1];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (other.used_digits_ == 1) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int quotient = this_bigit / other_bigit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(quotient < 0x10000);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += static_cast<uint16_t>(quotient);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Clamp();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int division_estimate = this_bigit / (other_bigit + 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(division_estimate < 0x10000);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += static_cast<uint16_t>(division_estimate);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński SubtractTimes(other, division_estimate);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (other_bigit * (division_estimate + 1) > this_bigit) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (LessEqual(other, *this)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński SubtractBignum(other);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskitemplate<typename S>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic int SizeInHexChars(S number) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(number > 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int result = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (number != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number >>= 4;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic char HexCharOfValue(int value) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(0 <= value && value <= 16);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (value < 10) return static_cast<char>(value + '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return static_cast<char>(value - 10 + 'A');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskibool Bignum::ToHexString(char* buffer, int buffer_size) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Each bigit must be printable as separate hex-character.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(kBigitSize % 4 == 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kHexCharsPerBigit = kBigitSize / 4;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (used_digits_ == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (buffer_size < 2) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[0] = '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[1] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // We add 1 for the terminating '\0' character.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit +
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński SizeInHexChars(bigits_[used_digits_ - 1]) + 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (needed_chars > buffer_size) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int string_index = needed_chars - 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[string_index--] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < exponent_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int j = 0; j < kHexCharsPerBigit; ++j) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[string_index--] = '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < used_digits_ - 1; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk current_bigit = bigits_[i];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int j = 0; j < kHexCharsPerBigit; ++j) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[string_index--] = HexCharOfValue(current_bigit & 0xF);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński current_bigit >>= 4;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // And finally the last bigit.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk most_significant_bigit = bigits_[used_digits_ - 1];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (most_significant_bigit != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński most_significant_bigit >>= 4;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof KosińskiBignum::Chunk Bignum::BigitAt(int index) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (index >= BigitLength()) return 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (index < exponent_) return 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return bigits_[index - exponent_];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiint Bignum::Compare(const Bignum& a, const Bignum& b) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(a.IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(b.IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int bigit_length_a = a.BigitLength();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int bigit_length_b = b.BigitLength();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (bigit_length_a < bigit_length_b) return -1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (bigit_length_a > bigit_length_b) return +1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = bigit_length_a - 1; i >= std::min(a.exponent_, b.exponent_); --i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk bigit_a = a.BigitAt(i);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk bigit_b = b.BigitAt(i);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (bigit_a < bigit_b) return -1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (bigit_a > bigit_b) return +1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiint Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(a.IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(b.IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(c.IsClamped());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (a.BigitLength() < b.BigitLength()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return PlusCompare(b, a, c);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (a.BigitLength() + 1 < c.BigitLength()) return -1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (a.BigitLength() > c.BigitLength()) return +1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return -1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk borrow = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Starting at min_exponent all digits are == 0. So no need to compare them.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int min_exponent = std::min(std::min(a.exponent_, b.exponent_), c.exponent_);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = c.BigitLength() - 1; i >= min_exponent; --i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk chunk_a = a.BigitAt(i);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk chunk_b = b.BigitAt(i);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk chunk_c = c.BigitAt(i);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk sum = chunk_a + chunk_b;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (sum > chunk_c + borrow) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return +1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński borrow = chunk_c + borrow - sum;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (borrow > 1) return -1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński borrow <<= kBigitSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (borrow == 0) return 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return -1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::Clamp() {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (used_digits_ == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Zero.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent_ = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskibool Bignum::IsClamped() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::Zero() {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_ = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent_ = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::Align(const Bignum& other) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent_ > other.exponent_) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int zero_digits = exponent_ - other.exponent_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EnsureCapacity(used_digits_ + zero_digits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = used_digits_ - 1; i >= 0; --i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i + zero_digits] = bigits_[i];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < zero_digits; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_ += zero_digits;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent_ -= zero_digits;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(used_digits_ >= 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(exponent_ >= 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::BigitsShiftLeft(int shift_amount) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(shift_amount < kBigitSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(shift_amount >= 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk carry = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński carry = new_carry;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (carry != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[used_digits_] = carry;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński used_digits_++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid Bignum::SubtractTimes(const Bignum& other, int factor) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(exponent_ <= other.exponent_);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (factor < 3) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < factor; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński SubtractBignum(other);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk borrow = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent_diff = other.exponent_ - exponent_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < other.used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleChunk product = static_cast<DoubleChunk>(factor) * other.bigits_[i];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleChunk remove = borrow + product;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i + exponent_diff] = difference & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński borrow = static_cast<Chunk>((difference >> (kChunkSize - 1)) +
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (remove >> kBigitSize));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (borrow == 0) return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Chunk difference = bigits_[i] - borrow;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bigits_[i] = difference & kBigitMask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński borrow = difference >> (kChunkSize - 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Clamp();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiclass PowersOfTenCache {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskipublic:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kDecimalExponentDistance;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kMinDecimalExponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kMaxDecimalExponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static void GetCachedPowerForBinaryExponentRange(int min_exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int max_exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp* power,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* decimal_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static void GetCachedPowerForDecimalExponent(int requested_exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp* power,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* found_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistruct CachedPower {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t significand;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int16_t binary_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int16_t decimal_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const CachedPower kCachedPowers[] = {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xef340a98, 172aace5), -715, -196},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xaa242499, 697392d3), -183, -36},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xd1b71758, e219652c), -77, -4},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x9c400000, 00000000), -50, 4},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x813f3978, f8940984), 30, 28},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x924d692c, a61be758), 269, 100},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xa59bc234, db398c25), 508, 172},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xd01fef10, a657842c), 800, 260},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340},
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kCachedPowersOffset = 348; // -1 * the first decimal_exponent.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// Difference between the decimal exponents in the table above.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiconst int PowersOfTenCache::kDecimalExponentDistance = 8;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiconst int PowersOfTenCache::kMinDecimalExponent = -348;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiconst int PowersOfTenCache::kMaxDecimalExponent = 340;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int min_exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int max_exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp* power,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* decimal_exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int kQ = DiyFp::kSignificandSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int foo = kCachedPowersOffset;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int index =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(0 <= index && index < kCachedPowersLength);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński CachedPower cached_power = kCachedPowers[index];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(min_exponent <= cached_power.binary_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (void) max_exponent; // Mark variable as used.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(cached_power.binary_exponent <= max_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_exponent = cached_power.decimal_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *power = DiyFp(cached_power.significand, cached_power.binary_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp* power,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* found_exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(kMinDecimalExponent <= requested_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int index =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński CachedPower cached_power = kCachedPowers[index];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *power = DiyFp(cached_power.significand, cached_power.binary_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *found_exponent = cached_power.decimal_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(*found_exponent <= requested_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskienum BignumDtoaMode {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński BIGNUM_DTOA_SHORTEST,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński BIGNUM_DTOA_FIXED,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński BIGNUM_DTOA_PRECISION
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic int NormalizedExponent(uint64_t significand, int exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(significand != 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while ((significand & Double::kHiddenBit) == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significand = significand << 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent = exponent - 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic int EstimatePower(int exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void InitialScaledStartValues(uint64_t significand,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool lower_boundary_is_closer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int estimated_power,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool need_boundary_deltas,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* numerator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* delta_minus,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* delta_plus);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void FixupMultiply10(int estimated_power, bool is_even,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* numerator, Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* delta_minus, Bignum* delta_plus);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* delta_minus, Bignum* delta_plus,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool is_even,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char> buffer, int* length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void BignumToFixed(int requested_digits, int* decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* numerator, Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char>(buffer), int* length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void GenerateCountedDigits(int count, int* decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* numerator, Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char>(buffer), int* length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char> buffer, int* length, int* decimal_point) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(v > 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(!Double(v).IsSpecial());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t significand;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool lower_boundary_is_closer;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significand = Double(v).Significand();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent = Double(v).Exponent();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool need_boundary_deltas =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (mode == BIGNUM_DTOA_SHORTEST);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool is_even = (significand & 1) == 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int normalized_exponent = NormalizedExponent(significand, exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // estimated_power might be too low by 1.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int estimated_power = EstimatePower(normalized_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[0] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = -requested_digits;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum numerator;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum denominator;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum delta_minus;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum delta_plus;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(Bignum::kMaxSignificantBits >= 324*4);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński InitialScaledStartValues(significand, exponent, lower_boundary_is_closer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński estimated_power, need_boundary_deltas,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &numerator, &denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &delta_minus, &delta_plus);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FixupMultiply10(estimated_power, is_even, decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &numerator, &denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &delta_minus, &delta_plus);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński switch (mode) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case BIGNUM_DTOA_SHORTEST:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński GenerateShortestDigits(&numerator, &denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &delta_minus, &delta_plus,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński is_even, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case BIGNUM_DTOA_FIXED:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński BignumToFixed(requested_digits, decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &numerator, &denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case BIGNUM_DTOA_PRECISION:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński GenerateCountedDigits(requested_digits, decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &numerator, &denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński default:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński UNREACHABLE();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[*length] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* delta_minus, Bignum* delta_plus,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool is_even,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char> buffer, int* length) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Bignum::Equal(*delta_minus, *delta_plus)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_plus = delta_minus;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (;;) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint16_t digit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński digit = numerator->DivideModuloIntBignum(*denominator);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(digit <= 9);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[(*length)++] = static_cast<char>(digit + '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool in_delta_room_minus;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool in_delta_room_plus;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (is_even) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński in_delta_room_minus = Bignum::Less(*numerator, *delta_minus);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (is_even) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński in_delta_room_plus =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński in_delta_room_plus =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!in_delta_room_minus && !in_delta_room_plus) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator->Times10();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_minus->Times10();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (delta_minus != delta_plus) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_plus->Times10();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (in_delta_room_minus && in_delta_room_plus) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (compare < 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Remaining digits are less than .5. -> Round down (== do nothing).
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (compare > 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Remaining digits are more than .5 of denominator. -> Round up.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer[(*length) - 1] != '9');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[(*length) - 1]++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((buffer[(*length) - 1] - '0') % 2 == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Round down => Do nothing.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer[(*length) - 1] != '9');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[(*length) - 1]++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (in_delta_room_minus) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else { // in_delta_room_plus
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Round up
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer[(*length) -1] != '9');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[(*length) - 1]++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void GenerateCountedDigits(int count, int* decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* numerator, Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char> buffer, int* length) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(count >= 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < count - 1; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint16_t digit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński digit = numerator->DivideModuloIntBignum(*denominator);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(digit <= 9);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[i] = static_cast<char>(digit + '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator->Times10();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint16_t digit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński digit = numerator->DivideModuloIntBignum(*denominator);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński digit++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(digit <= 10);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[count - 1] = static_cast<char>(digit + '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = count - 1; i > 0; --i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (buffer[i] != '0' + 10) break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[i] = '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[i - 1]++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (buffer[0] == '0' + 10) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[0] = '1';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*decimal_point)++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = count;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void BignumToFixed(int requested_digits, int* decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* numerator, Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char>(buffer), int* length)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (-(*decimal_point) > requested_digits) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = -requested_digits;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (-(*decimal_point) == requested_digits) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(*decimal_point == -requested_digits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński denominator->Times10();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[0] = '1';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*decimal_point)++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int needed_digits = (*decimal_point) + requested_digits;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński GenerateCountedDigits(needed_digits, decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator, denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic int EstimatePower(int exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const double k1Log10 = 0.30102999566398114; // 1/lg(10)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // For doubles len(f) == 53 (don't forget the hidden bit).
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kSignificandSize = Double::kSignificandSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return static_cast<int>(estimate);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void InitialScaledStartValuesPositiveExponent(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t significand, int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int estimated_power, bool need_boundary_deltas,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* numerator, Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* delta_minus, Bignum* delta_plus)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(estimated_power >= 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator->AssignUInt64(significand);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator->ShiftLeft(exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński denominator->AssignPowerUInt16(10, estimated_power);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (need_boundary_deltas) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński denominator->ShiftLeft(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator->ShiftLeft(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_plus->AssignUInt16(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_plus->ShiftLeft(exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_minus->AssignUInt16(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_minus->ShiftLeft(exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void InitialScaledStartValuesNegativeExponentPositivePower(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t significand, int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int estimated_power, bool need_boundary_deltas,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* numerator, Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* delta_minus, Bignum* delta_plus)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator->AssignUInt64(significand);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński denominator->AssignPowerUInt16(10, estimated_power);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński denominator->ShiftLeft(-exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (need_boundary_deltas) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński denominator->ShiftLeft(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator->ShiftLeft(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_plus->AssignUInt16(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_minus->AssignUInt16(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void InitialScaledStartValuesNegativeExponentNegativePower(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t significand, int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int estimated_power, bool need_boundary_deltas,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* numerator, Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* delta_minus, Bignum* delta_plus)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* power_ten = numerator;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński power_ten->AssignPowerUInt16(10, -estimated_power);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (need_boundary_deltas) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_plus->AssignBignum(*power_ten);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_minus->AssignBignum(*power_ten);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(numerator == power_ten);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator->MultiplyByUInt64(significand);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński denominator->AssignUInt16(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński denominator->ShiftLeft(-exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (need_boundary_deltas) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator->ShiftLeft(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński denominator->ShiftLeft(1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void InitialScaledStartValues(uint64_t significand,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool lower_boundary_is_closer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int estimated_power,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool need_boundary_deltas,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* numerator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* delta_minus,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* delta_plus)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent >= 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński InitialScaledStartValuesPositiveExponent(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significand, exponent, estimated_power, need_boundary_deltas,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator, denominator, delta_minus, delta_plus);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (estimated_power >= 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński InitialScaledStartValuesNegativeExponentPositivePower(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significand, exponent, estimated_power, need_boundary_deltas,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator, denominator, delta_minus, delta_plus);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński InitialScaledStartValuesNegativeExponentNegativePower(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significand, exponent, estimated_power, need_boundary_deltas,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator, denominator, delta_minus, delta_plus);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (need_boundary_deltas && lower_boundary_is_closer) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński denominator->ShiftLeft(1); // *2
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator->ShiftLeft(1); // *2
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_plus->ShiftLeft(1); // *2
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void FixupMultiply10(int estimated_power, bool is_even,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* numerator, Bignum* denominator,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum* delta_minus, Bignum* delta_plus) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool in_range;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (is_even) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (in_range) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = estimated_power + 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = estimated_power;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński numerator->Times10();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Bignum::Equal(*delta_minus, *delta_plus)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_minus->Times10();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_plus->AssignBignum(*delta_minus);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_minus->Times10();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński delta_plus->Times10();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskienum FastDtoaMode {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FAST_DTOA_SHORTEST,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FAST_DTOA_PRECISION
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kFastDtoaMaximalLength = 17;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskibool FastDtoa(double d,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FastDtoaMode mode,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kMinimalTargetExponent = -60;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kMaximalTargetExponent = -32;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool RoundWeed(Vector<char> buffer, int length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t distance_too_high_w, uint64_t unsafe_interval,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t rest, uint64_t ten_kappa, uint64_t unit)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t small_distance = distance_too_high_w - unit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t big_distance = distance_too_high_w + unit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(rest <= unsafe_interval);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (rest < small_distance && // Negated condition 1
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński unsafe_interval - rest >= ten_kappa && // Negated condition 2
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (rest + ten_kappa < small_distance || // buffer{-1} > w_high
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński small_distance - rest >= rest + ten_kappa - small_distance)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[length - 1]--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński rest += ten_kappa;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (rest < big_distance &&
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński unsafe_interval - rest >= ten_kappa &&
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (rest + ten_kappa < big_distance ||
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński big_distance - rest > rest + ten_kappa - big_distance)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool RoundWeedCounted(Vector<char> buffer, int length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t rest, uint64_t ten_kappa, uint64_t unit,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* kappa)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(rest < ten_kappa);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (unit >= ten_kappa) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (ten_kappa - unit <= unit) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((ten_kappa - rest > rest) && (ten_kappa - 2 * rest >= 2 * unit)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((rest > unit) && (ten_kappa - (rest - unit) <= (rest - unit))) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[length - 1]++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = length - 1; i > 0; --i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (buffer[i] != '0' + 10) break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[i] = '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[i - 1]++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (buffer[0] == '0' + 10) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[0] = '1';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*kappa) += 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic unsigned int const kSmallPowersOfTen[] =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński 1000000000};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void BiggestPowerTen(uint32_t number,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int number_bits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t* power,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* exponent_plus_one) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(number < (1u << (number_bits + 1)));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent_plus_one_guess = ((number_bits + 1) * 1233 >> 12);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent_plus_one_guess++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (number < kSmallPowersOfTen[exponent_plus_one_guess]) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent_plus_one_guess--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *power = kSmallPowersOfTen[exponent_plus_one_guess];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *exponent_plus_one = exponent_plus_one_guess;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool DigitGen(DiyFp low, DiyFp w, DiyFp high, Vector<char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* length, int* kappa)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(low.e() == w.e() && w.e() == high.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(low.f() + 1 <= high.f() - 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t unit = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp too_low = DiyFp(low.f() - unit, low.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp too_high = DiyFp(high.f() + unit, high.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp unsafe_interval = DiyFp::Minus(too_high, too_low);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t integrals = static_cast<uint32_t>(too_high.f() >> -one.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t fractionals = too_high.f() & (one.f() - 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t divisor;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int divisor_exponent_plus_one;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &divisor, &divisor_exponent_plus_one);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *kappa = divisor_exponent_plus_one;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (*kappa > 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digit = integrals / divisor;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(digit <= 9);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[*length] = static_cast<char>('0' + digit);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*length)++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński integrals %= divisor;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*kappa)--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t rest =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (static_cast<uint64_t>(integrals) << -one.e()) + fractionals;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (rest < unsafe_interval.f()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f(),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński unsafe_interval.f(), rest,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static_cast<uint64_t>(divisor) << -one.e(), unit);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński divisor /= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(one.e() >= -60);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(fractionals < one.f());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (;;) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fractionals *= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński unit *= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński unsafe_interval.set_f(unsafe_interval.f() * 10);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Integer division by one.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digit = static_cast<int>(fractionals >> -one.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(digit <= 9);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[*length] = static_cast<char>('0' + digit);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*length)++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fractionals &= one.f() - 1; // Modulo by one.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*kappa)--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (fractionals < unsafe_interval.f()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f() * unit,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński unsafe_interval.f(), fractionals, one.f(), unit);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool DigitGenCounted(DiyFp w, int requested_digits, Vector<char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* length, int* kappa)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(kMinimalTargetExponent >= -60);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(kMaximalTargetExponent <= -32);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t w_error = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t integrals = static_cast<uint32_t>(w.f() >> -one.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t fractionals = w.f() & (one.f() - 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t divisor;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int divisor_exponent_plus_one;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &divisor, &divisor_exponent_plus_one);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *kappa = divisor_exponent_plus_one;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (*kappa > 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digit = integrals / divisor;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(digit <= 9);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[*length] = static_cast<char>('0' + digit);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*length)++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński requested_digits--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński integrals %= divisor;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*kappa)--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (requested_digits == 0) break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński divisor /= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (requested_digits == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t rest =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (static_cast<uint64_t>(integrals) << -one.e()) + fractionals;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return RoundWeedCounted(buffer, *length, rest,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static_cast<uint64_t>(divisor) << -one.e(), w_error,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński kappa);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(one.e() >= -60);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(fractionals < one.f());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (requested_digits > 0 && fractionals > w_error) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fractionals *= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński w_error *= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Integer division by one.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digit = static_cast<int>(fractionals >> -one.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(digit <= 9);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[*length] = static_cast<char>('0' + digit);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*length)++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński requested_digits--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fractionals &= one.f() - 1; // Modulo by one.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*kappa)--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (requested_digits != 0) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return RoundWeedCounted(buffer, *length, fractionals, one.f(), w_error,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński kappa);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool Grisu3(double v, FastDtoaMode mode, Vector<char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* length, int* decimal_exponent)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp w = Double(v).AsNormalizedDiyFp();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp boundary_minus, boundary_plus;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(mode == FAST_DTOA_SHORTEST);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(boundary_plus.e() == w.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp ten_mk; // Cached power of ten: 10^-k
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int mk; // -k
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int ten_mk_minimal_binary_exponent =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int ten_mk_maximal_binary_exponent =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ten_mk_minimal_binary_exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ten_mk_maximal_binary_exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &ten_mk, &mk);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp::kSignificandSize) &&
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (kMaximalTargetExponent >= w.e() + ten_mk.e() +
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp::kSignificandSize));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp scaled_w = DiyFp::Times(w, ten_mk);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(scaled_w.e() ==
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński boundary_plus.e() + ten_mk.e() + DiyFp::kSignificandSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp scaled_boundary_plus = DiyFp::Times(boundary_plus, ten_mk);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int kappa;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer, length, &kappa);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_exponent = -mk + kappa;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool Grisu3Counted(double v, int requested_digits, Vector<char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* length, int* decimal_exponent)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp w = Double(v).AsNormalizedDiyFp();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp ten_mk; // Cached power of ten: 10^-k
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int mk; // -k
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int ten_mk_minimal_binary_exponent =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int ten_mk_maximal_binary_exponent =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ten_mk_minimal_binary_exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ten_mk_maximal_binary_exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &ten_mk, &mk);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp::kSignificandSize) &&
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (kMaximalTargetExponent >= w.e() + ten_mk.e() +
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp::kSignificandSize));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp scaled_w = DiyFp::Times(w, ten_mk);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int kappa;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool result = DigitGenCounted(scaled_w, requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer, length, &kappa);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_exponent = -mk + kappa;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskibool FastDtoa(double v,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FastDtoaMode mode,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* decimal_point) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(v > 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(!Double(v).IsSpecial());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool result = false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_exponent = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński switch (mode) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case FAST_DTOA_SHORTEST:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result = Grisu3(v, mode, buffer, length, &decimal_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case FAST_DTOA_PRECISION:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result = Grisu3Counted(v, requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer, length, &decimal_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński default:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński UNREACHABLE();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (result) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = *length + decimal_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[*length] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// Represents a 128bit type. This class should be replaced by a native type on
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// platforms that support 128bit integers.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiclass UInt128 {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński public:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński UInt128() : high_bits_(0), low_bits_(0) { }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) { }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void Multiply(uint32_t multiplicand) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t accumulator;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński accumulator = (low_bits_ & kMask32) * multiplicand;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t part = static_cast<uint32_t>(accumulator & kMask32);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński accumulator >>= 32;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński accumulator = accumulator + (low_bits_ >> 32) * multiplicand;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński low_bits_ = (accumulator << 32) + part;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński accumulator >>= 32;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński accumulator = accumulator + (high_bits_ & kMask32) * multiplicand;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński part = static_cast<uint32_t>(accumulator & kMask32);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński accumulator >>= 32;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński accumulator = accumulator + (high_bits_ >> 32) * multiplicand;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński high_bits_ = (accumulator << 32) + part;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT((accumulator >> 32) == 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void Shift(int shift_amount) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(-64 <= shift_amount && shift_amount <= 64);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (shift_amount == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (shift_amount == -64) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński high_bits_ = low_bits_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński low_bits_ = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (shift_amount == 64) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński low_bits_ = high_bits_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński high_bits_ = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (shift_amount <= 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński high_bits_ <<= -shift_amount;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński high_bits_ += low_bits_ >> (64 + shift_amount);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński low_bits_ <<= -shift_amount;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński low_bits_ >>= shift_amount;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński low_bits_ += high_bits_ << (64 - shift_amount);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński high_bits_ >>= shift_amount;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Modifies *this to *this MOD (2^power).
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Returns *this DIV (2^power).
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int DivModPowerOf2(int power) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (power >= 64) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int result = static_cast<int>(high_bits_ >> (power - 64));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński high_bits_ -= static_cast<uint64_t>(result) << (power - 64);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t part_low = low_bits_ >> power;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t part_high = high_bits_ << (64 - power);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int result = static_cast<int>(part_low + part_high);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński high_bits_ = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński low_bits_ -= part_low << power;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool IsZero() const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return high_bits_ == 0 && low_bits_ == 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int BitAt(int position) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (position >= 64) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return static_cast<int>(high_bits_ >> (position - 64)) & 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return static_cast<int>(low_bits_ >> position) & 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński private:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const uint64_t kMask32 = 0xFFFFFFFF;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Value == (high_bits_ << 64) + low_bits_
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t high_bits_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t low_bits_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kDoubleSignificandSize = 53; // Includes the hidden bit.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void FillDigits32FixedLength(uint32_t number, int requested_length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char> buffer, int* length) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = requested_length - 1; i >= 0; --i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[(*length) + i] = '0' + number % 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number /= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length += requested_length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void FillDigits32(uint32_t number, Vector<char> buffer, int* length) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int number_length = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // We fill the digits in reverse order and exchange them afterwards.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (number != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digit = number % 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number /= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[(*length) + number_length] = static_cast<char>('0' + digit);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number_length++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Exchange the digits.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int i = *length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int j = *length + number_length - 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (i < j) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char tmp = buffer[i];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[i] = buffer[j];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[j] = tmp;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński i++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński j--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length += number_length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void FillDigits64FixedLength(uint64_t number,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char> buffer, int* length) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint32_t kTen7 = 10000000;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // For efficiency cut the number into 3 uint32_t parts, and print those.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t part2 = static_cast<uint32_t>(number % kTen7);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number /= kTen7;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t part1 = static_cast<uint32_t>(number % kTen7);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t part0 = static_cast<uint32_t>(number / kTen7);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits32FixedLength(part0, 3, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits32FixedLength(part1, 7, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits32FixedLength(part2, 7, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void FillDigits64(uint64_t number, Vector<char> buffer, int* length) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint32_t kTen7 = 10000000;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // For efficiency cut the number into 3 uint32_t parts, and print those.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t part2 = static_cast<uint32_t>(number % kTen7);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number /= kTen7;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t part1 = static_cast<uint32_t>(number % kTen7);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t part0 = static_cast<uint32_t>(number / kTen7);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (part0 != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits32(part0, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits32FixedLength(part1, 7, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits32FixedLength(part2, 7, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (part1 != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits32(part1, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits32FixedLength(part2, 7, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits32(part2, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void RoundUp(Vector<char> buffer, int* length, int* decimal_point) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // An empty buffer represents 0.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*length == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[0] = '1';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[(*length) - 1]++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = (*length) - 1; i > 0; --i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (buffer[i] != '0' + 10) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[i] = '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[i - 1]++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (buffer[0] == '0' + 10) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[0] = '1';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*decimal_point)++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void FillFractionals(uint64_t fractionals, int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int fractional_count, Vector<char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* length, int* decimal_point)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(-128 <= exponent && exponent <= 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (-exponent <= 64) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(fractionals >> 56 == 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int point = -exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < fractional_count; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (fractionals == 0) break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fractionals *= 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński point--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digit = static_cast<int>(fractionals >> point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(digit <= 9);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[*length] = static_cast<char>('0' + digit);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*length)++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fractionals -= static_cast<uint64_t>(digit) << point;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (((fractionals >> (point - 1)) & 1) == 1) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński RoundUp(buffer, length, decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else { // We need 128 bits.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(64 < -exponent && -exponent <= 128);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński UInt128 fractionals128 = UInt128(fractionals, 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fractionals128.Shift(-exponent - 64);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int point = 128;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < fractional_count; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (fractionals128.IsZero()) break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fractionals128.Multiply(5);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński point--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digit = fractionals128.DivModPowerOf2(point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(digit <= 9);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[*length] = static_cast<char>('0' + digit);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*length)++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (fractionals128.BitAt(point - 1) == 1) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński RoundUp(buffer, length, decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// Removes leading and trailing zeros.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// If leading zeros are removed then the decimal point position is adjusted.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void TrimZeros(Vector<char> buffer, int* length, int* decimal_point) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (*length > 0 && buffer[(*length) - 1] == '0') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (*length)--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int first_non_zero = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (first_non_zero < *length && buffer[first_non_zero] == '0') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński first_non_zero++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (first_non_zero != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = first_non_zero; i < *length; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[i - first_non_zero] = buffer[i];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length -= first_non_zero;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point -= first_non_zero;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskibool FastFixedDtoa(double v,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int fractional_count,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* decimal_point) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint32_t kMaxUInt32 = 0xFFFFFFFF;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t significand = Double(v).Significand();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent = Double(v).Exponent();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent > 20) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (fractional_count > 20) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent + kDoubleSignificandSize > 64) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const uint64_t kFive17 = UINT64_2PART_C(0xB1, A2BC2EC5); // 5^17
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t divisor = kFive17;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int divisor_power = 17;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t dividend = significand;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint32_t quotient;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t remainder;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent > divisor_power) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński dividend <<= exponent - divisor_power;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński quotient = static_cast<uint32_t>(dividend / divisor);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński remainder = (dividend % divisor) << divisor_power;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński divisor <<= divisor_power - exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński quotient = static_cast<uint32_t>(dividend / divisor);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński remainder = (dividend % divisor) << exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits32(quotient, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits64FixedLength(remainder, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = *length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (exponent >= 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // 0 <= exponent <= 11
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significand <<= exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits64(significand, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = *length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (exponent > -kDoubleSignificandSize) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t integrals = significand >> -exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t fractionals = significand - (integrals << -exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (integrals > kMaxUInt32) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits64(integrals, buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillDigits32(static_cast<uint32_t>(integrals), buffer, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = *length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillFractionals(fractionals, exponent, fractional_count,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer, length, decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (exponent < -128) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // This configuration (with at most 20 digits) means that all digits must be
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // 0.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(fractional_count <= 20);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[0] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = -fractional_count;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FillFractionals(significand, exponent, fractional_count,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer, length, decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński TrimZeros(buffer, length, decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[*length] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((*length) == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *decimal_point = -fractional_count;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kMaxExactDoubleIntegerDecimalDigits = 15;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kMaxUint64DecimalDigits = 19;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kMaxDecimalPower = 309;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kMinDecimalPower = -324;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// 2^64 = 18446744073709551616
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kMaxSignificantDecimalDigits = 780;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < buffer.length(); i++) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (buffer[i] != '0') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return buffer.SubVector(i, buffer.length());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Vector<const char>(buffer.start(), 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = buffer.length() - 1; i >= 0; --i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (buffer[i] != '0') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return buffer.SubVector(0, i + 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Vector<const char>(buffer.start(), 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void CutToMaxSignificantDigits(Vector<const char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char* significant_buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* significant_exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significant_buffer[i] = buffer[i];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer[buffer.length() - 1] != '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significant_buffer[kMaxSignificantDecimalDigits - 1] = '1';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *significant_exponent =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent + (buffer.length() - kMaxSignificantDecimalDigits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void TrimAndCut(Vector<const char> buffer, int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char* buffer_copy_space, int space_size,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<const char>* trimmed, int* updated_exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<const char> right_trimmed = TrimTrailingZeros(left_trimmed);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent += left_trimmed.length() - right_trimmed.length();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (right_trimmed.length() > kMaxSignificantDecimalDigits) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (void) space_size; // Mark variable as used.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(space_size >= kMaxSignificantDecimalDigits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński CutToMaxSignificantDigits(right_trimmed, exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer_copy_space, updated_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *trimmed = Vector<const char>(buffer_copy_space,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński kMaxSignificantDecimalDigits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *trimmed = right_trimmed;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *updated_exponent = exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic uint64_t ReadUint64(Vector<const char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* number_of_read_digits) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t result = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int i = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digit = buffer[i++] - '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(0 <= digit && digit <= 9);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result = 10 * result + digit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *number_of_read_digits = i;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic void ReadDiyFp(Vector<const char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp* result,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* remaining_decimals) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int read_digits;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t significand = ReadUint64(buffer, &read_digits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (buffer.length() == read_digits) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *result = DiyFp(significand, 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *remaining_decimals = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Round the significand.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (buffer[read_digits] >= '5') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significand++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Compute the binary exponent.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *result = DiyFp(significand, exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *remaining_decimals = buffer.length() - read_digits;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic DiyFp AdjustmentPowerOfTen(int exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(0 < exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Simply hardcode the remaining powers for the given decimal exponent
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // distance.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński switch (exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński default:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński UNREACHABLE();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool DiyFpStrtod(Vector<const char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double* result) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp input;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int remaining_decimals;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ReadDiyFp(buffer, &input, &remaining_decimals);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kDenominatorLog = 3;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kDenominator = 1 << kDenominatorLog;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Move the remaining decimals into the exponent.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent += remaining_decimals;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int old_e = input.e();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński input.Normalize();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński error <<= old_e - input.e();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent < PowersOfTenCache::kMinDecimalExponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *result = 0.0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp cached_power;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int cached_decimal_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &cached_power,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &cached_decimal_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (cached_decimal_exponent != exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int adjustment_exponent = exponent - cached_decimal_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński input.Multiply(adjustment_power);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // The product of input with the adjustment power fits into a 64 bit
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // integer.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(DiyFp::kSignificandSize == 64);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // The adjustment power is exact. There is hence only an error of 0.5.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński error += kDenominator / 2;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński input.Multiply(cached_power);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int error_b = kDenominator / 2;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int error_ab = (error == 0 ? 0 : 1); // We round up to 1.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int fixed_error = kDenominator / 2;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński error += error_b + error_ab + fixed_error;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński old_e = input.e();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński input.Normalize();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński error <<= old_e - input.e();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int order_of_magnitude = DiyFp::kSignificandSize + input.e();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int effective_significand_size =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int precision_digits_count =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp::kSignificandSize - effective_significand_size;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int shift_amount = (precision_digits_count + kDenominatorLog) -
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp::kSignificandSize + 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński input.set_f(input.f() >> shift_amount);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński input.set_e(input.e() + shift_amount);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński error = (error >> shift_amount) + 1 + kDenominator;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński precision_digits_count -= shift_amount;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(DiyFp::kSignificandSize == 64);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(precision_digits_count < 64);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t one64 = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t precision_bits = input.f() & precision_bits_mask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński uint64_t half_way = one64 << (precision_digits_count - 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński precision_bits *= kDenominator;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński half_way *= kDenominator;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp rounded_input(input.f() >> precision_digits_count,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński input.e() + precision_digits_count);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (precision_bits >= half_way + error) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński rounded_input.set_f(rounded_input.f() + 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *result = Double(rounded_input).value();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (half_way - error < precision_bits && precision_bits < half_way + error) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic int CompareBufferWithDiyFp(Vector<const char> buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp diy_fp) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer.length() + exponent > kMinDecimalPower);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer.length() <= kMaxSignificantDecimalDigits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum buffer_bignum;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Bignum diy_fp_bignum;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer_bignum.AssignDecimalString(buffer);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński diy_fp_bignum.AssignUInt64(diy_fp.f());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent >= 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer_bignum.MultiplyByPowerOfTen(exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński diy_fp_bignum.MultiplyByPowerOfTen(-exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (diy_fp.e() > 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński diy_fp_bignum.ShiftLeft(diy_fp.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer_bignum.ShiftLeft(-diy_fp.e());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Bignum::Compare(buffer_bignum, diy_fp_bignum);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool ComputeGuess(Vector<const char> trimmed, int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double* guess)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (trimmed.length() == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *guess = 0.0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *guess = Double::Infinity();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent + trimmed.length() <= kMinDecimalPower) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *guess = 0.0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (DiyFpStrtod(trimmed, exponent, guess)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*guess == Double::Infinity()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskidouble Strtod(Vector<const char> buffer, int exponent)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char copy_buffer[kMaxSignificantDecimalDigits];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<const char> trimmed;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int updated_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &trimmed, &updated_exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent = updated_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double guess;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool is_correct = ComputeGuess(trimmed, exponent, &guess);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (is_correct) return guess;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DiyFp upper_boundary = Double(guess).UpperBoundary();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (comparison < 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return guess;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (comparison > 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Double(guess).NextDouble();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if ((Double(guess).Significand() & 1) == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Round towards even.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return guess;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Double(guess).NextDouble();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiclass DoubleToStringConverter {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskipublic:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kMaxFixedDigitsBeforePoint = 60;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kMaxFixedDigitsAfterPoint = 60;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kMaxExponentialDigits = 120;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kMinPrecisionDigits = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kMaxPrecisionDigits = 120;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński enum Flags {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński NO_FLAGS = 0,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EMIT_POSITIVE_EXPONENT_SIGN = 1,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EMIT_TRAILING_DECIMAL_POINT = 2,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński EMIT_TRAILING_ZERO_AFTER_POINT = 4,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński UNIQUE_ZERO = 8
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński };
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleToStringConverter(int flags,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* infinity_symbol,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* nan_symbol,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char exponent_character,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_in_shortest_low,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_in_shortest_high,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int max_leading_padding_zeroes_in_precision_mode,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int max_trailing_padding_zeroes_in_precision_mode)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński : flags_(flags),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński infinity_symbol_(infinity_symbol),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński nan_symbol_(nan_symbol),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent_character_(exponent_character),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński decimal_in_shortest_low_(decimal_in_shortest_low),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński decimal_in_shortest_high_(decimal_in_shortest_high),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński max_leading_padding_zeroes_in_precision_mode_(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński max_leading_padding_zeroes_in_precision_mode),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński max_trailing_padding_zeroes_in_precision_mode_(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński max_trailing_padding_zeroes_in_precision_mode) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // When 'trailing zero after the point' is set, then 'trailing point'
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // must be set too.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) ||
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool ToShortest(double value, std::string &s) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return ToShortestIeeeNumber(value, s, SHORTEST);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool ToFixed(double value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &s) const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool ToExponential(double value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &s) const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool ToPrecision(double value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int precision,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &s) const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński enum DtoaMode {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński SHORTEST,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński FIXED, // Produce a fixed number of digits after the decimal point
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński PRECISION // Fixed number of digits (independent of the decimal point)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński };
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static const int kBase10MaximalLength = 17;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // The result should be interpreted as buffer * 10^(point-length).
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static void DoubleToAscii(double v,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DtoaMode mode,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char* buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int buffer_length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool* sign,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński private:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Implementation for ToShortest.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool ToShortestIeeeNumber(double value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &s,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DtoaMode mode) const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool HandleSpecialValues(double value, std::string &s) const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void CreateExponentialRepresentation(const char* decimal_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &s) const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński void CreateDecimalRepresentation(const char* decimal_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digits_after_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &s) const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int flags_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* const infinity_symbol_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* const nan_symbol_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char exponent_character_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int decimal_in_shortest_low_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int decimal_in_shortest_high_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int max_leading_padding_zeroes_in_precision_mode_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int max_trailing_padding_zeroes_in_precision_mode_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiclass StringToDoubleConverter {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński public:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński enum Flags {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński NO_FLAGS = 0,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ALLOW_HEX = 1,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ALLOW_OCTALS = 2,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ALLOW_TRAILING_JUNK = 4,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ALLOW_LEADING_SPACES = 8,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ALLOW_TRAILING_SPACES = 16,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ALLOW_SPACES_AFTER_SIGN = 32
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński };
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński StringToDoubleConverter(int flags,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double empty_string_value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double junk_string_value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* infinity_symbol,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* nan_symbol)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński : flags_(flags),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński empty_string_value_(empty_string_value),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński junk_string_value_(junk_string_value),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński infinity_symbol_(infinity_symbol),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński nan_symbol_(nan_symbol) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double StringToDouble(const char* buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* processed_characters_count) const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński private:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int flags_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const double empty_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const double junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* const infinity_symbol_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* const nan_symbol_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double StringToIeee(const char *start_pointer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* processed_characters_count) const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński};
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskibool DoubleToStringConverter::HandleSpecialValues(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &result) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Double double_inspect(value);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (double_inspect.IsInfinite()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (infinity_symbol_ == NULL) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (value < 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '-';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += infinity_symbol_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (double_inspect.IsNan()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (nan_symbol_ == NULL) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result = nan_symbol_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid DoubleToStringConverter::CreateExponentialRepresentation(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* decimal_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &result) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(length != 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += decimal_digits[0];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (length != 1) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '.';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.append(&decimal_digits[1], length-1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += exponent_character_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent < 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '-';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent = -exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '+';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(exponent < 1e4);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kMaxExponentLength = 5;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char buffer[kMaxExponentLength + 1];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[kMaxExponentLength] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int first_char_pos = kMaxExponentLength;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (exponent > 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[--first_char_pos] = '0' + (exponent % 10);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent /= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.append(&buffer[first_char_pos],
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński kMaxExponentLength - first_char_pos);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid DoubleToStringConverter::CreateDecimalRepresentation(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* decimal_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digits_after_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &result) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Create a representation that is padded with zeros if needed.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (decimal_point <= 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // "0.00000decimal_rep".
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (digits_after_point > 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '.';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.append(-decimal_point, '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(length <= digits_after_point - (-decimal_point));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.append(decimal_digits, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int remaining_digits = digits_after_point - (-decimal_point) - length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.append(remaining_digits, '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (decimal_point >= length) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // "decimal_rep0000.00000" or "decimal_rep.0000"
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.append(decimal_digits, length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.append(decimal_point - length, '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (digits_after_point > 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '.';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.append(digits_after_point, '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // "decima.l_rep000"
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(digits_after_point > 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.append(decimal_digits, decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '.';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(length - decimal_point <= digits_after_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.append(&decimal_digits[decimal_point], length - decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int remaining_digits = digits_after_point - (length - decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result.append(remaining_digits, '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (digits_after_point == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '.';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskibool DoubleToStringConverter::ToShortestIeeeNumber(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &result,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleToStringConverter::DtoaMode mode) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(mode == SHORTEST);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Double(value).IsSpecial()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return HandleSpecialValues(value, result);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_point;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool sign;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kDecimalRepCapacity = kBase10MaximalLength + 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char decimal_rep[kDecimalRepCapacity];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_rep_length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &sign, &decimal_rep_length, &decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (sign && (value != 0.0 || !unique_zero)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '-';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent = decimal_point - 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((decimal_in_shortest_low_ <= exponent) &&
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (exponent < decimal_in_shortest_high_)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::max(0, decimal_rep_length - decimal_point),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent, result);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskibool DoubleToStringConverter::ToFixed(double value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &result) const
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(kMaxFixedDigitsBeforePoint == 60);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const double kFirstNonFixed = 1e60;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Double(value).IsSpecial()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return HandleSpecialValues(value, result);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Find a sufficiently precise decimal representation of n.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_point;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool sign;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Add space for the '\0' byte.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kDecimalRepCapacity =
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char decimal_rep[kDecimalRepCapacity];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_rep_length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleToAscii(value, FIXED, requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński decimal_rep, kDecimalRepCapacity,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &sign, &decimal_rep_length, &decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (sign && (value != 0.0 || !unique_zero)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '-';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński requested_digits, result);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskibool DoubleToStringConverter::ToExponential(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &result) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Double(value).IsSpecial()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return HandleSpecialValues(value, result);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (requested_digits < -1) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (requested_digits > kMaxExponentialDigits) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_point;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool sign;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Add space for digit before the decimal point and the '\0' character.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char decimal_rep[kDecimalRepCapacity];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_rep_length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (requested_digits == -1) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleToAscii(value, SHORTEST, 0,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński decimal_rep, kDecimalRepCapacity,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &sign, &decimal_rep_length, &decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleToAscii(value, PRECISION, requested_digits + 1,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński decimal_rep, kDecimalRepCapacity,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &sign, &decimal_rep_length, &decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(decimal_rep_length <= requested_digits + 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński decimal_rep[i] = '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński decimal_rep_length = requested_digits + 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (sign && (value != 0.0 || !unique_zero)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '-';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent = decimal_point - 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński CreateExponentialRepresentation(decimal_rep,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński decimal_rep_length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent, result);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskibool DoubleToStringConverter::ToPrecision(double value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int precision,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string &result) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Double(value).IsSpecial()) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return HandleSpecialValues(value, result);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Find a sufficiently precise decimal representation of n.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_point;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool sign;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Add one for the terminating null character.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char decimal_rep[kDecimalRepCapacity];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int decimal_rep_length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleToAscii(value, PRECISION, precision,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński decimal_rep, kDecimalRepCapacity,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &sign, &decimal_rep_length, &decimal_point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(decimal_rep_length <= precision);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (sign && (value != 0.0 || !unique_zero)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result += '-';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // The exponent if we print the number as x.xxeyyy. That is with the
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // decimal point after the first digit.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent = decimal_point - 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński (decimal_point - precision + extra_zero >
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński max_trailing_padding_zeroes_in_precision_mode_)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = decimal_rep_length; i < precision; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński decimal_rep[i] = '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński CreateExponentialRepresentation(decimal_rep,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński precision,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::max(0, precision - decimal_point),
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic BignumDtoaMode DtoaToBignumDtoaMode(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleToStringConverter::DtoaMode dtoa_mode) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński switch (dtoa_mode) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński default:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński UNREACHABLE();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskivoid DoubleToStringConverter::DoubleToAscii(double v, DtoaMode mode, int requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char* buffer, int buffer_length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool* sign, int* length, int* point)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Vector<char> vector(buffer, buffer_length);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(!Double(v).IsSpecial());
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(mode == SHORTEST || requested_digits >= 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (Double(v).Sign() < 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *sign = true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński v = -v;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *sign = false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (mode == PRECISION && requested_digits == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński vector[0] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (v == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński vector[0] = '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński vector[1] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *length = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *point = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool fast_worked;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński switch (mode) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case SHORTEST:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case FIXED:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński case PRECISION:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński vector, length, point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński default:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fast_worked = false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński UNREACHABLE();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (fast_worked) return;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // If the fast dtoa didn't succeed use the slower bignum version.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński vector[*length] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskitemplate <class Iterator>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool ConsumeSubString(Iterator* current,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Iterator end,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* substring) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(**current == *substring);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (substring++; *substring != '\0'; substring++) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++*current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*current == end || **current != *substring) return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++*current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiconst int kMaxSignificantDigits = 772;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool isWhitespace(int x) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (x < 128) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (int i = 0; i < kWhitespaceTable7Length; i++) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (kWhitespaceTable7[i] == x) return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// Returns true if a nonspace found and false if the end has reached.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskitemplate <class Iterator>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic inline bool AdvanceToNonspace(Iterator* current, Iterator end) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (*current != end) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!isWhitespace(**current)) return true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++*current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool isDigit(int x, int radix) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return (x >= '0' && x <= '9' && x < '0' + radix)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic double SignedZero(bool sign) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return sign ? -0.0 : 0.0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool IsDecimalDigitForRadix(int c, int radix) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return '0' <= c && c <= '9' && (c - '0') < radix;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return radix > 10 && c >= a_character && c < a_character + radix - 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskitemplate <int radix_log_2, class Iterator>
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistatic double RadixStringToIeee(Iterator* current, Iterator end,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool sign, bool allow_trailing_junk, double junk_string_value,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool* result_is_junk)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(*current != end);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kSignificandSize = Double::kSignificandSize;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *result_is_junk = true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Skip leading 0s.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (**current == '0') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++(*current);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*current == end) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *result_is_junk = false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return SignedZero(sign);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int64_t number = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int radix = (1 << radix_log_2);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński do {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (IsDecimalDigitForRadix(**current, radix)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński digit = static_cast<char>(**current) - '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński digit = static_cast<char>(**current) - 'a' + 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński digit = static_cast<char>(**current) - 'A' + 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number = number * radix + digit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int overflow = static_cast<int>(number >> kSignificandSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (overflow != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Overflow occurred. Need to determine which direction to round the
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // result.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int overflow_bits_count = 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (overflow > 1) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński overflow_bits_count++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński overflow >>= 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number >>= overflow_bits_count;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent = overflow_bits_count;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool zero_tail = true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (;;) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++(*current);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*current == end || !isDigit(**current, radix)) break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński zero_tail = zero_tail && **current == '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent += radix_log_2;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!allow_trailing_junk && AdvanceToNonspace(current, end)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int middle_value = (1 << (overflow_bits_count - 1));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (dropped_bits > middle_value) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number++; // Rounding up.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (dropped_bits == middle_value) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Rounding to even to consistency with decimals: half-way case rounds
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // up if significant part is odd and down otherwise.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((number & 1) != 0 || !zero_tail) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number++; // Rounding up.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Rounding up may cause overflow.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number >>= 1;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński break;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++(*current);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } while (*current != end);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(number < ((int64_t)1 << kSignificandSize));
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *result_is_junk = false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (sign) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (number == 0) return -0.0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński number = -number;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return static_cast<double>(number);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(number != 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return Double(DiyFp(number, exponent)).value();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskidouble StringToDoubleConverter::StringToIeee(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char *input,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* processed_characters_count) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char *current = input;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char *end = input + length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *processed_characters_count = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (current == end) return empty_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (allow_leading_spaces || allow_trailing_spaces) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!AdvanceToNonspace(&current, end)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *processed_characters_count = static_cast<int>(current - input);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return empty_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!allow_leading_spaces && (input != current)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int kBufferSize = kMaxSignificantDigits + 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char buffer[kBufferSize]; // NOLINT: size is known at compile time.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int buffer_pos = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int significant_digits = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int insignificant_digits = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool nonzero_digit_dropped = false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool sign = false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*current == '+' || *current == '-') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński sign = (*current == '-');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char *next_non_space = current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!allow_spaces_after_sign && (current != next_non_space)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński current = next_non_space;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (infinity_symbol_ != NULL) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*current == infinity_symbol_[0]) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!ConsumeSubString(&current, end, infinity_symbol_)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer_pos == 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *processed_characters_count = static_cast<int>(current - input);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return sign ? -Double::Infinity() : Double::Infinity();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (nan_symbol_ != NULL) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*current == nan_symbol_[0]) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!ConsumeSubString(&current, end, nan_symbol_)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer_pos == 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *processed_characters_count = static_cast<int>(current - input);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return sign ? -Double::NaN() : Double::NaN();
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool leading_zero = false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*current == '0') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (current == end) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *processed_characters_count = static_cast<int>(current - input);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return SignedZero(sign);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński leading_zero = true;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // It could be hexadecimal value.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (current == end || !isDigit(*current, 16)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_; // "0x".
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool result_is_junk;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double result = RadixStringToIeee<4>(&current,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński end,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński sign,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński allow_trailing_junk,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński junk_string_value_,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &result_is_junk);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!result_is_junk) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (allow_trailing_spaces) AdvanceToNonspace(&current, end);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *processed_characters_count = static_cast<int>(current - input);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Ignore leading zeros in the integer part.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (*current == '0') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (current == end) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *processed_characters_count = static_cast<int>(current - input);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return SignedZero(sign);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Copy significant digits of the integer part (if any) to the buffer.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (*current >= '0' && *current <= '9') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (significant_digits < kMaxSignificantDigits) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer_pos < kBufferSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[buffer_pos++] = static_cast<char>(*current);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significant_digits++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Will later check if it's an octal in the buffer.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński insignificant_digits++; // Move the digit into the exponential part.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński octal = octal && *current < '8';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (current == end) goto parsing_done;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (significant_digits == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński octal = false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*current == '.') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (octal && !allow_trailing_junk) return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (octal) goto parsing_done;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (current == end) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (significant_digits == 0 && !leading_zero) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński goto parsing_done;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (significant_digits == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // octal = false;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Integer part consists of 0 or is absent. Significant digits start after
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // leading zeros (if any).
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (*current == '0') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (current == end) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *processed_characters_count = static_cast<int>(current - input);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return SignedZero(sign);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent--; // Move this 0 into the exponent.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // There is a fractional part.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // We don't emit a '.', but adjust the exponent instead.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński while (*current >= '0' && *current <= '9') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (significant_digits < kMaxSignificantDigits) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer_pos < kBufferSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[buffer_pos++] = static_cast<char>(*current);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński significant_digits++;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Ignore insignificant digits in the fractional part.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (current == end) goto parsing_done;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!leading_zero && exponent == 0 && significant_digits == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // If leading_zeros is true then the string contains zeros.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // If exponent < 0 then string was [+-]\.0*...
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // If significant_digits != 0 the string is not equal to 0.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Otherwise there are no digits in the string.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Parse exponential part.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*current == 'e' || *current == 'E') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (octal && !allow_trailing_junk) return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (octal) goto parsing_done;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (current == end) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (allow_trailing_junk) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński goto parsing_done;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char sign = '+';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (*current == '+' || *current == '-') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński sign = static_cast<char>(*current);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (current == end) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (allow_trailing_junk) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński goto parsing_done;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (current == end || *current < '0' || *current > '9') {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (allow_trailing_junk) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński goto parsing_done;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const int max_exponent = INT_MAX / 2;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int num = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński do {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // Check overflow.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int digit = *current - '0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (num >= max_exponent / 10
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński num = max_exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński num = num * 10 + digit;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ++current;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } while (current != end && *current >= '0' && *current <= '9');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent += (sign == '-' ? -num : num);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return junk_string_value_;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (allow_trailing_spaces) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński AdvanceToNonspace(&current, end);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński parsing_done:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent += insignificant_digits;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (octal) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool result_is_junk;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char* start = buffer;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński result = RadixStringToIeee<3>(&start,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer + buffer_pos,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński sign,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński allow_trailing_junk,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński junk_string_value_,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński &result_is_junk);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(!result_is_junk);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *processed_characters_count = static_cast<int>(current - input);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return result;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (nonzero_digit_dropped) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[buffer_pos++] = '1';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent--;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ASSERT(buffer_pos < kBufferSize);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński buffer[buffer_pos] = '\0';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński *processed_characters_count = static_cast<int>(current - input);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return sign? -converted: converted;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskidouble StringToDoubleConverter::StringToDouble(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński const char* buffer,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int* processed_characters_count) const {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return StringToIeee(buffer, length, processed_characters_count);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński} // end anonymous namespace
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistd::string format_coord_shortest(Coord x)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char buf[20];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński bool sign;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int length, point;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleToStringConverter::DoubleToAscii(x, DoubleToStringConverter::SHORTEST,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński 0, buf, 20, &sign, &length, &point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int exponent = point - length;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string ret;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret.reserve(32);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (sign) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret += '-';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent == 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // return digits without any changes
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret += buf;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (point >= 0 && point <= length) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // insert decimal point
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret.append(buf, point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret += '.';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret.append(&buf[point], length - point);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (exponent > 0 && exponent <= 2) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // add trailing zeroes
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret += buf;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret.append(exponent, '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else if (point >= -3 && point <= -1) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // add leading zeroes
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret += '.';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret.append(-point, '0');
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret += buf;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński } else {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // exponential form
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret += buf;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret += 'e';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński if (exponent < 0) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret += '-';
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent = -exponent;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński /* Convert exponent by hand.
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * Using ostringstream is ~3x slower */
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int const buflen = 6;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int i = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński char expdigits[buflen+1];
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński expdigits[buflen] = 0;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński for (; exponent && i < buflen; ++i) {
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński expdigits[buflen - 1 - i] = '0' + (exponent % 10);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński exponent /= 10;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret.append(&expdigits[buflen - i]);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return ret;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskistd::string format_coord_nice(Coord x)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static DoubleToStringConverter conv(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński DoubleToStringConverter::UNIQUE_ZERO,
e4369b05aaa20df73a37f4d319ce456865cc74f3Krzysztof Kosiński "inf", "NaN", 'e', -6, 21, 0, 0);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński std::string ret;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński ret.reserve(32);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński conv.ToShortest(x, ret);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return ret;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof KosińskiCoord parse_coord(std::string const &s)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński{
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński static StringToDoubleConverter conv(
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński StringToDoubleConverter::ALLOW_LEADING_SPACES |
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński StringToDoubleConverter::ALLOW_TRAILING_SPACES |
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN,
e4369b05aaa20df73a37f4d319ce456865cc74f3Krzysztof Kosiński 0.0, nan(""), "inf", "NaN");
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński int dummy;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński return conv.StringToDouble(s.c_str(), s.length(), &dummy);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński} // namespace Geom
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński/*
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński Local Variables:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński mode:c++
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński c-file-style:"stroustrup"
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński indent-tabs-mode:nil
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński fill-column:99
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński End:
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński*/
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :