mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Merge branch 'master' into zvonand-implicit-tz
This commit is contained in:
commit
984e8fde41
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -7,11 +7,11 @@ tests/ci/run_check.py
|
||||
### Changelog category (leave one):
|
||||
- New Feature
|
||||
- Improvement
|
||||
- Bug Fix (user-visible misbehavior in an official stable release)
|
||||
- Performance Improvement
|
||||
- Backward Incompatible Change
|
||||
- Build/Testing/Packaging Improvement
|
||||
- Documentation (changelog entry is not required)
|
||||
- Bug Fix (user-visible misbehavior in an official stable release)
|
||||
- Not for changelog (changelog entry is not required)
|
||||
|
||||
|
||||
|
38
.github/workflows/pull_request.yml
vendored
38
.github/workflows/pull_request.yml
vendored
@ -4846,3 +4846,41 @@ jobs:
|
||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||
python3 finish_check.py
|
||||
python3 merge_pr.py --check-approved
|
||||
##############################################################################################
|
||||
########################### SQLLOGIC TEST ###################################################
|
||||
##############################################################################################
|
||||
SQLLogicTestRelease:
|
||||
needs: [BuilderDebRelease]
|
||||
runs-on: [self-hosted, func-tester]
|
||||
steps:
|
||||
- name: Set envs
|
||||
run: |
|
||||
cat >> "$GITHUB_ENV" << 'EOF'
|
||||
TEMP_PATH=${{runner.temp}}/sqllogic_debug
|
||||
REPORTS_PATH=${{runner.temp}}/reports_dir
|
||||
CHECK_NAME=Sqllogic test (release)
|
||||
REPO_COPY=${{runner.temp}}/sqllogic_debug/ClickHouse
|
||||
KILL_TIMEOUT=10800
|
||||
EOF
|
||||
- name: Download json reports
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: ${{ env.REPORTS_PATH }}
|
||||
- name: Clear repository
|
||||
run: |
|
||||
sudo rm -fr "$GITHUB_WORKSPACE" && mkdir "$GITHUB_WORKSPACE"
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v2
|
||||
- name: Sqllogic test
|
||||
run: |
|
||||
sudo rm -fr "$TEMP_PATH"
|
||||
mkdir -p "$TEMP_PATH"
|
||||
cp -r "$GITHUB_WORKSPACE" "$TEMP_PATH"
|
||||
cd "$REPO_COPY/tests/ci"
|
||||
python3 sqllogic_test.py "$CHECK_NAME" "$KILL_TIMEOUT"
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: |
|
||||
docker ps --quiet | xargs --no-run-if-empty docker kill ||:
|
||||
docker ps --all --quiet | xargs --no-run-if-empty docker rm -f ||:
|
||||
sudo rm -fr "$TEMP_PATH"
|
||||
|
@ -393,7 +393,11 @@ else()
|
||||
endif ()
|
||||
|
||||
option (ENABLE_GWP_ASAN "Enable Gwp-Asan" ON)
|
||||
if (NOT OS_LINUX AND NOT OS_ANDROID)
|
||||
# We use mmap for allocations more heavily in debug builds,
|
||||
# but GWP-ASan also wants to use mmap frequently,
|
||||
# and due to a large number of memory mappings,
|
||||
# it does not work together well.
|
||||
if ((NOT OS_LINUX AND NOT OS_ANDROID) OR (CMAKE_BUILD_TYPE_UC STREQUAL "DEBUG"))
|
||||
set(ENABLE_GWP_ASAN OFF)
|
||||
endif ()
|
||||
|
||||
|
@ -21,10 +21,10 @@ curl https://clickhouse.com/ | sh
|
||||
* [Contacts](https://clickhouse.com/company/contact) can help to get your questions answered if there are any.
|
||||
|
||||
## Upcoming Events
|
||||
* [**ClickHouse Meetup in Austin**](https://www.meetup.com/clickhouse-austin-user-group/events/291486654/) - Mar 30 - The first ClickHouse Meetup in Austin is happening soon! Interested in speaking, let us know!
|
||||
* [**v23.3 Release Webinar**](https://clickhouse.com/company/events/v23-3-release-webinar?utm_source=github&utm_medium=social&utm_campaign=release-webinar-2023-02) - Mar 30 - 23.3 is rapidly approaching. Original creator, co-founder, and CTO of ClickHouse Alexey Milovidov will walk us through the highlights of the release.
|
||||
* [**ClickHouse Spring Meetup in Manhattan**](https://www.meetup.com/clickhouse-new-york-user-group/events/292517734) - April 26 - It's spring, and it's time to meet again in the city! Talks include: "Building a domain specific query language on top of Clickhouse", "A Galaxy of Information", "Our Journey to ClickHouse Cloud from Redshift", and a ClickHouse update!
|
||||
* [**v23.4 Release Webinar**](https://clickhouse.com/company/events/v23-4-release-webinar?utm_source=github&utm_medium=social&utm_campaign=release-webinar-2023-04) - April 26 - 23.4 is rapidly approaching. Original creator, co-founder, and CTO of ClickHouse Alexey Milovidov will walk us through the highlights of the release.
|
||||
|
||||
## Recent Recordings
|
||||
* **FOSDEM 2023**: In the "Fast and Streaming Data" room Alexey gave a talk entitled "Building Analytical Apps With ClickHouse" that looks at the landscape of data tools, an interesting data set, and how you can interact with data quickly. Check out the recording on **[YouTube](https://www.youtube.com/watch?v=JlcI2Vfz_uk)**.
|
||||
* **Recording available**: [**v23.2 Release Webinar**](https://www.youtube.com/watch?v=2o0vRMMIrkY) NTILE Window Function support, Partition Key for GROUP By, io_uring, Apache Iceberg support, Dynamic Disks, integrations updates! Watch it now!
|
||||
* **Recent Meetup Videos**: [Meetup Playlist](https://www.youtube.com/playlist?list=PL0Z2YDlm0b3iNDUzpY1S3L_iV4nARda_U) Whenever possible recordings of the ClickHouse Community Meetups are edited and presented as individual talks. Current featuring "Modern SQL in 2023", "Fast, Concurrent, and Consistent Asynchronous INSERTS in ClickHouse", and "Full-Text Indices: Design and Experiments"
|
||||
* **Recording available**: [**v23.3 Release Webinar**](https://www.youtube.com/watch?v=ISaGUjvBNao) UNDROP TABLE, server settings introspection, nested dynamic disks, MySQL compatibility, parseDate Time, Lightweight Deletes, Parallel Replicas, integrations updates, and so much more! Watch it now!
|
||||
* **All release webinar recordings**: [YouTube playlist](https://www.youtube.com/playlist?list=PL0Z2YDlm0b3jAlSy1JxyP8zluvXaN3nxU)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <base/extended_types.h>
|
||||
#include <base/Decimal_fwd.h>
|
||||
|
||||
#if !defined(NO_SANITIZE_UNDEFINED)
|
||||
#if defined(__clang__)
|
||||
@ -19,23 +20,6 @@ using Decimal64 = Decimal<Int64>;
|
||||
using Decimal128 = Decimal<Int128>;
|
||||
using Decimal256 = Decimal<Int256>;
|
||||
|
||||
template <class T>
|
||||
concept is_decimal =
|
||||
std::is_same_v<T, Decimal32>
|
||||
|| std::is_same_v<T, Decimal64>
|
||||
|| std::is_same_v<T, Decimal128>
|
||||
|| std::is_same_v<T, Decimal256>
|
||||
|| std::is_same_v<T, DateTime64>;
|
||||
|
||||
template <class T>
|
||||
concept is_over_big_int =
|
||||
std::is_same_v<T, Int128>
|
||||
|| std::is_same_v<T, UInt128>
|
||||
|| std::is_same_v<T, Int256>
|
||||
|| std::is_same_v<T, UInt256>
|
||||
|| std::is_same_v<T, Decimal128>
|
||||
|| std::is_same_v<T, Decimal256>;
|
||||
|
||||
template <class T> struct NativeTypeT { using Type = T; };
|
||||
template <is_decimal T> struct NativeTypeT<T> { using Type = typename T::NativeType; };
|
||||
template <class T> using NativeType = typename NativeTypeT<T>::Type;
|
||||
|
46
base/base/Decimal_fwd.h
Normal file
46
base/base/Decimal_fwd.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <base/types.h>
|
||||
|
||||
namespace wide
|
||||
{
|
||||
|
||||
template <size_t Bits, typename Signed>
|
||||
class integer;
|
||||
|
||||
}
|
||||
|
||||
using Int128 = wide::integer<128, signed>;
|
||||
using UInt128 = wide::integer<128, unsigned>;
|
||||
using Int256 = wide::integer<256, signed>;
|
||||
using UInt256 = wide::integer<256, unsigned>;
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
template <class> struct Decimal;
|
||||
|
||||
using Decimal32 = Decimal<Int32>;
|
||||
using Decimal64 = Decimal<Int64>;
|
||||
using Decimal128 = Decimal<Int128>;
|
||||
using Decimal256 = Decimal<Int256>;
|
||||
|
||||
class DateTime64;
|
||||
|
||||
template <class T>
|
||||
concept is_decimal =
|
||||
std::is_same_v<T, Decimal32>
|
||||
|| std::is_same_v<T, Decimal64>
|
||||
|| std::is_same_v<T, Decimal128>
|
||||
|| std::is_same_v<T, Decimal256>
|
||||
|| std::is_same_v<T, DateTime64>;
|
||||
|
||||
template <class T>
|
||||
concept is_over_big_int =
|
||||
std::is_same_v<T, Int128>
|
||||
|| std::is_same_v<T, UInt128>
|
||||
|| std::is_same_v<T, Int256>
|
||||
|| std::is_same_v<T, UInt256>
|
||||
|| std::is_same_v<T, Decimal128>
|
||||
|| std::is_same_v<T, Decimal256>;
|
||||
}
|
@ -51,3 +51,15 @@ namespace DB
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<DB::IPv6>
|
||||
{
|
||||
size_t operator()(const DB::IPv6 & x) const
|
||||
{
|
||||
return std::hash<DB::IPv6::UnderlyingType>()(x.toUnderType());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -233,7 +233,8 @@ target_link_libraries (_poco_foundation
|
||||
PRIVATE
|
||||
Poco::Foundation::PCRE
|
||||
ch_contrib::zlib
|
||||
ch_contrib::lz4)
|
||||
ch_contrib::lz4
|
||||
ch_contrib::double_conversion)
|
||||
|
||||
if(OS_DARWIN AND ARCH_AARCH64)
|
||||
target_compile_definitions (_poco_foundation
|
||||
|
@ -14,23 +14,9 @@
|
||||
|
||||
#include "Poco/Bugcheck.h"
|
||||
|
||||
|
||||
// +++ double conversion +++
|
||||
#define double_conversion poco_double_conversion // don't collide with standalone double_conversion library
|
||||
#define UNREACHABLE poco_bugcheck
|
||||
#define UNIMPLEMENTED poco_bugcheck
|
||||
#include "diy-fp.cc"
|
||||
#include "cached-powers.cc"
|
||||
#include "bignum-dtoa.cc"
|
||||
#include "bignum.cc"
|
||||
#include "fast-dtoa.cc"
|
||||
#include "fixed-dtoa.cc"
|
||||
#include "strtod.cc"
|
||||
#include "double-conversion.cc"
|
||||
// --- double conversion ---
|
||||
#include <double-conversion/double-conversion.h>
|
||||
|
||||
#include "Poco/NumericString.h"
|
||||
poco_static_assert(POCO_MAX_FLT_STRING_LEN == double_conversion::kMaxSignificantDecimalDigits);
|
||||
#include "Poco/String.h"
|
||||
#include <memory>
|
||||
#include <cctype>
|
||||
@ -263,7 +249,7 @@ float strToFloat(const char* str)
|
||||
int processed;
|
||||
int flags = StringToDoubleConverter::ALLOW_LEADING_SPACES |
|
||||
StringToDoubleConverter::ALLOW_TRAILING_SPACES;
|
||||
StringToDoubleConverter converter(flags, 0.0, Single::NaN(), POCO_FLT_INF, POCO_FLT_NAN);
|
||||
StringToDoubleConverter converter(flags, 0.0, std::numeric_limits<float>::quiet_NaN(), POCO_FLT_INF, POCO_FLT_NAN);
|
||||
float result = converter.StringToFloat(str, static_cast<int>(strlen(str)), &processed);
|
||||
return result;
|
||||
}
|
||||
@ -275,7 +261,7 @@ double strToDouble(const char* str)
|
||||
int processed;
|
||||
int flags = StringToDoubleConverter::ALLOW_LEADING_SPACES |
|
||||
StringToDoubleConverter::ALLOW_TRAILING_SPACES;
|
||||
StringToDoubleConverter converter(flags, 0.0, Double::NaN(), POCO_FLT_INF, POCO_FLT_NAN);
|
||||
StringToDoubleConverter converter(flags, 0.0, std::numeric_limits<double>::quiet_NaN(), POCO_FLT_INF, POCO_FLT_NAN);
|
||||
double result = converter.StringToDouble(str, static_cast<int>(strlen(str)), &processed);
|
||||
return result;
|
||||
}
|
||||
|
@ -1,188 +0,0 @@
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2011, 2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
#define local static
|
||||
|
||||
local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
|
||||
|
||||
#define BASE 65521U /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
|
||||
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
|
||||
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
|
||||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
/* use NO_DIVIDE if your processor does not do division in hardware --
|
||||
try it both ways to see which is faster */
|
||||
#ifdef NO_DIVIDE
|
||||
/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
|
||||
(thank you to John Reiser for pointing this out) */
|
||||
# define CHOP(a) \
|
||||
do { \
|
||||
unsigned long tmp = a >> 16; \
|
||||
a &= 0xffffUL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
} while (0)
|
||||
# define MOD28(a) \
|
||||
do { \
|
||||
CHOP(a); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
CHOP(a); \
|
||||
MOD28(a); \
|
||||
} while (0)
|
||||
# define MOD63(a) \
|
||||
do { /* this assumes a is not negative */ \
|
||||
z_off64_t tmp = a >> 32; \
|
||||
a &= 0xffffffffL; \
|
||||
a += (tmp << 8) - (tmp << 5) + tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
# define MOD28(a) a %= BASE
|
||||
# define MOD63(a) a %= BASE
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32_z(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
z_size_t len;
|
||||
{
|
||||
unsigned long sum2;
|
||||
unsigned n;
|
||||
|
||||
/* split Adler-32 into component sums */
|
||||
sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1) {
|
||||
adler += buf[0];
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf == Z_NULL)
|
||||
return 1L;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16) {
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
MOD28(sum2); /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
do {
|
||||
DO16(buf); /* 16 sums unrolled */
|
||||
buf += 16;
|
||||
} while (--n);
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||
if (len) { /* avoid modulos if none remaining */
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
}
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
return adler32_z(adler, buf, len);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local uLong adler32_combine_(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
unsigned long sum1;
|
||||
unsigned long sum2;
|
||||
unsigned rem;
|
||||
|
||||
/* for negative len, return invalid adler32 as a clue for debugging */
|
||||
if (len2 < 0)
|
||||
return 0xffffffffUL;
|
||||
|
||||
/* the derivation of this formula is left as an exercise for the reader */
|
||||
MOD63(len2); /* assumes len2 >= 0 */
|
||||
rem = (unsigned)len2;
|
||||
sum1 = adler1 & 0xffff;
|
||||
sum2 = rem * sum1;
|
||||
MOD(sum2);
|
||||
sum1 += (adler2 & 0xffff) + BASE - 1;
|
||||
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
|
||||
if (sum2 >= BASE) sum2 -= BASE;
|
||||
return sum1 | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off_t len2;
|
||||
{
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
||||
|
||||
uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
@ -1,641 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "bignum-dtoa.h"
|
||||
|
||||
#include "bignum.h"
|
||||
#include "ieee.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
static int NormalizedExponent(uint64_t significand, int exponent) {
|
||||
ASSERT(significand != 0);
|
||||
while ((significand & Double::kHiddenBit) == 0) {
|
||||
significand = significand << 1;
|
||||
exponent = exponent - 1;
|
||||
}
|
||||
return exponent;
|
||||
}
|
||||
|
||||
|
||||
// Forward declarations:
|
||||
// Returns an estimation of k such that 10^(k-1) <= v < 10^k.
|
||||
static int EstimatePower(int exponent);
|
||||
// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
|
||||
// and denominator.
|
||||
static void InitialScaledStartValues(uint64_t significand,
|
||||
int exponent,
|
||||
bool lower_boundary_is_closer,
|
||||
int estimated_power,
|
||||
bool need_boundary_deltas,
|
||||
Bignum* numerator,
|
||||
Bignum* denominator,
|
||||
Bignum* delta_minus,
|
||||
Bignum* delta_plus);
|
||||
// Multiplies numerator/denominator so that its values lies in the range 1-10.
|
||||
// Returns decimal_point s.t.
|
||||
// v = numerator'/denominator' * 10^(decimal_point-1)
|
||||
// where numerator' and denominator' are the values of numerator and
|
||||
// denominator after the call to this function.
|
||||
static void FixupMultiply10(int estimated_power, bool is_even,
|
||||
int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus);
|
||||
// Generates digits from the left to the right and stops when the generated
|
||||
// digits yield the shortest decimal representation of v.
|
||||
static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus,
|
||||
bool is_even,
|
||||
Vector<char> buffer, int* length);
|
||||
// Generates 'requested_digits' after the decimal point.
|
||||
static void BignumToFixed(int requested_digits, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char>(buffer), int* length);
|
||||
// Generates 'count' digits of numerator/denominator.
|
||||
// Once 'count' digits have been produced rounds the result depending on the
|
||||
// remainder (remainders of exactly .5 round upwards). Might update the
|
||||
// decimal_point when rounding up (for example for 0.9999).
|
||||
static void GenerateCountedDigits(int count, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char>(buffer), int* length);
|
||||
|
||||
|
||||
void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
|
||||
Vector<char> buffer, int* length, int* decimal_point) {
|
||||
ASSERT(v > 0);
|
||||
ASSERT(!Double(v).IsSpecial());
|
||||
uint64_t significand;
|
||||
int exponent;
|
||||
bool lower_boundary_is_closer;
|
||||
if (mode == BIGNUM_DTOA_SHORTEST_SINGLE) {
|
||||
float f = static_cast<float>(v);
|
||||
ASSERT(f == v);
|
||||
significand = Single(f).Significand();
|
||||
exponent = Single(f).Exponent();
|
||||
lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser();
|
||||
} else {
|
||||
significand = Double(v).Significand();
|
||||
exponent = Double(v).Exponent();
|
||||
lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser();
|
||||
}
|
||||
bool need_boundary_deltas =
|
||||
(mode == BIGNUM_DTOA_SHORTEST || mode == BIGNUM_DTOA_SHORTEST_SINGLE);
|
||||
|
||||
bool is_even = (significand & 1) == 0;
|
||||
int normalized_exponent = NormalizedExponent(significand, exponent);
|
||||
// estimated_power might be too low by 1.
|
||||
int estimated_power = EstimatePower(normalized_exponent);
|
||||
|
||||
// Shortcut for Fixed.
|
||||
// The requested digits correspond to the digits after the point. If the
|
||||
// number is much too small, then there is no need in trying to get any
|
||||
// digits.
|
||||
if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) {
|
||||
buffer[0] = '\0';
|
||||
*length = 0;
|
||||
// Set decimal-point to -requested_digits. This is what Gay does.
|
||||
// Note that it should not have any effect anyways since the string is
|
||||
// empty.
|
||||
*decimal_point = -requested_digits;
|
||||
return;
|
||||
}
|
||||
|
||||
Bignum numerator;
|
||||
Bignum denominator;
|
||||
Bignum delta_minus;
|
||||
Bignum delta_plus;
|
||||
// Make sure the bignum can grow large enough. The smallest double equals
|
||||
// 4e-324. In this case the denominator needs fewer than 324*4 binary digits.
|
||||
// The maximum double is 1.7976931348623157e308 which needs fewer than
|
||||
// 308*4 binary digits.
|
||||
ASSERT(Bignum::kMaxSignificantBits >= 324*4);
|
||||
InitialScaledStartValues(significand, exponent, lower_boundary_is_closer,
|
||||
estimated_power, need_boundary_deltas,
|
||||
&numerator, &denominator,
|
||||
&delta_minus, &delta_plus);
|
||||
// We now have v = (numerator / denominator) * 10^estimated_power.
|
||||
FixupMultiply10(estimated_power, is_even, decimal_point,
|
||||
&numerator, &denominator,
|
||||
&delta_minus, &delta_plus);
|
||||
// We now have v = (numerator / denominator) * 10^(decimal_point-1), and
|
||||
// 1 <= (numerator + delta_plus) / denominator < 10
|
||||
switch (mode) {
|
||||
case BIGNUM_DTOA_SHORTEST:
|
||||
case BIGNUM_DTOA_SHORTEST_SINGLE:
|
||||
GenerateShortestDigits(&numerator, &denominator,
|
||||
&delta_minus, &delta_plus,
|
||||
is_even, buffer, length);
|
||||
break;
|
||||
case BIGNUM_DTOA_FIXED:
|
||||
BignumToFixed(requested_digits, decimal_point,
|
||||
&numerator, &denominator,
|
||||
buffer, length);
|
||||
break;
|
||||
case BIGNUM_DTOA_PRECISION:
|
||||
GenerateCountedDigits(requested_digits, decimal_point,
|
||||
&numerator, &denominator,
|
||||
buffer, length);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
buffer[*length] = '\0';
|
||||
}
|
||||
|
||||
|
||||
// The procedure starts generating digits from the left to the right and stops
|
||||
// when the generated digits yield the shortest decimal representation of v. A
|
||||
// decimal representation of v is a number lying closer to v than to any other
|
||||
// double, so it converts to v when read.
|
||||
//
|
||||
// This is true if d, the decimal representation, is between m- and m+, the
|
||||
// upper and lower boundaries. d must be strictly between them if !is_even.
|
||||
// m- := (numerator - delta_minus) / denominator
|
||||
// m+ := (numerator + delta_plus) / denominator
|
||||
//
|
||||
// Precondition: 0 <= (numerator+delta_plus) / denominator < 10.
|
||||
// If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit
|
||||
// will be produced. This should be the standard precondition.
|
||||
static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus,
|
||||
bool is_even,
|
||||
Vector<char> buffer, int* length) {
|
||||
// Small optimization: if delta_minus and delta_plus are the same just reuse
|
||||
// one of the two bignums.
|
||||
if (Bignum::Equal(*delta_minus, *delta_plus)) {
|
||||
delta_plus = delta_minus;
|
||||
}
|
||||
*length = 0;
|
||||
for (;;) {
|
||||
uint16_t digit;
|
||||
digit = numerator->DivideModuloIntBignum(*denominator);
|
||||
ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
|
||||
// digit = numerator / denominator (integer division).
|
||||
// numerator = numerator % denominator.
|
||||
buffer[(*length)++] = static_cast<char>(digit + '0');
|
||||
|
||||
// Can we stop already?
|
||||
// If the remainder of the division is less than the distance to the lower
|
||||
// boundary we can stop. In this case we simply round down (discarding the
|
||||
// remainder).
|
||||
// Similarly we test if we can round up (using the upper boundary).
|
||||
bool in_delta_room_minus;
|
||||
bool in_delta_room_plus;
|
||||
if (is_even) {
|
||||
in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus);
|
||||
} else {
|
||||
in_delta_room_minus = Bignum::Less(*numerator, *delta_minus);
|
||||
}
|
||||
if (is_even) {
|
||||
in_delta_room_plus =
|
||||
Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
|
||||
} else {
|
||||
in_delta_room_plus =
|
||||
Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
|
||||
}
|
||||
if (!in_delta_room_minus && !in_delta_room_plus) {
|
||||
// Prepare for next iteration.
|
||||
numerator->Times10();
|
||||
delta_minus->Times10();
|
||||
// We optimized delta_plus to be equal to delta_minus (if they share the
|
||||
// same value). So don't multiply delta_plus if they point to the same
|
||||
// object.
|
||||
if (delta_minus != delta_plus) {
|
||||
delta_plus->Times10();
|
||||
}
|
||||
} else if (in_delta_room_minus && in_delta_room_plus) {
|
||||
// Let's see if 2*numerator < denominator.
|
||||
// If yes, then the next digit would be < 5 and we can round down.
|
||||
int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator);
|
||||
if (compare < 0) {
|
||||
// Remaining digits are less than .5. -> Round down (== do nothing).
|
||||
} else if (compare > 0) {
|
||||
// Remaining digits are more than .5 of denominator. -> Round up.
|
||||
// Note that the last digit could not be a '9' as otherwise the whole
|
||||
// loop would have stopped earlier.
|
||||
// We still have an assert here in case the preconditions were not
|
||||
// satisfied.
|
||||
ASSERT(buffer[(*length) - 1] != '9');
|
||||
buffer[(*length) - 1]++;
|
||||
} else {
|
||||
// Halfway case.
|
||||
// TODO(floitsch): need a way to solve half-way cases.
|
||||
// For now let's round towards even (since this is what Gay seems to
|
||||
// do).
|
||||
|
||||
if ((buffer[(*length) - 1] - '0') % 2 == 0) {
|
||||
// Round down => Do nothing.
|
||||
} else {
|
||||
ASSERT(buffer[(*length) - 1] != '9');
|
||||
buffer[(*length) - 1]++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (in_delta_room_minus) {
|
||||
// Round down (== do nothing).
|
||||
return;
|
||||
} else { // in_delta_room_plus
|
||||
// Round up.
|
||||
// Note again that the last digit could not be '9' since this would have
|
||||
// stopped the loop earlier.
|
||||
// We still have an ASSERT here, in case the preconditions were not
|
||||
// satisfied.
|
||||
ASSERT(buffer[(*length) -1] != '9');
|
||||
buffer[(*length) - 1]++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Let v = numerator / denominator < 10.
|
||||
// Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)
|
||||
// from left to right. Once 'count' digits have been produced we decide whether
|
||||
// to round up or down. Remainders of exactly .5 round upwards. Numbers such
|
||||
// as 9.999999 propagate a carry all the way, and change the
|
||||
// exponent (decimal_point), when rounding upwards.
|
||||
static void GenerateCountedDigits(int count, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char> buffer, int* length) {
|
||||
ASSERT(count >= 0);
|
||||
for (int i = 0; i < count - 1; ++i) {
|
||||
uint16_t digit;
|
||||
digit = numerator->DivideModuloIntBignum(*denominator);
|
||||
ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
|
||||
// digit = numerator / denominator (integer division).
|
||||
// numerator = numerator % denominator.
|
||||
buffer[i] = static_cast<char>(digit + '0');
|
||||
// Prepare for next iteration.
|
||||
numerator->Times10();
|
||||
}
|
||||
// Generate the last digit.
|
||||
uint16_t digit;
|
||||
digit = numerator->DivideModuloIntBignum(*denominator);
|
||||
if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
|
||||
digit++;
|
||||
}
|
||||
ASSERT(digit <= 10);
|
||||
buffer[count - 1] = static_cast<char>(digit + '0');
|
||||
// Correct bad digits (in case we had a sequence of '9's). Propagate the
|
||||
// carry until we hat a non-'9' or til we reach the first digit.
|
||||
for (int i = count - 1; i > 0; --i) {
|
||||
if (buffer[i] != '0' + 10) break;
|
||||
buffer[i] = '0';
|
||||
buffer[i - 1]++;
|
||||
}
|
||||
if (buffer[0] == '0' + 10) {
|
||||
// Propagate a carry past the top place.
|
||||
buffer[0] = '1';
|
||||
(*decimal_point)++;
|
||||
}
|
||||
*length = count;
|
||||
}
|
||||
|
||||
|
||||
// Generates 'requested_digits' after the decimal point. It might omit
|
||||
// trailing '0's. If the input number is too small then no digits at all are
|
||||
// generated (ex.: 2 fixed digits for 0.00001).
|
||||
//
|
||||
// Input verifies: 1 <= (numerator + delta) / denominator < 10.
|
||||
static void BignumToFixed(int requested_digits, int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Vector<char>(buffer), int* length) {
|
||||
// Note that we have to look at more than just the requested_digits, since
|
||||
// a number could be rounded up. Example: v=0.5 with requested_digits=0.
|
||||
// Even though the power of v equals 0 we can't just stop here.
|
||||
if (-(*decimal_point) > requested_digits) {
|
||||
// The number is definitively too small.
|
||||
// Ex: 0.001 with requested_digits == 1.
|
||||
// Set decimal-point to -requested_digits. This is what Gay does.
|
||||
// Note that it should not have any effect anyways since the string is
|
||||
// empty.
|
||||
*decimal_point = -requested_digits;
|
||||
*length = 0;
|
||||
return;
|
||||
} else if (-(*decimal_point) == requested_digits) {
|
||||
// We only need to verify if the number rounds down or up.
|
||||
// Ex: 0.04 and 0.06 with requested_digits == 1.
|
||||
ASSERT(*decimal_point == -requested_digits);
|
||||
// Initially the fraction lies in range (1, 10]. Multiply the denominator
|
||||
// by 10 so that we can compare more easily.
|
||||
denominator->Times10();
|
||||
if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
|
||||
// If the fraction is >= 0.5 then we have to include the rounded
|
||||
// digit.
|
||||
buffer[0] = '1';
|
||||
*length = 1;
|
||||
(*decimal_point)++;
|
||||
} else {
|
||||
// Note that we caught most of similar cases earlier.
|
||||
*length = 0;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
// The requested digits correspond to the digits after the point.
|
||||
// The variable 'needed_digits' includes the digits before the point.
|
||||
int needed_digits = (*decimal_point) + requested_digits;
|
||||
GenerateCountedDigits(needed_digits, decimal_point,
|
||||
numerator, denominator,
|
||||
buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns an estimation of k such that 10^(k-1) <= v < 10^k where
|
||||
// v = f * 2^exponent and 2^52 <= f < 2^53.
|
||||
// v is hence a normalized double with the given exponent. The output is an
|
||||
// approximation for the exponent of the decimal approimation .digits * 10^k.
|
||||
//
|
||||
// The result might undershoot by 1 in which case 10^k <= v < 10^k+1.
|
||||
// Note: this property holds for v's upper boundary m+ too.
|
||||
// 10^k <= m+ < 10^k+1.
|
||||
// (see explanation below).
|
||||
//
|
||||
// Examples:
|
||||
// EstimatePower(0) => 16
|
||||
// EstimatePower(-52) => 0
|
||||
//
|
||||
// Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0.
|
||||
static int EstimatePower(int exponent) {
|
||||
// This function estimates log10 of v where v = f*2^e (with e == exponent).
|
||||
// Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)).
|
||||
// Note that f is bounded by its container size. Let p = 53 (the double's
|
||||
// significand size). Then 2^(p-1) <= f < 2^p.
|
||||
//
|
||||
// Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close
|
||||
// to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)).
|
||||
// The computed number undershoots by less than 0.631 (when we compute log3
|
||||
// and not log10).
|
||||
//
|
||||
// Optimization: since we only need an approximated result this computation
|
||||
// can be performed on 64 bit integers. On x86/x64 architecture the speedup is
|
||||
// not really measurable, though.
|
||||
//
|
||||
// Since we want to avoid overshooting we decrement by 1e10 so that
|
||||
// floating-point imprecisions don't affect us.
|
||||
//
|
||||
// Explanation for v's boundary m+: the computation takes advantage of
|
||||
// the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement
|
||||
// (even for denormals where the delta can be much more important).
|
||||
|
||||
const double k1Log10 = 0.30102999566398114; // 1/lg(10)
|
||||
|
||||
// For doubles len(f) == 53 (don't forget the hidden bit).
|
||||
const int kSignificandSize = Double::kSignificandSize;
|
||||
double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
|
||||
return static_cast<int>(estimate);
|
||||
}
|
||||
|
||||
|
||||
// See comments for InitialScaledStartValues.
|
||||
static void InitialScaledStartValuesPositiveExponent(
|
||||
uint64_t significand, int exponent,
|
||||
int estimated_power, bool need_boundary_deltas,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
// A positive exponent implies a positive power.
|
||||
ASSERT(estimated_power >= 0);
|
||||
// Since the estimated_power is positive we simply multiply the denominator
|
||||
// by 10^estimated_power.
|
||||
|
||||
// numerator = v.
|
||||
numerator->AssignUInt64(significand);
|
||||
numerator->ShiftLeft(exponent);
|
||||
// denominator = 10^estimated_power.
|
||||
denominator->AssignPowerUInt16(10, estimated_power);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Introduce a common denominator so that the deltas to the boundaries are
|
||||
// integers.
|
||||
denominator->ShiftLeft(1);
|
||||
numerator->ShiftLeft(1);
|
||||
// Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
|
||||
// denominator (of 2) delta_plus equals 2^e.
|
||||
delta_plus->AssignUInt16(1);
|
||||
delta_plus->ShiftLeft(exponent);
|
||||
// Same for delta_minus. The adjustments if f == 2^p-1 are done later.
|
||||
delta_minus->AssignUInt16(1);
|
||||
delta_minus->ShiftLeft(exponent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// See comments for InitialScaledStartValues
|
||||
static void InitialScaledStartValuesNegativeExponentPositivePower(
|
||||
uint64_t significand, int exponent,
|
||||
int estimated_power, bool need_boundary_deltas,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
// v = f * 2^e with e < 0, and with estimated_power >= 0.
|
||||
// This means that e is close to 0 (have a look at how estimated_power is
|
||||
// computed).
|
||||
|
||||
// numerator = significand
|
||||
// since v = significand * 2^exponent this is equivalent to
|
||||
// numerator = v * / 2^-exponent
|
||||
numerator->AssignUInt64(significand);
|
||||
// denominator = 10^estimated_power * 2^-exponent (with exponent < 0)
|
||||
denominator->AssignPowerUInt16(10, estimated_power);
|
||||
denominator->ShiftLeft(-exponent);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Introduce a common denominator so that the deltas to the boundaries are
|
||||
// integers.
|
||||
denominator->ShiftLeft(1);
|
||||
numerator->ShiftLeft(1);
|
||||
// Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
|
||||
// denominator (of 2) delta_plus equals 2^e.
|
||||
// Given that the denominator already includes v's exponent the distance
|
||||
// to the boundaries is simply 1.
|
||||
delta_plus->AssignUInt16(1);
|
||||
// Same for delta_minus. The adjustments if f == 2^p-1 are done later.
|
||||
delta_minus->AssignUInt16(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// See comments for InitialScaledStartValues
|
||||
static void InitialScaledStartValuesNegativeExponentNegativePower(
|
||||
uint64_t significand, int exponent,
|
||||
int estimated_power, bool need_boundary_deltas,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
// Instead of multiplying the denominator with 10^estimated_power we
|
||||
// multiply all values (numerator and deltas) by 10^-estimated_power.
|
||||
|
||||
// Use numerator as temporary container for power_ten.
|
||||
Bignum* power_ten = numerator;
|
||||
power_ten->AssignPowerUInt16(10, -estimated_power);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Since power_ten == numerator we must make a copy of 10^estimated_power
|
||||
// before we complete the computation of the numerator.
|
||||
// delta_plus = delta_minus = 10^estimated_power
|
||||
delta_plus->AssignBignum(*power_ten);
|
||||
delta_minus->AssignBignum(*power_ten);
|
||||
}
|
||||
|
||||
// numerator = significand * 2 * 10^-estimated_power
|
||||
// since v = significand * 2^exponent this is equivalent to
|
||||
// numerator = v * 10^-estimated_power * 2 * 2^-exponent.
|
||||
// Remember: numerator has been abused as power_ten. So no need to assign it
|
||||
// to itself.
|
||||
ASSERT(numerator == power_ten);
|
||||
numerator->MultiplyByUInt64(significand);
|
||||
|
||||
// denominator = 2 * 2^-exponent with exponent < 0.
|
||||
denominator->AssignUInt16(1);
|
||||
denominator->ShiftLeft(-exponent);
|
||||
|
||||
if (need_boundary_deltas) {
|
||||
// Introduce a common denominator so that the deltas to the boundaries are
|
||||
// integers.
|
||||
numerator->ShiftLeft(1);
|
||||
denominator->ShiftLeft(1);
|
||||
// With this shift the boundaries have their correct value, since
|
||||
// delta_plus = 10^-estimated_power, and
|
||||
// delta_minus = 10^-estimated_power.
|
||||
// These assignments have been done earlier.
|
||||
// The adjustments if f == 2^p-1 (lower boundary is closer) are done later.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Let v = significand * 2^exponent.
|
||||
// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
|
||||
// and denominator. The functions GenerateShortestDigits and
|
||||
// GenerateCountedDigits will then convert this ratio to its decimal
|
||||
// representation d, with the required accuracy.
|
||||
// Then d * 10^estimated_power is the representation of v.
|
||||
// (Note: the fraction and the estimated_power might get adjusted before
|
||||
// generating the decimal representation.)
|
||||
//
|
||||
// The initial start values consist of:
|
||||
// - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power.
|
||||
// - a scaled (common) denominator.
|
||||
// optionally (used by GenerateShortestDigits to decide if it has the shortest
|
||||
// decimal converting back to v):
|
||||
// - v - m-: the distance to the lower boundary.
|
||||
// - m+ - v: the distance to the upper boundary.
|
||||
//
|
||||
// v, m+, m-, and therefore v - m- and m+ - v all share the same denominator.
|
||||
//
|
||||
// Let ep == estimated_power, then the returned values will satisfy:
|
||||
// v / 10^ep = numerator / denominator.
|
||||
// v's boundaries m- and m+:
|
||||
// m- / 10^ep == v / 10^ep - delta_minus / denominator
|
||||
// m+ / 10^ep == v / 10^ep + delta_plus / denominator
|
||||
// Or in other words:
|
||||
// m- == v - delta_minus * 10^ep / denominator;
|
||||
// m+ == v + delta_plus * 10^ep / denominator;
|
||||
//
|
||||
// Since 10^(k-1) <= v < 10^k (with k == estimated_power)
|
||||
// or 10^k <= v < 10^(k+1)
|
||||
// we then have 0.1 <= numerator/denominator < 1
|
||||
// or 1 <= numerator/denominator < 10
|
||||
//
|
||||
// It is then easy to kickstart the digit-generation routine.
|
||||
//
|
||||
// The boundary-deltas are only filled if the mode equals BIGNUM_DTOA_SHORTEST
|
||||
// or BIGNUM_DTOA_SHORTEST_SINGLE.
|
||||
|
||||
static void InitialScaledStartValues(uint64_t significand,
|
||||
int exponent,
|
||||
bool lower_boundary_is_closer,
|
||||
int estimated_power,
|
||||
bool need_boundary_deltas,
|
||||
Bignum* numerator,
|
||||
Bignum* denominator,
|
||||
Bignum* delta_minus,
|
||||
Bignum* delta_plus) {
|
||||
if (exponent >= 0) {
|
||||
InitialScaledStartValuesPositiveExponent(
|
||||
significand, exponent, estimated_power, need_boundary_deltas,
|
||||
numerator, denominator, delta_minus, delta_plus);
|
||||
} else if (estimated_power >= 0) {
|
||||
InitialScaledStartValuesNegativeExponentPositivePower(
|
||||
significand, exponent, estimated_power, need_boundary_deltas,
|
||||
numerator, denominator, delta_minus, delta_plus);
|
||||
} else {
|
||||
InitialScaledStartValuesNegativeExponentNegativePower(
|
||||
significand, exponent, estimated_power, need_boundary_deltas,
|
||||
numerator, denominator, delta_minus, delta_plus);
|
||||
}
|
||||
|
||||
if (need_boundary_deltas && lower_boundary_is_closer) {
|
||||
// The lower boundary is closer at half the distance of "normal" numbers.
|
||||
// Increase the common denominator and adapt all but the delta_minus.
|
||||
denominator->ShiftLeft(1); // *2
|
||||
numerator->ShiftLeft(1); // *2
|
||||
delta_plus->ShiftLeft(1); // *2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This routine multiplies numerator/denominator so that its values lies in the
|
||||
// range 1-10. That is after a call to this function we have:
|
||||
// 1 <= (numerator + delta_plus) /denominator < 10.
|
||||
// Let numerator the input before modification and numerator' the argument
|
||||
// after modification, then the output-parameter decimal_point is such that
|
||||
// numerator / denominator * 10^estimated_power ==
|
||||
// numerator' / denominator' * 10^(decimal_point - 1)
|
||||
// In some cases estimated_power was too low, and this is already the case. We
|
||||
// then simply adjust the power so that 10^(k-1) <= v < 10^k (with k ==
|
||||
// estimated_power) but do not touch the numerator or denominator.
|
||||
// Otherwise the routine multiplies the numerator and the deltas by 10.
|
||||
static void FixupMultiply10(int estimated_power, bool is_even,
|
||||
int* decimal_point,
|
||||
Bignum* numerator, Bignum* denominator,
|
||||
Bignum* delta_minus, Bignum* delta_plus) {
|
||||
bool in_range;
|
||||
if (is_even) {
|
||||
// For IEEE doubles half-way cases (in decimal system numbers ending with 5)
|
||||
// are rounded to the closest floating-point number with even significand.
|
||||
in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
|
||||
} else {
|
||||
in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
|
||||
}
|
||||
if (in_range) {
|
||||
// Since numerator + delta_plus >= denominator we already have
|
||||
// 1 <= numerator/denominator < 10. Simply update the estimated_power.
|
||||
*decimal_point = estimated_power + 1;
|
||||
} else {
|
||||
*decimal_point = estimated_power;
|
||||
numerator->Times10();
|
||||
if (Bignum::Equal(*delta_minus, *delta_plus)) {
|
||||
delta_minus->Times10();
|
||||
delta_plus->AssignBignum(*delta_minus);
|
||||
} else {
|
||||
delta_minus->Times10();
|
||||
delta_plus->Times10();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
@ -1,85 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_BIGNUM_DTOA_H_
|
||||
#define DOUBLE_CONVERSION_BIGNUM_DTOA_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion
|
||||
{
|
||||
|
||||
enum BignumDtoaMode
|
||||
{
|
||||
// Return the shortest correct representation.
|
||||
// For example the output of 0.299999999999999988897 is (the less accurate but
|
||||
// correct) 0.3.
|
||||
BIGNUM_DTOA_SHORTEST,
|
||||
// Same as BIGNUM_DTOA_SHORTEST but for single-precision floats.
|
||||
BIGNUM_DTOA_SHORTEST_SINGLE,
|
||||
// Return a fixed number of digits after the decimal point.
|
||||
// For instance fixed(0.1, 4) becomes 0.1000
|
||||
// If the input number is big, the output will be big.
|
||||
BIGNUM_DTOA_FIXED,
|
||||
// Return a fixed number of digits, no matter what the exponent is.
|
||||
BIGNUM_DTOA_PRECISION
|
||||
};
|
||||
|
||||
// Converts the given double 'v' to ascii.
|
||||
// The result should be interpreted as buffer * 10^(point-length).
|
||||
// The buffer will be null-terminated.
|
||||
//
|
||||
// The input v must be > 0 and different from NaN, and Infinity.
|
||||
//
|
||||
// The output depends on the given mode:
|
||||
// - SHORTEST: produce the least amount of digits for which the internal
|
||||
// identity requirement is still satisfied. If the digits are printed
|
||||
// (together with the correct exponent) then reading this number will give
|
||||
// 'v' again. The buffer will choose the representation that is closest to
|
||||
// 'v'. If there are two at the same distance, than the number is round up.
|
||||
// In this mode the 'requested_digits' parameter is ignored.
|
||||
// - FIXED: produces digits necessary to print a given number with
|
||||
// 'requested_digits' digits after the decimal point. The produced digits
|
||||
// might be too short in which case the caller has to fill the gaps with '0's.
|
||||
// Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
|
||||
// Halfway cases are rounded up. The call toFixed(0.15, 2) thus returns
|
||||
// buffer="2", point=0.
|
||||
// Note: the length of the returned buffer has no meaning wrt the significance
|
||||
// of its digits. That is, just because it contains '0's does not mean that
|
||||
// any other digit would not satisfy the internal identity requirement.
|
||||
// - PRECISION: produces 'requested_digits' where the first digit is not '0'.
|
||||
// Even though the length of produced digits usually equals
|
||||
// 'requested_digits', the function is allowed to return fewer digits, in
|
||||
// which case the caller has to fill the missing digits with '0's.
|
||||
// Halfway cases are again rounded up.
|
||||
// 'BignumDtoa' expects the given buffer to be big enough to hold all digits
|
||||
// and a terminating null-character.
|
||||
void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits, Vector<char> buffer, int * length, int * point);
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_BIGNUM_DTOA_H_
|
@ -1,766 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "bignum.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
Bignum::Bignum()
|
||||
: bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
|
||||
for (int i = 0; i < kBigitCapacity; ++i) {
|
||||
bigits_[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename S>
|
||||
static int BitSize(S value) {
|
||||
(void) value; // Mark variable as used.
|
||||
return 8 * sizeof(value);
|
||||
}
|
||||
|
||||
// Guaranteed to lie in one Bigit.
|
||||
void Bignum::AssignUInt16(uint16_t value) {
|
||||
ASSERT(kBigitSize >= BitSize(value));
|
||||
Zero();
|
||||
if (value == 0) return;
|
||||
|
||||
EnsureCapacity(1);
|
||||
bigits_[0] = value;
|
||||
used_digits_ = 1;
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AssignUInt64(uint64_t value) {
|
||||
const int kUInt64Size = 64;
|
||||
|
||||
Zero();
|
||||
if (value == 0) return;
|
||||
|
||||
int needed_bigits = kUInt64Size / kBigitSize + 1;
|
||||
EnsureCapacity(needed_bigits);
|
||||
for (int i = 0; i < needed_bigits; ++i) {
|
||||
bigits_[i] = value & kBigitMask;
|
||||
value = value >> kBigitSize;
|
||||
}
|
||||
used_digits_ = needed_bigits;
|
||||
Clamp();
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AssignBignum(const Bignum& other) {
|
||||
exponent_ = other.exponent_;
|
||||
for (int i = 0; i < other.used_digits_; ++i) {
|
||||
bigits_[i] = other.bigits_[i];
|
||||
}
|
||||
// Clear the excess digits (if there were any).
|
||||
for (int i = other.used_digits_; i < used_digits_; ++i) {
|
||||
bigits_[i] = 0;
|
||||
}
|
||||
used_digits_ = other.used_digits_;
|
||||
}
|
||||
|
||||
|
||||
static uint64_t ReadUInt64(Vector<const char> buffer,
|
||||
int from,
|
||||
int digits_to_read) {
|
||||
uint64_t result = 0;
|
||||
for (int i = from; i < from + digits_to_read; ++i) {
|
||||
int digit = buffer[i] - '0';
|
||||
ASSERT(0 <= digit && digit <= 9);
|
||||
result = result * 10 + digit;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AssignDecimalString(Vector<const char> value) {
|
||||
// 2^64 = 18446744073709551616 > 10^19
|
||||
const int kMaxUint64DecimalDigits = 19;
|
||||
Zero();
|
||||
int length = value.length();
|
||||
int pos = 0;
|
||||
// Let's just say that each digit needs 4 bits.
|
||||
while (length >= kMaxUint64DecimalDigits) {
|
||||
uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
|
||||
pos += kMaxUint64DecimalDigits;
|
||||
length -= kMaxUint64DecimalDigits;
|
||||
MultiplyByPowerOfTen(kMaxUint64DecimalDigits);
|
||||
AddUInt64(digits);
|
||||
}
|
||||
uint64_t digits = ReadUInt64(value, pos, length);
|
||||
MultiplyByPowerOfTen(length);
|
||||
AddUInt64(digits);
|
||||
Clamp();
|
||||
}
|
||||
|
||||
|
||||
static int HexCharValue(char c) {
|
||||
if ('0' <= c && c <= '9') return c - '0';
|
||||
if ('a' <= c && c <= 'f') return 10 + c - 'a';
|
||||
ASSERT('A' <= c && c <= 'F');
|
||||
return 10 + c - 'A';
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AssignHexString(Vector<const char> value) {
|
||||
Zero();
|
||||
int length = value.length();
|
||||
|
||||
int needed_bigits = length * 4 / kBigitSize + 1;
|
||||
EnsureCapacity(needed_bigits);
|
||||
int string_index = length - 1;
|
||||
for (int i = 0; i < needed_bigits - 1; ++i) {
|
||||
// These bigits are guaranteed to be "full".
|
||||
Chunk current_bigit = 0;
|
||||
for (int j = 0; j < kBigitSize / 4; j++) {
|
||||
current_bigit += HexCharValue(value[string_index--]) << (j * 4);
|
||||
}
|
||||
bigits_[i] = current_bigit;
|
||||
}
|
||||
used_digits_ = needed_bigits - 1;
|
||||
|
||||
Chunk most_significant_bigit = 0; // Could be = 0;
|
||||
for (int j = 0; j <= string_index; ++j) {
|
||||
most_significant_bigit <<= 4;
|
||||
most_significant_bigit += HexCharValue(value[j]);
|
||||
}
|
||||
if (most_significant_bigit != 0) {
|
||||
bigits_[used_digits_] = most_significant_bigit;
|
||||
used_digits_++;
|
||||
}
|
||||
Clamp();
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AddUInt64(uint64_t operand) {
|
||||
if (operand == 0) return;
|
||||
Bignum other;
|
||||
other.AssignUInt64(operand);
|
||||
AddBignum(other);
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AddBignum(const Bignum& other) {
|
||||
ASSERT(IsClamped());
|
||||
ASSERT(other.IsClamped());
|
||||
|
||||
// If this has a greater exponent than other append zero-bigits to this.
|
||||
// After this call exponent_ <= other.exponent_.
|
||||
Align(other);
|
||||
|
||||
// There are two possibilities:
|
||||
// aaaaaaaaaaa 0000 (where the 0s represent a's exponent)
|
||||
// bbbbb 00000000
|
||||
// ----------------
|
||||
// ccccccccccc 0000
|
||||
// or
|
||||
// aaaaaaaaaa 0000
|
||||
// bbbbbbbbb 0000000
|
||||
// -----------------
|
||||
// cccccccccccc 0000
|
||||
// In both cases we might need a carry bigit.
|
||||
|
||||
EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_);
|
||||
Chunk carry = 0;
|
||||
int bigit_pos = other.exponent_ - exponent_;
|
||||
ASSERT(bigit_pos >= 0);
|
||||
for (int i = 0; i < other.used_digits_; ++i) {
|
||||
Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry;
|
||||
bigits_[bigit_pos] = sum & kBigitMask;
|
||||
carry = sum >> kBigitSize;
|
||||
bigit_pos++;
|
||||
}
|
||||
|
||||
while (carry != 0) {
|
||||
Chunk sum = bigits_[bigit_pos] + carry;
|
||||
bigits_[bigit_pos] = sum & kBigitMask;
|
||||
carry = sum >> kBigitSize;
|
||||
bigit_pos++;
|
||||
}
|
||||
used_digits_ = Max(bigit_pos, used_digits_);
|
||||
ASSERT(IsClamped());
|
||||
}
|
||||
|
||||
|
||||
void Bignum::SubtractBignum(const Bignum& other) {
|
||||
ASSERT(IsClamped());
|
||||
ASSERT(other.IsClamped());
|
||||
// We require this to be bigger than other.
|
||||
ASSERT(LessEqual(other, *this));
|
||||
|
||||
Align(other);
|
||||
|
||||
int offset = other.exponent_ - exponent_;
|
||||
Chunk borrow = 0;
|
||||
int i;
|
||||
for (i = 0; i < other.used_digits_; ++i) {
|
||||
ASSERT((borrow == 0) || (borrow == 1));
|
||||
Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow;
|
||||
bigits_[i + offset] = difference & kBigitMask;
|
||||
borrow = difference >> (kChunkSize - 1);
|
||||
}
|
||||
while (borrow != 0) {
|
||||
Chunk difference = bigits_[i + offset] - borrow;
|
||||
bigits_[i + offset] = difference & kBigitMask;
|
||||
borrow = difference >> (kChunkSize - 1);
|
||||
++i;
|
||||
}
|
||||
Clamp();
|
||||
}
|
||||
|
||||
|
||||
void Bignum::ShiftLeft(int shift_amount) {
|
||||
if (used_digits_ == 0) return;
|
||||
exponent_ += shift_amount / kBigitSize;
|
||||
int local_shift = shift_amount % kBigitSize;
|
||||
EnsureCapacity(used_digits_ + 1);
|
||||
BigitsShiftLeft(local_shift);
|
||||
}
|
||||
|
||||
|
||||
void Bignum::MultiplyByUInt32(uint32_t factor) {
|
||||
if (factor == 1) return;
|
||||
if (factor == 0) {
|
||||
Zero();
|
||||
return;
|
||||
}
|
||||
if (used_digits_ == 0) return;
|
||||
|
||||
// The product of a bigit with the factor is of size kBigitSize + 32.
|
||||
// Assert that this number + 1 (for the carry) fits into double chunk.
|
||||
ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1);
|
||||
DoubleChunk carry = 0;
|
||||
for (int i = 0; i < used_digits_; ++i) {
|
||||
DoubleChunk product = static_cast<DoubleChunk>(factor) * bigits_[i] + carry;
|
||||
bigits_[i] = static_cast<Chunk>(product & kBigitMask);
|
||||
carry = (product >> kBigitSize);
|
||||
}
|
||||
while (carry != 0) {
|
||||
EnsureCapacity(used_digits_ + 1);
|
||||
bigits_[used_digits_] = carry & kBigitMask;
|
||||
used_digits_++;
|
||||
carry >>= kBigitSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Bignum::MultiplyByUInt64(uint64_t factor) {
|
||||
if (factor == 1) return;
|
||||
if (factor == 0) {
|
||||
Zero();
|
||||
return;
|
||||
}
|
||||
ASSERT(kBigitSize < 32);
|
||||
uint64_t carry = 0;
|
||||
uint64_t low = factor & 0xFFFFFFFF;
|
||||
uint64_t high = factor >> 32;
|
||||
for (int i = 0; i < used_digits_; ++i) {
|
||||
uint64_t product_low = low * bigits_[i];
|
||||
uint64_t product_high = high * bigits_[i];
|
||||
uint64_t tmp = (carry & kBigitMask) + product_low;
|
||||
bigits_[i] = tmp & kBigitMask;
|
||||
carry = (carry >> kBigitSize) + (tmp >> kBigitSize) +
|
||||
(product_high << (32 - kBigitSize));
|
||||
}
|
||||
while (carry != 0) {
|
||||
EnsureCapacity(used_digits_ + 1);
|
||||
bigits_[used_digits_] = carry & kBigitMask;
|
||||
used_digits_++;
|
||||
carry >>= kBigitSize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Bignum::MultiplyByPowerOfTen(int exponent) {
|
||||
const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d);
|
||||
const uint16_t kFive1 = 5;
|
||||
const uint16_t kFive2 = kFive1 * 5;
|
||||
const uint16_t kFive3 = kFive2 * 5;
|
||||
const uint16_t kFive4 = kFive3 * 5;
|
||||
const uint16_t kFive5 = kFive4 * 5;
|
||||
const uint16_t kFive6 = kFive5 * 5;
|
||||
const uint32_t kFive7 = kFive6 * 5;
|
||||
const uint32_t kFive8 = kFive7 * 5;
|
||||
const uint32_t kFive9 = kFive8 * 5;
|
||||
const uint32_t kFive10 = kFive9 * 5;
|
||||
const uint32_t kFive11 = kFive10 * 5;
|
||||
const uint32_t kFive12 = kFive11 * 5;
|
||||
const uint32_t kFive13 = kFive12 * 5;
|
||||
const uint32_t kFive1_to_12[] =
|
||||
{ kFive1, kFive2, kFive3, kFive4, kFive5, kFive6,
|
||||
kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 };
|
||||
|
||||
ASSERT(exponent >= 0);
|
||||
if (exponent == 0) return;
|
||||
if (used_digits_ == 0) return;
|
||||
|
||||
// We shift by exponent at the end just before returning.
|
||||
int remaining_exponent = exponent;
|
||||
while (remaining_exponent >= 27) {
|
||||
MultiplyByUInt64(kFive27);
|
||||
remaining_exponent -= 27;
|
||||
}
|
||||
while (remaining_exponent >= 13) {
|
||||
MultiplyByUInt32(kFive13);
|
||||
remaining_exponent -= 13;
|
||||
}
|
||||
if (remaining_exponent > 0) {
|
||||
MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]);
|
||||
}
|
||||
ShiftLeft(exponent);
|
||||
}
|
||||
|
||||
|
||||
void Bignum::Square() {
|
||||
ASSERT(IsClamped());
|
||||
int product_length = 2 * used_digits_;
|
||||
EnsureCapacity(product_length);
|
||||
|
||||
// Comba multiplication: compute each column separately.
|
||||
// Example: r = a2a1a0 * b2b1b0.
|
||||
// r = 1 * a0b0 +
|
||||
// 10 * (a1b0 + a0b1) +
|
||||
// 100 * (a2b0 + a1b1 + a0b2) +
|
||||
// 1000 * (a2b1 + a1b2) +
|
||||
// 10000 * a2b2
|
||||
//
|
||||
// In the worst case we have to accumulate nb-digits products of digit*digit.
|
||||
//
|
||||
// Assert that the additional number of bits in a DoubleChunk are enough to
|
||||
// sum up used_digits of Bigit*Bigit.
|
||||
if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
DoubleChunk accumulator = 0;
|
||||
// First shift the digits so we don't overwrite them.
|
||||
int copy_offset = used_digits_;
|
||||
for (int i = 0; i < used_digits_; ++i) {
|
||||
bigits_[copy_offset + i] = bigits_[i];
|
||||
}
|
||||
// We have two loops to avoid some 'if's in the loop.
|
||||
for (int i = 0; i < used_digits_; ++i) {
|
||||
// Process temporary digit i with power i.
|
||||
// The sum of the two indices must be equal to i.
|
||||
int bigit_index1 = i;
|
||||
int bigit_index2 = 0;
|
||||
// Sum all of the sub-products.
|
||||
while (bigit_index1 >= 0) {
|
||||
Chunk chunk1 = bigits_[copy_offset + bigit_index1];
|
||||
Chunk chunk2 = bigits_[copy_offset + bigit_index2];
|
||||
accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
|
||||
bigit_index1--;
|
||||
bigit_index2++;
|
||||
}
|
||||
bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;
|
||||
accumulator >>= kBigitSize;
|
||||
}
|
||||
for (int i = used_digits_; i < product_length; ++i) {
|
||||
int bigit_index1 = used_digits_ - 1;
|
||||
int bigit_index2 = i - bigit_index1;
|
||||
// Invariant: sum of both indices is again equal to i.
|
||||
// Inner loop runs 0 times on last iteration, emptying accumulator.
|
||||
while (bigit_index2 < used_digits_) {
|
||||
Chunk chunk1 = bigits_[copy_offset + bigit_index1];
|
||||
Chunk chunk2 = bigits_[copy_offset + bigit_index2];
|
||||
accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
|
||||
bigit_index1--;
|
||||
bigit_index2++;
|
||||
}
|
||||
// The overwritten bigits_[i] will never be read in further loop iterations,
|
||||
// because bigit_index1 and bigit_index2 are always greater
|
||||
// than i - used_digits_.
|
||||
bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;
|
||||
accumulator >>= kBigitSize;
|
||||
}
|
||||
// Since the result was guaranteed to lie inside the number the
|
||||
// accumulator must be 0 now.
|
||||
ASSERT(accumulator == 0);
|
||||
|
||||
// Don't forget to update the used_digits and the exponent.
|
||||
used_digits_ = product_length;
|
||||
exponent_ *= 2;
|
||||
Clamp();
|
||||
}
|
||||
|
||||
|
||||
void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
|
||||
ASSERT(base != 0);
|
||||
ASSERT(power_exponent >= 0);
|
||||
if (power_exponent == 0) {
|
||||
AssignUInt16(1);
|
||||
return;
|
||||
}
|
||||
Zero();
|
||||
int shifts = 0;
|
||||
// We expect base to be in range 2-32, and most often to be 10.
|
||||
// It does not make much sense to implement different algorithms for counting
|
||||
// the bits.
|
||||
while ((base & 1) == 0) {
|
||||
base >>= 1;
|
||||
shifts++;
|
||||
}
|
||||
int bit_size = 0;
|
||||
int tmp_base = base;
|
||||
while (tmp_base != 0) {
|
||||
tmp_base >>= 1;
|
||||
bit_size++;
|
||||
}
|
||||
int final_size = bit_size * power_exponent;
|
||||
// 1 extra bigit for the shifting, and one for rounded final_size.
|
||||
EnsureCapacity(final_size / kBigitSize + 2);
|
||||
|
||||
// Left to Right exponentiation.
|
||||
int mask = 1;
|
||||
while (power_exponent >= mask) mask <<= 1;
|
||||
|
||||
// The mask is now pointing to the bit above the most significant 1-bit of
|
||||
// power_exponent.
|
||||
// Get rid of first 1-bit;
|
||||
mask >>= 2;
|
||||
uint64_t this_value = base;
|
||||
|
||||
bool delayed_multipliciation = false;
|
||||
const uint64_t max_32bits = 0xFFFFFFFF;
|
||||
while (mask != 0 && this_value <= max_32bits) {
|
||||
this_value = this_value * this_value;
|
||||
// Verify that there is enough space in this_value to perform the
|
||||
// multiplication. The first bit_size bits must be 0.
|
||||
if ((power_exponent & mask) != 0) {
|
||||
uint64_t base_bits_mask =
|
||||
~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
|
||||
bool high_bits_zero = (this_value & base_bits_mask) == 0;
|
||||
if (high_bits_zero) {
|
||||
this_value *= base;
|
||||
} else {
|
||||
delayed_multipliciation = true;
|
||||
}
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
AssignUInt64(this_value);
|
||||
if (delayed_multipliciation) {
|
||||
MultiplyByUInt32(base);
|
||||
}
|
||||
|
||||
// Now do the same thing as a bignum.
|
||||
while (mask != 0) {
|
||||
Square();
|
||||
if ((power_exponent & mask) != 0) {
|
||||
MultiplyByUInt32(base);
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
// And finally add the saved shifts.
|
||||
ShiftLeft(shifts * power_exponent);
|
||||
}
|
||||
|
||||
|
||||
// Precondition: this/other < 16bit.
|
||||
uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
|
||||
ASSERT(IsClamped());
|
||||
ASSERT(other.IsClamped());
|
||||
ASSERT(other.used_digits_ > 0);
|
||||
|
||||
// Easy case: if we have less digits than the divisor than the result is 0.
|
||||
// Note: this handles the case where this == 0, too.
|
||||
if (BigitLength() < other.BigitLength()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Align(other);
|
||||
|
||||
uint16_t result = 0;
|
||||
|
||||
// Start by removing multiples of 'other' until both numbers have the same
|
||||
// number of digits.
|
||||
while (BigitLength() > other.BigitLength()) {
|
||||
// This naive approach is extremely inefficient if `this` divided by other
|
||||
// is big. This function is implemented for doubleToString where
|
||||
// the result should be small (less than 10).
|
||||
ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16));
|
||||
ASSERT(bigits_[used_digits_ - 1] < 0x10000);
|
||||
// Remove the multiples of the first digit.
|
||||
// Example this = 23 and other equals 9. -> Remove 2 multiples.
|
||||
result += static_cast<uint16_t>(bigits_[used_digits_ - 1]);
|
||||
SubtractTimes(other, bigits_[used_digits_ - 1]);
|
||||
}
|
||||
|
||||
ASSERT(BigitLength() == other.BigitLength());
|
||||
|
||||
// Both bignums are at the same length now.
|
||||
// Since other has more than 0 digits we know that the access to
|
||||
// bigits_[used_digits_ - 1] is safe.
|
||||
Chunk this_bigit = bigits_[used_digits_ - 1];
|
||||
Chunk other_bigit = other.bigits_[other.used_digits_ - 1];
|
||||
|
||||
if (other.used_digits_ == 1) {
|
||||
// Shortcut for easy (and common) case.
|
||||
int quotient = this_bigit / other_bigit;
|
||||
bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient;
|
||||
ASSERT(quotient < 0x10000);
|
||||
result += static_cast<uint16_t>(quotient);
|
||||
Clamp();
|
||||
return result;
|
||||
}
|
||||
|
||||
int division_estimate = this_bigit / (other_bigit + 1);
|
||||
ASSERT(division_estimate < 0x10000);
|
||||
result += static_cast<uint16_t>(division_estimate);
|
||||
SubtractTimes(other, division_estimate);
|
||||
|
||||
if (other_bigit * (division_estimate + 1) > this_bigit) {
|
||||
// No need to even try to subtract. Even if other's remaining digits were 0
|
||||
// another subtraction would be too much.
|
||||
return result;
|
||||
}
|
||||
|
||||
while (LessEqual(other, *this)) {
|
||||
SubtractBignum(other);
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template<typename S>
|
||||
static int SizeInHexChars(S number) {
|
||||
ASSERT(number > 0);
|
||||
int result = 0;
|
||||
while (number != 0) {
|
||||
number >>= 4;
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static char HexCharOfValue(int value) {
|
||||
ASSERT(0 <= value && value <= 16);
|
||||
if (value < 10) return static_cast<char>(value + '0');
|
||||
return static_cast<char>(value - 10 + 'A');
|
||||
}
|
||||
|
||||
|
||||
bool Bignum::ToHexString(char* buffer, int buffer_size) const {
|
||||
ASSERT(IsClamped());
|
||||
// Each bigit must be printable as separate hex-character.
|
||||
ASSERT(kBigitSize % 4 == 0);
|
||||
const int kHexCharsPerBigit = kBigitSize / 4;
|
||||
|
||||
if (used_digits_ == 0) {
|
||||
if (buffer_size < 2) return false;
|
||||
buffer[0] = '0';
|
||||
buffer[1] = '\0';
|
||||
return true;
|
||||
}
|
||||
// We add 1 for the terminating '\0' character.
|
||||
int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit +
|
||||
SizeInHexChars(bigits_[used_digits_ - 1]) + 1;
|
||||
if (needed_chars > buffer_size) return false;
|
||||
int string_index = needed_chars - 1;
|
||||
buffer[string_index--] = '\0';
|
||||
for (int i = 0; i < exponent_; ++i) {
|
||||
for (int j = 0; j < kHexCharsPerBigit; ++j) {
|
||||
buffer[string_index--] = '0';
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < used_digits_ - 1; ++i) {
|
||||
Chunk current_bigit = bigits_[i];
|
||||
for (int j = 0; j < kHexCharsPerBigit; ++j) {
|
||||
buffer[string_index--] = HexCharOfValue(current_bigit & 0xF);
|
||||
current_bigit >>= 4;
|
||||
}
|
||||
}
|
||||
// And finally the last bigit.
|
||||
Chunk most_significant_bigit = bigits_[used_digits_ - 1];
|
||||
while (most_significant_bigit != 0) {
|
||||
buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF);
|
||||
most_significant_bigit >>= 4;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Bignum::Chunk Bignum::BigitAt(int index) const {
|
||||
if (index >= BigitLength()) return 0;
|
||||
if (index < exponent_) return 0;
|
||||
return bigits_[index - exponent_];
|
||||
}
|
||||
|
||||
|
||||
int Bignum::Compare(const Bignum& a, const Bignum& b) {
|
||||
ASSERT(a.IsClamped());
|
||||
ASSERT(b.IsClamped());
|
||||
int bigit_length_a = a.BigitLength();
|
||||
int bigit_length_b = b.BigitLength();
|
||||
if (bigit_length_a < bigit_length_b) return -1;
|
||||
if (bigit_length_a > bigit_length_b) return +1;
|
||||
for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) {
|
||||
Chunk bigit_a = a.BigitAt(i);
|
||||
Chunk bigit_b = b.BigitAt(i);
|
||||
if (bigit_a < bigit_b) return -1;
|
||||
if (bigit_a > bigit_b) return +1;
|
||||
// Otherwise they are equal up to this digit. Try the next digit.
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) {
|
||||
ASSERT(a.IsClamped());
|
||||
ASSERT(b.IsClamped());
|
||||
ASSERT(c.IsClamped());
|
||||
if (a.BigitLength() < b.BigitLength()) {
|
||||
return PlusCompare(b, a, c);
|
||||
}
|
||||
if (a.BigitLength() + 1 < c.BigitLength()) return -1;
|
||||
if (a.BigitLength() > c.BigitLength()) return +1;
|
||||
// The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than
|
||||
// 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one
|
||||
// of 'a'.
|
||||
if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Chunk borrow = 0;
|
||||
// Starting at min_exponent all digits are == 0. So no need to compare them.
|
||||
int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_);
|
||||
for (int i = c.BigitLength() - 1; i >= min_exponent; --i) {
|
||||
Chunk chunk_a = a.BigitAt(i);
|
||||
Chunk chunk_b = b.BigitAt(i);
|
||||
Chunk chunk_c = c.BigitAt(i);
|
||||
Chunk sum = chunk_a + chunk_b;
|
||||
if (sum > chunk_c + borrow) {
|
||||
return +1;
|
||||
} else {
|
||||
borrow = chunk_c + borrow - sum;
|
||||
if (borrow > 1) return -1;
|
||||
borrow <<= kBigitSize;
|
||||
}
|
||||
}
|
||||
if (borrow == 0) return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void Bignum::Clamp() {
|
||||
while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) {
|
||||
used_digits_--;
|
||||
}
|
||||
if (used_digits_ == 0) {
|
||||
// Zero.
|
||||
exponent_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Bignum::IsClamped() const {
|
||||
return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0;
|
||||
}
|
||||
|
||||
|
||||
void Bignum::Zero() {
|
||||
for (int i = 0; i < used_digits_; ++i) {
|
||||
bigits_[i] = 0;
|
||||
}
|
||||
used_digits_ = 0;
|
||||
exponent_ = 0;
|
||||
}
|
||||
|
||||
|
||||
void Bignum::Align(const Bignum& other) {
|
||||
if (exponent_ > other.exponent_) {
|
||||
// If "X" represents a "hidden" digit (by the exponent) then we are in the
|
||||
// following case (a == this, b == other):
|
||||
// a: aaaaaaXXXX or a: aaaaaXXX
|
||||
// b: bbbbbbX b: bbbbbbbbXX
|
||||
// We replace some of the hidden digits (X) of a with 0 digits.
|
||||
// a: aaaaaa000X or a: aaaaa0XX
|
||||
int zero_digits = exponent_ - other.exponent_;
|
||||
EnsureCapacity(used_digits_ + zero_digits);
|
||||
for (int i = used_digits_ - 1; i >= 0; --i) {
|
||||
bigits_[i + zero_digits] = bigits_[i];
|
||||
}
|
||||
for (int i = 0; i < zero_digits; ++i) {
|
||||
bigits_[i] = 0;
|
||||
}
|
||||
used_digits_ += zero_digits;
|
||||
exponent_ -= zero_digits;
|
||||
ASSERT(used_digits_ >= 0);
|
||||
ASSERT(exponent_ >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Bignum::BigitsShiftLeft(int shift_amount) {
|
||||
ASSERT(shift_amount < kBigitSize);
|
||||
ASSERT(shift_amount >= 0);
|
||||
Chunk carry = 0;
|
||||
for (int i = 0; i < used_digits_; ++i) {
|
||||
Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount);
|
||||
bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask;
|
||||
carry = new_carry;
|
||||
}
|
||||
if (carry != 0) {
|
||||
bigits_[used_digits_] = carry;
|
||||
used_digits_++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Bignum::SubtractTimes(const Bignum& other, int factor) {
|
||||
ASSERT(exponent_ <= other.exponent_);
|
||||
if (factor < 3) {
|
||||
for (int i = 0; i < factor; ++i) {
|
||||
SubtractBignum(other);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Chunk borrow = 0;
|
||||
int exponent_diff = other.exponent_ - exponent_;
|
||||
for (int i = 0; i < other.used_digits_; ++i) {
|
||||
DoubleChunk product = static_cast<DoubleChunk>(factor) * other.bigits_[i];
|
||||
DoubleChunk remove = borrow + product;
|
||||
Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask);
|
||||
bigits_[i + exponent_diff] = difference & kBigitMask;
|
||||
borrow = static_cast<Chunk>((difference >> (kChunkSize - 1)) +
|
||||
(remove >> kBigitSize));
|
||||
}
|
||||
for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) {
|
||||
if (borrow == 0) return;
|
||||
Chunk difference = bigits_[i] - borrow;
|
||||
bigits_[i] = difference & kBigitMask;
|
||||
borrow = difference >> (kChunkSize - 1);
|
||||
}
|
||||
Clamp();
|
||||
}
|
||||
|
||||
|
||||
} // namespace double_conversion
|
@ -1,138 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_BIGNUM_H_
|
||||
#define DOUBLE_CONVERSION_BIGNUM_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion
|
||||
{
|
||||
|
||||
class Bignum
|
||||
{
|
||||
public:
|
||||
// 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately.
|
||||
// This bignum can encode much bigger numbers, since it contains an
|
||||
// exponent.
|
||||
static const int kMaxSignificantBits = 3584;
|
||||
|
||||
Bignum();
|
||||
void AssignUInt16(uint16_t value);
|
||||
void AssignUInt64(uint64_t value);
|
||||
void AssignBignum(const Bignum & other);
|
||||
|
||||
void AssignDecimalString(Vector<const char> value);
|
||||
void AssignHexString(Vector<const char> value);
|
||||
|
||||
void AssignPowerUInt16(uint16_t base, int exponent);
|
||||
|
||||
void AddUInt16(uint16_t operand);
|
||||
void AddUInt64(uint64_t operand);
|
||||
void AddBignum(const Bignum & other);
|
||||
// Precondition: this >= other.
|
||||
void SubtractBignum(const Bignum & other);
|
||||
|
||||
void Square();
|
||||
void ShiftLeft(int shift_amount);
|
||||
void MultiplyByUInt32(uint32_t factor);
|
||||
void MultiplyByUInt64(uint64_t factor);
|
||||
void MultiplyByPowerOfTen(int exponent);
|
||||
void Times10() { return MultiplyByUInt32(10); }
|
||||
// Pseudocode:
|
||||
// int result = this / other;
|
||||
// this = this % other;
|
||||
// In the worst case this function is in O(this/other).
|
||||
uint16_t DivideModuloIntBignum(const Bignum & other);
|
||||
|
||||
bool ToHexString(char * buffer, int buffer_size) const;
|
||||
|
||||
// Returns
|
||||
// -1 if a < b,
|
||||
// 0 if a == b, and
|
||||
// +1 if a > b.
|
||||
static int Compare(const Bignum & a, const Bignum & b);
|
||||
static bool Equal(const Bignum & a, const Bignum & b) { return Compare(a, b) == 0; }
|
||||
static bool LessEqual(const Bignum & a, const Bignum & b) { return Compare(a, b) <= 0; }
|
||||
static bool Less(const Bignum & a, const Bignum & b) { return Compare(a, b) < 0; }
|
||||
// Returns Compare(a + b, c);
|
||||
static int PlusCompare(const Bignum & a, const Bignum & b, const Bignum & c);
|
||||
// Returns a + b == c
|
||||
static bool PlusEqual(const Bignum & a, const Bignum & b, const Bignum & c) { return PlusCompare(a, b, c) == 0; }
|
||||
// Returns a + b <= c
|
||||
static bool PlusLessEqual(const Bignum & a, const Bignum & b, const Bignum & c) { return PlusCompare(a, b, c) <= 0; }
|
||||
// Returns a + b < c
|
||||
static bool PlusLess(const Bignum & a, const Bignum & b, const Bignum & c) { return PlusCompare(a, b, c) < 0; }
|
||||
|
||||
private:
|
||||
typedef uint32_t Chunk;
|
||||
typedef uint64_t DoubleChunk;
|
||||
|
||||
static const int kChunkSize = sizeof(Chunk) * 8;
|
||||
static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8;
|
||||
// With bigit size of 28 we loose some bits, but a double still fits easily
|
||||
// into two chunks, and more importantly we can use the Comba multiplication.
|
||||
static const int kBigitSize = 28;
|
||||
static const Chunk kBigitMask = (1 << kBigitSize) - 1;
|
||||
// Every instance allocates kBigitLength chunks on the stack. Bignums cannot
|
||||
// grow. There are no checks if the stack-allocated space is sufficient.
|
||||
static const int kBigitCapacity = kMaxSignificantBits / kBigitSize;
|
||||
|
||||
void EnsureCapacity(int size)
|
||||
{
|
||||
if (size > kBigitCapacity)
|
||||
{
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
void Align(const Bignum & other);
|
||||
void Clamp();
|
||||
bool IsClamped() const;
|
||||
void Zero();
|
||||
// Requires this to have enough capacity (no tests done).
|
||||
// Updates used_digits_ if necessary.
|
||||
// shift_amount must be < kBigitSize.
|
||||
void BigitsShiftLeft(int shift_amount);
|
||||
// BigitLength includes the "hidden" digits encoded in the exponent.
|
||||
int BigitLength() const { return used_digits_ + exponent_; }
|
||||
Chunk BigitAt(int index) const;
|
||||
void SubtractTimes(const Bignum & other, int factor);
|
||||
|
||||
Chunk bigits_buffer_[kBigitCapacity];
|
||||
// A vector backed by bigits_buffer_. This way accesses to the array are
|
||||
// checked for out-of-bounds errors.
|
||||
Vector<Chunk> bigits_;
|
||||
int used_digits_;
|
||||
// The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
|
||||
int exponent_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Bignum);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_BIGNUM_H_
|
@ -1,176 +0,0 @@
|
||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include "cached-powers.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
struct CachedPower {
|
||||
uint64_t significand;
|
||||
int16_t binary_exponent;
|
||||
int16_t decimal_exponent;
|
||||
};
|
||||
|
||||
static const CachedPower kCachedPowers[] = {
|
||||
{UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348},
|
||||
{UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340},
|
||||
{UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332},
|
||||
{UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324},
|
||||
{UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316},
|
||||
{UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308},
|
||||
{UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300},
|
||||
{UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292},
|
||||
{UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284},
|
||||
{UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276},
|
||||
{UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268},
|
||||
{UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260},
|
||||
{UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252},
|
||||
{UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244},
|
||||
{UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236},
|
||||
{UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228},
|
||||
{UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220},
|
||||
{UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212},
|
||||
{UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204},
|
||||
{UINT64_2PART_C(0xef340a98, 172aace5), -715, -196},
|
||||
{UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188},
|
||||
{UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180},
|
||||
{UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172},
|
||||
{UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164},
|
||||
{UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156},
|
||||
{UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148},
|
||||
{UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140},
|
||||
{UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132},
|
||||
{UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124},
|
||||
{UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116},
|
||||
{UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108},
|
||||
{UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100},
|
||||
{UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92},
|
||||
{UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84},
|
||||
{UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76},
|
||||
{UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68},
|
||||
{UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60},
|
||||
{UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52},
|
||||
{UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44},
|
||||
{UINT64_2PART_C(0xaa242499, 697392d3), -183, -36},
|
||||
{UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28},
|
||||
{UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20},
|
||||
{UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12},
|
||||
{UINT64_2PART_C(0xd1b71758, e219652c), -77, -4},
|
||||
{UINT64_2PART_C(0x9c400000, 00000000), -50, 4},
|
||||
{UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12},
|
||||
{UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20},
|
||||
{UINT64_2PART_C(0x813f3978, f8940984), 30, 28},
|
||||
{UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36},
|
||||
{UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44},
|
||||
{UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52},
|
||||
{UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60},
|
||||
{UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68},
|
||||
{UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76},
|
||||
{UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84},
|
||||
{UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92},
|
||||
{UINT64_2PART_C(0x924d692c, a61be758), 269, 100},
|
||||
{UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108},
|
||||
{UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116},
|
||||
{UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124},
|
||||
{UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132},
|
||||
{UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140},
|
||||
{UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148},
|
||||
{UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156},
|
||||
{UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164},
|
||||
{UINT64_2PART_C(0xa59bc234, db398c25), 508, 172},
|
||||
{UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180},
|
||||
{UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188},
|
||||
{UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196},
|
||||
{UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204},
|
||||
{UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212},
|
||||
{UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220},
|
||||
{UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228},
|
||||
{UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236},
|
||||
{UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244},
|
||||
{UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252},
|
||||
{UINT64_2PART_C(0xd01fef10, a657842c), 800, 260},
|
||||
{UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268},
|
||||
{UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276},
|
||||
{UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284},
|
||||
{UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292},
|
||||
{UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300},
|
||||
{UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308},
|
||||
{UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316},
|
||||
{UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324},
|
||||
{UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332},
|
||||
{UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340},
|
||||
};
|
||||
|
||||
static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers);
|
||||
static const int kCachedPowersOffset = 348; // -1 * the first decimal_exponent.
|
||||
static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
|
||||
// Difference between the decimal exponents in the table above.
|
||||
const int PowersOfTenCache::kDecimalExponentDistance = 8;
|
||||
const int PowersOfTenCache::kMinDecimalExponent = -348;
|
||||
const int PowersOfTenCache::kMaxDecimalExponent = 340;
|
||||
|
||||
void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
|
||||
int min_exponent,
|
||||
int max_exponent,
|
||||
DiyFp* power,
|
||||
int* decimal_exponent) {
|
||||
int kQ = DiyFp::kSignificandSize;
|
||||
double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10);
|
||||
int foo = kCachedPowersOffset;
|
||||
int index =
|
||||
(foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1;
|
||||
ASSERT(0 <= index && index < kCachedPowersLength);
|
||||
CachedPower cached_power = kCachedPowers[index];
|
||||
ASSERT(min_exponent <= cached_power.binary_exponent);
|
||||
(void) max_exponent; // Mark variable as used.
|
||||
ASSERT(cached_power.binary_exponent <= max_exponent);
|
||||
*decimal_exponent = cached_power.decimal_exponent;
|
||||
*power = DiyFp(cached_power.significand, cached_power.binary_exponent);
|
||||
}
|
||||
|
||||
|
||||
void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent,
|
||||
DiyFp* power,
|
||||
int* found_exponent) {
|
||||
ASSERT(kMinDecimalExponent <= requested_exponent);
|
||||
ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance);
|
||||
int index =
|
||||
(requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance;
|
||||
CachedPower cached_power = kCachedPowers[index];
|
||||
*power = DiyFp(cached_power.significand, cached_power.binary_exponent);
|
||||
*found_exponent = cached_power.decimal_exponent;
|
||||
ASSERT(*found_exponent <= requested_exponent);
|
||||
ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance);
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
@ -1,60 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_CACHED_POWERS_H_
|
||||
#define DOUBLE_CONVERSION_CACHED_POWERS_H_
|
||||
|
||||
#include "diy-fp.h"
|
||||
|
||||
namespace double_conversion
|
||||
{
|
||||
|
||||
class PowersOfTenCache
|
||||
{
|
||||
public:
|
||||
// Not all powers of ten are cached. The decimal exponent of two neighboring
|
||||
// cached numbers will differ by kDecimalExponentDistance.
|
||||
static const int kDecimalExponentDistance;
|
||||
|
||||
static const int kMinDecimalExponent;
|
||||
static const int kMaxDecimalExponent;
|
||||
|
||||
// Returns a cached power-of-ten with a binary exponent in the range
|
||||
// [min_exponent; max_exponent] (boundaries included).
|
||||
static void GetCachedPowerForBinaryExponentRange(int min_exponent, int max_exponent, DiyFp * power, int * decimal_exponent);
|
||||
|
||||
// Returns a cached power of ten x ~= 10^k such that
|
||||
// k <= decimal_exponent < k + kCachedPowersDecimalDistance.
|
||||
// The given decimal_exponent must satisfy
|
||||
// kMinDecimalExponent <= requested_exponent, and
|
||||
// requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance.
|
||||
static void GetCachedPowerForDecimalExponent(int requested_exponent, DiyFp * power, int * found_exponent);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_CACHED_POWERS_H_
|
@ -1,86 +0,0 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
int level;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
const uInt max = (uInt)-1;
|
||||
uLong left;
|
||||
|
||||
left = *destLen;
|
||||
*destLen = 0;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = 0;
|
||||
stream.next_in = (z_const Bytef *)source;
|
||||
stream.avail_in = 0;
|
||||
|
||||
do {
|
||||
if (stream.avail_out == 0) {
|
||||
stream.avail_out = left > (uLong)max ? max : (uInt)left;
|
||||
left -= stream.avail_out;
|
||||
}
|
||||
if (stream.avail_in == 0) {
|
||||
stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen;
|
||||
sourceLen -= stream.avail_in;
|
||||
}
|
||||
err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
|
||||
} while (err == Z_OK);
|
||||
|
||||
*destLen = stream.total_out;
|
||||
deflateEnd(&stream);
|
||||
return err == Z_STREAM_END ? Z_OK : err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT compress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
If the default memLevel or windowBits for deflateInit() is changed, then
|
||||
this function needs to be updated.
|
||||
*/
|
||||
uLong ZEXPORT compressBound (sourceLen)
|
||||
uLong sourceLen;
|
||||
{
|
||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
|
||||
(sourceLen >> 25) + 13;
|
||||
}
|
@ -1,444 +0,0 @@
|
||||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
||||
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
|
||||
* tables for updating the shift register in one step with three exclusive-ors
|
||||
* instead of four steps with four exclusive-ors. This results in about a
|
||||
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
/*
|
||||
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
|
||||
protection on the static variables used to control the first-use generation
|
||||
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
|
||||
first call get_crc_table() to initialize the tables before allowing more than
|
||||
one thread to use crc32().
|
||||
|
||||
DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
|
||||
*/
|
||||
|
||||
#ifdef MAKECRCH
|
||||
# include <stdio.h>
|
||||
# ifndef DYNAMIC_CRC_TABLE
|
||||
# define DYNAMIC_CRC_TABLE
|
||||
# endif /* !DYNAMIC_CRC_TABLE */
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#include "zutil.h" /* for STDC and FAR definitions */
|
||||
|
||||
#define local static
|
||||
|
||||
/* Definitions for doing the crc four data bytes at a time. */
|
||||
#if !defined(NOBYFOUR) && defined(Z_U4)
|
||||
# define BYFOUR
|
||||
#endif
|
||||
#ifdef BYFOUR
|
||||
local unsigned long crc32_little OF((unsigned long,
|
||||
const unsigned char FAR *, z_size_t));
|
||||
local unsigned long crc32_big OF((unsigned long,
|
||||
const unsigned char FAR *, z_size_t));
|
||||
# define TBLS 8
|
||||
#else
|
||||
# define TBLS 1
|
||||
#endif /* BYFOUR */
|
||||
|
||||
/* Local functions for crc concatenation */
|
||||
local unsigned long gf2_matrix_times OF((unsigned long *mat,
|
||||
unsigned long vec));
|
||||
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
|
||||
local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
|
||||
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
|
||||
local volatile int crc_table_empty = 1;
|
||||
local z_crc_t FAR crc_table[TBLS][256];
|
||||
local void make_crc_table OF((void));
|
||||
#ifdef MAKECRCH
|
||||
local void write_table OF((FILE *, const z_crc_t FAR *));
|
||||
#endif /* MAKECRCH */
|
||||
/*
|
||||
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
|
||||
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
|
||||
|
||||
Polynomials over GF(2) are represented in binary, one bit per coefficient,
|
||||
with the lowest powers in the most significant bit. Then adding polynomials
|
||||
is just exclusive-or, and multiplying a polynomial by x is a right shift by
|
||||
one. If we call the above polynomial p, and represent a byte as the
|
||||
polynomial q, also with the lowest power in the most significant bit (so the
|
||||
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
|
||||
where a mod b means the remainder after dividing a by b.
|
||||
|
||||
This calculation is done using the shift-register method of multiplying and
|
||||
taking the remainder. The register is initialized to zero, and for each
|
||||
incoming bit, x^32 is added mod p to the register if the bit is a one (where
|
||||
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
|
||||
x (which is shifting right by one and adding x^32 mod p if the bit shifted
|
||||
out is a one). We start with the highest power (least significant bit) of
|
||||
q and repeat for all eight bits of q.
|
||||
|
||||
The first table is simply the CRC of all possible eight bit values. This is
|
||||
all the information needed to generate CRCs on data a byte at a time for all
|
||||
combinations of CRC register values and incoming bytes. The remaining tables
|
||||
allow for word-at-a-time CRC calculation for both big-endian and little-
|
||||
endian machines, where a word is four bytes.
|
||||
*/
|
||||
local void make_crc_table()
|
||||
{
|
||||
z_crc_t c;
|
||||
int n, k;
|
||||
z_crc_t poly; /* polynomial exclusive-or pattern */
|
||||
/* terms of polynomial defining this crc (except x^32): */
|
||||
static volatile int first = 1; /* flag to limit concurrent making */
|
||||
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
|
||||
|
||||
/* See if another task is already doing this (not thread-safe, but better
|
||||
than nothing -- significantly reduces duration of vulnerability in
|
||||
case the advice about DYNAMIC_CRC_TABLE is ignored) */
|
||||
if (first) {
|
||||
first = 0;
|
||||
|
||||
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
|
||||
poly = 0;
|
||||
for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
|
||||
poly |= (z_crc_t)1 << (31 - p[n]);
|
||||
|
||||
/* generate a crc for every 8-bit value */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (z_crc_t)n;
|
||||
for (k = 0; k < 8; k++)
|
||||
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||
crc_table[0][n] = c;
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
/* generate crc for each value followed by one, two, and three zeros,
|
||||
and then the byte reversal of those as well as the first table */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = crc_table[0][n];
|
||||
crc_table[4][n] = ZSWAP32(c);
|
||||
for (k = 1; k < 4; k++) {
|
||||
c = crc_table[0][c & 0xff] ^ (c >> 8);
|
||||
crc_table[k][n] = c;
|
||||
crc_table[k + 4][n] = ZSWAP32(c);
|
||||
}
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
|
||||
crc_table_empty = 0;
|
||||
}
|
||||
else { /* not first */
|
||||
/* wait for the other guy to finish (not efficient, but rare) */
|
||||
while (crc_table_empty)
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
/* write out CRC tables to crc32.h */
|
||||
{
|
||||
FILE *out;
|
||||
|
||||
out = fopen("crc32.h", "w");
|
||||
if (out == NULL) return;
|
||||
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
|
||||
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
|
||||
fprintf(out, "local const z_crc_t FAR ");
|
||||
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
|
||||
write_table(out, crc_table[0]);
|
||||
# ifdef BYFOUR
|
||||
fprintf(out, "#ifdef BYFOUR\n");
|
||||
for (k = 1; k < 8; k++) {
|
||||
fprintf(out, " },\n {\n");
|
||||
write_table(out, crc_table[k]);
|
||||
}
|
||||
fprintf(out, "#endif\n");
|
||||
# endif /* BYFOUR */
|
||||
fprintf(out, " }\n};\n");
|
||||
fclose(out);
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
local void write_table(out, table)
|
||||
FILE *out;
|
||||
const z_crc_t FAR *table;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ",
|
||||
(unsigned long)(table[n]),
|
||||
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#else /* !DYNAMIC_CRC_TABLE */
|
||||
/* ========================================================================
|
||||
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
|
||||
*/
|
||||
#include "crc32.h"
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
const z_crc_t FAR * ZEXPORT get_crc_table()
|
||||
{
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
return (const z_crc_t FAR *)crc_table;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
|
||||
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned long ZEXPORT crc32_z(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
z_size_t len;
|
||||
{
|
||||
if (buf == Z_NULL) return 0UL;
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
#ifdef BYFOUR
|
||||
if (sizeof(void *) == sizeof(ptrdiff_t)) {
|
||||
z_crc_t endian;
|
||||
|
||||
endian = 1;
|
||||
if (*((unsigned char *)(&endian)))
|
||||
return crc32_little(crc, buf, len);
|
||||
else
|
||||
return crc32_big(crc, buf, len);
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
crc = crc ^ 0xffffffffUL;
|
||||
while (len >= 8) {
|
||||
DO8;
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
DO1;
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffffUL;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned long ZEXPORT crc32(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
uInt len;
|
||||
{
|
||||
return crc32_z(crc, buf, len);
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
|
||||
/*
|
||||
This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
|
||||
integer pointer type. This violates the strict aliasing rule, where a
|
||||
compiler can assume, for optimization purposes, that two pointers to
|
||||
fundamentally different types won't ever point to the same memory. This can
|
||||
manifest as a problem only if one of the pointers is written to. This code
|
||||
only reads from those pointers. So long as this code remains isolated in
|
||||
this compilation unit, there won't be a problem. For this reason, this code
|
||||
should not be copied and pasted into a compilation unit in which other code
|
||||
writes to the buffer that is passed to these routines.
|
||||
*/
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOLIT4 c ^= *buf4++; \
|
||||
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
|
||||
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
|
||||
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_little(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
z_size_t len;
|
||||
{
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
|
||||
c = (z_crc_t)crc;
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOLIT32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOLIT4;
|
||||
len -= 4;
|
||||
}
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)c;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOBIG4 c ^= *buf4++; \
|
||||
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
|
||||
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
|
||||
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_big(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
z_size_t len;
|
||||
{
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
|
||||
c = ZSWAP32((z_crc_t)crc);
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOBIG32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOBIG4;
|
||||
len -= 4;
|
||||
}
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)(ZSWAP32(c));
|
||||
}
|
||||
|
||||
#endif /* BYFOUR */
|
||||
|
||||
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long gf2_matrix_times(mat, vec)
|
||||
unsigned long *mat;
|
||||
unsigned long vec;
|
||||
{
|
||||
unsigned long sum;
|
||||
|
||||
sum = 0;
|
||||
while (vec) {
|
||||
if (vec & 1)
|
||||
sum ^= *mat;
|
||||
vec >>= 1;
|
||||
mat++;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local void gf2_matrix_square(square, mat)
|
||||
unsigned long *square;
|
||||
unsigned long *mat;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < GF2_DIM; n++)
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local uLong crc32_combine_(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
int n;
|
||||
unsigned long row;
|
||||
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
|
||||
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
|
||||
|
||||
/* degenerate case (also disallow negative lengths) */
|
||||
if (len2 <= 0)
|
||||
return crc1;
|
||||
|
||||
/* put operator for one zero bit in odd */
|
||||
odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
|
||||
row = 1;
|
||||
for (n = 1; n < GF2_DIM; n++) {
|
||||
odd[n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
|
||||
/* put operator for two zero bits in even */
|
||||
gf2_matrix_square(even, odd);
|
||||
|
||||
/* put operator for four zero bits in odd */
|
||||
gf2_matrix_square(odd, even);
|
||||
|
||||
/* apply len2 zeros to crc1 (first square will put the operator for one
|
||||
zero byte, eight zero bits, in even) */
|
||||
do {
|
||||
/* apply zeros operator for this bit of len2 */
|
||||
gf2_matrix_square(even, odd);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(even, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
if (len2 == 0)
|
||||
break;
|
||||
|
||||
/* another iteration of the loop with odd and even swapped */
|
||||
gf2_matrix_square(odd, even);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(odd, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
} while (len2 != 0);
|
||||
|
||||
/* return combined crc */
|
||||
crc1 ^= crc2;
|
||||
return crc1;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off_t len2;
|
||||
{
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
||||
|
||||
uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
@ -1,241 +0,0 @@
|
||||
/* crc32.h -- tables for rapid CRC calculation
|
||||
* Generated automatically by crc32.c
|
||||
*/
|
||||
|
||||
local const z_crc_t FAR crc_table[TBLS][256]
|
||||
= {{0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL,
|
||||
0x79dcb8a4UL, 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL,
|
||||
0xf3b97148UL, 0x84be41deUL, 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, 0x646ba8c0UL, 0xfd62f97aUL,
|
||||
0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, 0xa2677172UL,
|
||||
0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
|
||||
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL,
|
||||
0xcfba9599UL, 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL,
|
||||
0xb6662d3dUL, 0x76dc4190UL, 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, 0x9fbfe4a5UL, 0xe8b8d433UL,
|
||||
0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, 0x6b6b51f4UL,
|
||||
0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
|
||||
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL,
|
||||
0xd4bb30e2UL, 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL,
|
||||
0x44042d73UL, 0x33031de5UL, 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, 0xc90c2086UL, 0x5768b525UL,
|
||||
0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, 0x2eb40d81UL,
|
||||
0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
|
||||
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL,
|
||||
0xf00f9344UL, 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL,
|
||||
0x89d32be0UL, 0x10da7a5aUL, 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, 0xd6d6a3e8UL, 0xa1d1937eUL,
|
||||
0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, 0x36034af6UL,
|
||||
0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
|
||||
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL,
|
||||
0xb5d0cf31UL, 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL,
|
||||
0x72076785UL, 0x05005713UL, 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, 0xe5d5be0dUL, 0x7cdcefb7UL,
|
||||
0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, 0x18b74777UL,
|
||||
0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
|
||||
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL,
|
||||
0x40df0b66UL, 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL,
|
||||
0x24b4a3a6UL, 0xbad03605UL, 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, 0x5d681b02UL, 0x2a6f2b94UL,
|
||||
0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, 0x2d02ef8dUL
|
||||
#ifdef BYFOUR
|
||||
},
|
||||
{0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL,
|
||||
0xd1c2bb49UL, 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL,
|
||||
0x78f470d3UL, 0x61ef4192UL, 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, 0x9b00a918UL, 0xb02dfadbUL,
|
||||
0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, 0xbea97761UL,
|
||||
0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
|
||||
0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL,
|
||||
0x891c9175UL, 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL,
|
||||
0x58de2a3cUL, 0xf0794f05UL, 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, 0xa623e883UL, 0xbf38d9c2UL,
|
||||
0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, 0xbabb5d54UL,
|
||||
0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
|
||||
0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL,
|
||||
0x4ed03864UL, 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL,
|
||||
0xc94824abUL, 0xd05315eaUL, 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, 0x04122a35UL, 0x4b53bcf2UL,
|
||||
0x52488db3UL, 0x7965de70UL, 0x607eef31UL, 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, 0x9a9107bbUL,
|
||||
0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
|
||||
0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL,
|
||||
0x71418a1aUL, 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL,
|
||||
0xa0833153UL, 0x8bae6290UL, 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, 0xae07bce9UL, 0xb71c8da8UL,
|
||||
0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, 0x54e85463UL,
|
||||
0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
|
||||
0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL,
|
||||
0x516bd0f5UL, 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL,
|
||||
0x9da070c8UL, 0x84bb4189UL, 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, 0x7e54a903UL, 0x5579fac0UL,
|
||||
0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, 0xce7953d8UL,
|
||||
0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
|
||||
0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL,
|
||||
0xa4911b66UL, 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL,
|
||||
0x3f91b27eUL, 0x70d024b9UL, 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, 0xee530937UL, 0xf7483876UL,
|
||||
0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, 0x9324fd72UL},
|
||||
{0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL,
|
||||
0x0fd13b8fUL, 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL,
|
||||
0x1fa2771eUL, 0x1e601d29UL, 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, 0x13f798ffUL, 0x11b126a6UL,
|
||||
0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, 0x3a0bf8b9UL,
|
||||
0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
|
||||
0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL,
|
||||
0x20e69922UL, 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL,
|
||||
0x2f37a2adUL, 0x709a8dc0UL, 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, 0x7417f172UL, 0x75d59b45UL,
|
||||
0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, 0x6cbc2eb0UL,
|
||||
0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
|
||||
0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL,
|
||||
0x4a917579UL, 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL,
|
||||
0x41cd3244UL, 0x400f5873UL, 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, 0x56b7d609UL, 0x53f8c08cUL,
|
||||
0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, 0x5c29fb03UL,
|
||||
0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
|
||||
0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL,
|
||||
0xfd13b8f0UL, 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL,
|
||||
0xf2c2837fUL, 0xf0843d26UL, 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, 0xd9785d60UL, 0xd8ba3757UL,
|
||||
0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, 0xd4efd8b6UL,
|
||||
0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
|
||||
0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL,
|
||||
0xcd866d43UL, 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL,
|
||||
0x9522eaf2UL, 0x94e080c5UL, 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, 0x99770513UL, 0x9b31bb4aUL,
|
||||
0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, 0x88c623b5UL,
|
||||
0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
|
||||
0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL,
|
||||
0xa4755576UL, 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL,
|
||||
0xb782cd89UL, 0xb2cddb0cUL, 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, 0xb853f606UL, 0xb9919c31UL,
|
||||
0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, 0xbe9834edUL},
|
||||
{0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL,
|
||||
0x7d084f8aUL, 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, 0x58631056UL, 0x5019579fUL, 0xe8a530faUL,
|
||||
0xfa109f14UL, 0x42acf871UL, 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, 0x2d111815UL, 0x3fa4b7fbUL,
|
||||
0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, 0xb28700d0UL,
|
||||
0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
|
||||
0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL,
|
||||
0xd540a77dUL, 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL,
|
||||
0xa848e8f7UL, 0x9b14583dUL, 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, 0xbe7f07e1UL, 0x06c36084UL,
|
||||
0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, 0xcb0d0fa2UL,
|
||||
0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
|
||||
0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL,
|
||||
0x299358edUL, 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, 0x462eb889UL, 0x549b1767UL, 0xec277002UL,
|
||||
0x71f048bbUL, 0xc94c2fdeUL, 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, 0x798a0f72UL, 0xe45d37cbUL,
|
||||
0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, 0x99557841UL,
|
||||
0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
|
||||
0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL,
|
||||
0xbd40e1a4UL, 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL,
|
||||
0xc048ae2eUL, 0xd2fd01c0UL, 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, 0x4d6b1905UL, 0xf5d77e60UL,
|
||||
0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, 0x22d6f961UL,
|
||||
0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
|
||||
0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL,
|
||||
0xef189647UL, 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL,
|
||||
0x5326b1daUL, 0xeb9ad6bfUL, 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, 0x842736dbUL, 0x96929935UL,
|
||||
0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, 0xbb838120UL,
|
||||
0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
|
||||
0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL,
|
||||
0xb9c2a15cUL, 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL,
|
||||
0x94d3b949UL, 0x090481f0UL, 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, 0xe9dbf6c3UL, 0x516791a6UL,
|
||||
0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, 0xde0506f1UL},
|
||||
{0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL,
|
||||
0xa4b8dc79UL, 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL,
|
||||
0x4871b9f3UL, 0xde41be84UL, 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, 0xc0a86b64UL, 0x7af962fdUL,
|
||||
0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, 0x727167a2UL,
|
||||
0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
|
||||
0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL,
|
||||
0x9995bacfUL, 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL,
|
||||
0x3d2d66b6UL, 0x9041dc76UL, 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, 0xa5e4bf9fUL, 0x33d4b8e8UL,
|
||||
0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, 0xf4516b6bUL,
|
||||
0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
|
||||
0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL,
|
||||
0xe230bbd4UL, 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL,
|
||||
0x732d0444UL, 0xe51d0333UL, 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, 0x86200cc9UL, 0x25b56857UL,
|
||||
0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, 0x810db42eUL,
|
||||
0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
|
||||
0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL,
|
||||
0x44930ff0UL, 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL,
|
||||
0xe02bd389UL, 0x5a7ada10UL, 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, 0xe8a3d6d6UL, 0x7e93d1a1UL,
|
||||
0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, 0xf64a0336UL,
|
||||
0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
|
||||
0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL,
|
||||
0x31cfd0b5UL, 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL,
|
||||
0x85670772UL, 0x13570005UL, 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, 0x0dbed5e5UL, 0xb7efdc7cUL,
|
||||
0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, 0x7747b718UL,
|
||||
0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
|
||||
0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL,
|
||||
0x660bdf40UL, 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL,
|
||||
0xa6a3b424UL, 0x0536d0baUL, 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, 0x021b685dUL, 0x942b6f2aUL,
|
||||
0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, 0x8def022dUL},
|
||||
{0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL,
|
||||
0x49bbc2d1UL, 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL,
|
||||
0xd370f478UL, 0x9241ef61UL, 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, 0x18a9009bUL, 0xdbfa2db0UL,
|
||||
0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, 0x6177a9beUL,
|
||||
0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
|
||||
0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL,
|
||||
0x75911c89UL, 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL,
|
||||
0x3c2ade58UL, 0x054f79f0UL, 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, 0x83e823a6UL, 0xc2d938bfUL,
|
||||
0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, 0x545dbbbaUL,
|
||||
0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
|
||||
0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL,
|
||||
0x6438d04eUL, 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL,
|
||||
0xab2448c9UL, 0xea1553d0UL, 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, 0x352a1204UL, 0xf2bc534bUL,
|
||||
0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, 0xbb07919aUL,
|
||||
0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
|
||||
0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL,
|
||||
0x1a8a4171UL, 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL,
|
||||
0x533183a0UL, 0x9062ae8bUL, 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, 0xe9bc07aeUL, 0xa88d1cb7UL,
|
||||
0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, 0x6354e854UL,
|
||||
0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
|
||||
0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL,
|
||||
0xf5d06b51UL, 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL,
|
||||
0xc870a09dUL, 0x8941bb84UL, 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, 0x03a9547eUL, 0xc0fa7955UL,
|
||||
0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, 0xd85379ceUL,
|
||||
0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
|
||||
0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL,
|
||||
0x661b91a4UL, 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL,
|
||||
0x7eb2913fUL, 0xb924d070UL, 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, 0x370953eeUL, 0x763848f7UL,
|
||||
0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, 0x72fd2493UL},
|
||||
{0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL,
|
||||
0x8f3bd10fUL, 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL,
|
||||
0x1e77a21fUL, 0x291d601eUL, 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, 0xff98f713UL, 0xa626b111UL,
|
||||
0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, 0xb9f80b3aUL,
|
||||
0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
|
||||
0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL,
|
||||
0x2299e620UL, 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL,
|
||||
0xada2372fUL, 0xc08d9a70UL, 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, 0x72f11774UL, 0x459bd575UL,
|
||||
0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, 0xb02ebc6cUL,
|
||||
0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
|
||||
0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL,
|
||||
0x7975914aUL, 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL,
|
||||
0x4432cd41UL, 0x73580f40UL, 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, 0x09d6b756UL, 0x8cc0f853UL,
|
||||
0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, 0x03fb295cUL,
|
||||
0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
|
||||
0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL,
|
||||
0xf0b813fdUL, 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL,
|
||||
0x7f83c2f2UL, 0x263d84f0UL, 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, 0x605d78d9UL, 0x5737bad8UL,
|
||||
0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, 0xb6d8efd4UL,
|
||||
0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
|
||||
0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL,
|
||||
0x436d86cdUL, 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL,
|
||||
0xf2ea2295UL, 0xc580e094UL, 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, 0x13057799UL, 0x4abb319bUL,
|
||||
0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, 0xb523c688UL,
|
||||
0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
|
||||
0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL,
|
||||
0x765575a4UL, 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL,
|
||||
0x89cd82b7UL, 0x0cdbcdb2UL, 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, 0x06f653b8UL, 0x319c91b9UL,
|
||||
0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, 0xed3498beUL},
|
||||
{0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL,
|
||||
0x8a4f087dUL, 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL,
|
||||
0x149f10faUL, 0x71f8ac42UL, 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, 0x1518112dUL, 0xfbb7a43fUL,
|
||||
0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, 0xd00087b2UL,
|
||||
0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
|
||||
0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL,
|
||||
0x7da740d5UL, 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL,
|
||||
0xf7e848a8UL, 0x3d58149bUL, 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, 0xe1077fbeUL, 0x8460c306UL,
|
||||
0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, 0xa20f0dcbUL,
|
||||
0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
|
||||
0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL,
|
||||
0xed589329UL, 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL,
|
||||
0xbb48f071UL, 0xde2f4cc9UL, 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, 0x720f8a79UL, 0xcb375de4UL,
|
||||
0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, 0x41785599UL,
|
||||
0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
|
||||
0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL,
|
||||
0xa4e140bdUL, 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL,
|
||||
0x2eae48c0UL, 0xc001fdd2UL, 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, 0x05196b4dUL, 0x607ed7f5UL,
|
||||
0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, 0x61f9d622UL,
|
||||
0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
|
||||
0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL,
|
||||
0x479618efUL, 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL,
|
||||
0xdab12653UL, 0xbfd69aebUL, 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, 0xdb362784UL, 0x35999296UL,
|
||||
0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, 0x208183bbUL,
|
||||
0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
|
||||
0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL,
|
||||
0x5ca1c2b9UL, 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL,
|
||||
0x49b9d394UL, 0xf0810409UL, 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, 0xc3f6dbe9UL, 0xa6916751UL,
|
||||
0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, 0xf10605deUL
|
||||
#endif
|
||||
}};
|
File diff suppressed because it is too large
Load Diff
@ -1,355 +0,0 @@
|
||||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-2016 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef DEFLATE_H
|
||||
#define DEFLATE_H
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
/* define NO_GZIP when compiling if you want to disable gzip header and
|
||||
trailer creation by deflate(). NO_GZIP would be used to avoid linking in
|
||||
the crc code when it is not needed. For shared libraries, gzip encoding
|
||||
should be left enabled. */
|
||||
#ifndef NO_GZIP
|
||||
# define GZIP
|
||||
#endif
|
||||
|
||||
/* ===========================================================================
|
||||
* Internal compression state.
|
||||
*/
|
||||
|
||||
#define LENGTH_CODES 29
|
||||
/* number of length codes, not counting the special END_BLOCK code */
|
||||
|
||||
#define LITERALS 256
|
||||
/* number of literal bytes 0..255 */
|
||||
|
||||
#define L_CODES (LITERALS + 1 + LENGTH_CODES)
|
||||
/* number of Literal or Length codes, including the END_BLOCK code */
|
||||
|
||||
#define D_CODES 30
|
||||
/* number of distance codes */
|
||||
|
||||
#define BL_CODES 19
|
||||
/* number of codes used to transfer the bit lengths */
|
||||
|
||||
#define HEAP_SIZE (2 * L_CODES + 1)
|
||||
/* maximum heap size */
|
||||
|
||||
#define MAX_BITS 15
|
||||
/* All codes must not exceed MAX_BITS bits */
|
||||
|
||||
#define Buf_size 16
|
||||
/* size of bit buffer in bi_buf */
|
||||
|
||||
#define INIT_STATE 42 /* zlib header -> BUSY_STATE */
|
||||
#ifdef GZIP
|
||||
# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */
|
||||
#endif
|
||||
#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */
|
||||
#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */
|
||||
#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */
|
||||
#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */
|
||||
#define BUSY_STATE 113 /* deflate -> FINISH_STATE */
|
||||
#define FINISH_STATE 666 /* stream complete */
|
||||
/* Stream status */
|
||||
|
||||
|
||||
/* Data structure describing a single value and its code string. */
|
||||
typedef struct ct_data_s
|
||||
{
|
||||
union
|
||||
{
|
||||
ush freq; /* frequency count */
|
||||
ush code; /* bit string */
|
||||
} fc;
|
||||
union
|
||||
{
|
||||
ush dad; /* father node in Huffman tree */
|
||||
ush len; /* length of bit string */
|
||||
} dl;
|
||||
} FAR ct_data;
|
||||
|
||||
#define Freq fc.freq
|
||||
#define Code fc.code
|
||||
#define Dad dl.dad
|
||||
#define Len dl.len
|
||||
|
||||
typedef struct static_tree_desc_s static_tree_desc;
|
||||
|
||||
typedef struct tree_desc_s
|
||||
{
|
||||
ct_data * dyn_tree; /* the dynamic tree */
|
||||
int max_code; /* largest code with non zero frequency */
|
||||
const static_tree_desc * stat_desc; /* the corresponding static tree */
|
||||
} FAR tree_desc;
|
||||
|
||||
typedef ush Pos;
|
||||
typedef Pos FAR Posf;
|
||||
typedef unsigned IPos;
|
||||
|
||||
/* A Pos is an index in the character window. We use short instead of int to
|
||||
* save space in the various tables. IPos is used only for parameter passing.
|
||||
*/
|
||||
|
||||
typedef struct internal_state
|
||||
{
|
||||
z_streamp strm; /* pointer back to this zlib stream */
|
||||
int status; /* as the name implies */
|
||||
Bytef * pending_buf; /* output still pending */
|
||||
ulg pending_buf_size; /* size of pending_buf */
|
||||
Bytef * pending_out; /* next pending byte to output to the stream */
|
||||
ulg pending; /* nb of bytes in the pending buffer */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
gz_headerp gzhead; /* gzip header information to write */
|
||||
ulg gzindex; /* where in extra, name, or comment */
|
||||
Byte method; /* can only be DEFLATED */
|
||||
int last_flush; /* value of flush param for previous deflate call */
|
||||
|
||||
/* used by deflate.c: */
|
||||
|
||||
uInt w_size; /* LZ77 window size (32K by default) */
|
||||
uInt w_bits; /* log2(w_size) (8..16) */
|
||||
uInt w_mask; /* w_size - 1 */
|
||||
|
||||
Bytef * window;
|
||||
/* Sliding window. Input bytes are read into the second half of the window,
|
||||
* and move to the first half later to keep a dictionary of at least wSize
|
||||
* bytes. With this organization, matches are limited to a distance of
|
||||
* wSize-MAX_MATCH bytes, but this ensures that IO is always
|
||||
* performed with a length multiple of the block size. Also, it limits
|
||||
* the window size to 64K, which is quite useful on MS-DOS.
|
||||
* To do: use the user input buffer as sliding window.
|
||||
*/
|
||||
|
||||
ulg window_size;
|
||||
/* Actual size of window: 2*wSize, except when the user input buffer
|
||||
* is directly used as sliding window.
|
||||
*/
|
||||
|
||||
Posf * prev;
|
||||
/* Link to older string with same hash index. To limit the size of this
|
||||
* array to 64K, this link is maintained only for the last 32K strings.
|
||||
* An index in this array is thus a window index modulo 32K.
|
||||
*/
|
||||
|
||||
Posf * head; /* Heads of the hash chains or NIL. */
|
||||
|
||||
uInt ins_h; /* hash index of string to be inserted */
|
||||
uInt hash_size; /* number of elements in hash table */
|
||||
uInt hash_bits; /* log2(hash_size) */
|
||||
uInt hash_mask; /* hash_size-1 */
|
||||
|
||||
uInt hash_shift;
|
||||
/* Number of bits by which ins_h must be shifted at each input
|
||||
* step. It must be such that after MIN_MATCH steps, the oldest
|
||||
* byte no longer takes part in the hash key, that is:
|
||||
* hash_shift * MIN_MATCH >= hash_bits
|
||||
*/
|
||||
|
||||
long block_start;
|
||||
/* Window position at the beginning of the current output block. Gets
|
||||
* negative when the window is moved backwards.
|
||||
*/
|
||||
|
||||
uInt match_length; /* length of best match */
|
||||
IPos prev_match; /* previous match */
|
||||
int match_available; /* set if previous match exists */
|
||||
uInt strstart; /* start of string to insert */
|
||||
uInt match_start; /* start of matching string */
|
||||
uInt lookahead; /* number of valid bytes ahead in window */
|
||||
|
||||
uInt prev_length;
|
||||
/* Length of the best match at previous step. Matches not greater than this
|
||||
* are discarded. This is used in the lazy match evaluation.
|
||||
*/
|
||||
|
||||
uInt max_chain_length;
|
||||
/* To speed up deflation, hash chains are never searched beyond this
|
||||
* length. A higher limit improves compression ratio but degrades the
|
||||
* speed.
|
||||
*/
|
||||
|
||||
uInt max_lazy_match;
|
||||
/* Attempt to find a better match only when the current match is strictly
|
||||
* smaller than this value. This mechanism is used only for compression
|
||||
* levels >= 4.
|
||||
*/
|
||||
#define max_insert_length max_lazy_match
|
||||
/* Insert new strings in the hash table only if the match length is not
|
||||
* greater than this length. This saves time but degrades compression.
|
||||
* max_insert_length is used only for compression levels <= 3.
|
||||
*/
|
||||
|
||||
int level; /* compression level (1..9) */
|
||||
int strategy; /* favor or force Huffman coding*/
|
||||
|
||||
uInt good_match;
|
||||
/* Use a faster search when the previous match is longer than this */
|
||||
|
||||
int nice_match; /* Stop searching when current match exceeds this */
|
||||
|
||||
/* used by trees.c: */
|
||||
/* Didn't use ct_data typedef below to suppress compiler warning */
|
||||
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
||||
struct ct_data_s dyn_dtree[2 * D_CODES + 1]; /* distance tree */
|
||||
struct ct_data_s bl_tree[2 * BL_CODES + 1]; /* Huffman tree for bit lengths */
|
||||
|
||||
struct tree_desc_s l_desc; /* desc. for literal tree */
|
||||
struct tree_desc_s d_desc; /* desc. for distance tree */
|
||||
struct tree_desc_s bl_desc; /* desc. for bit length tree */
|
||||
|
||||
ush bl_count[MAX_BITS + 1];
|
||||
/* number of codes at each bit length for an optimal tree */
|
||||
|
||||
int heap[2 * L_CODES + 1]; /* heap used to build the Huffman trees */
|
||||
int heap_len; /* number of elements in the heap */
|
||||
int heap_max; /* element of largest frequency */
|
||||
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
|
||||
* The same heap array is used to build all trees.
|
||||
*/
|
||||
|
||||
uch depth[2 * L_CODES + 1];
|
||||
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
||||
*/
|
||||
|
||||
uchf * l_buf; /* buffer for literals or lengths */
|
||||
|
||||
uInt lit_bufsize;
|
||||
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
||||
* limiting lit_bufsize to 64K:
|
||||
* - frequencies can be kept in 16 bit counters
|
||||
* - if compression is not successful for the first block, all input
|
||||
* data is still in the window so we can still emit a stored block even
|
||||
* when input comes from standard input. (This can also be done for
|
||||
* all blocks if lit_bufsize is not greater than 32K.)
|
||||
* - if compression is not successful for a file smaller than 64K, we can
|
||||
* even emit a stored file instead of a stored block (saving 5 bytes).
|
||||
* This is applicable only for zip (not gzip or zlib).
|
||||
* - creating new Huffman trees less frequently may not provide fast
|
||||
* adaptation to changes in the input data statistics. (Take for
|
||||
* example a binary file with poorly compressible code followed by
|
||||
* a highly compressible string table.) Smaller buffer sizes give
|
||||
* fast adaptation but have of course the overhead of transmitting
|
||||
* trees more frequently.
|
||||
* - I can't count above 4
|
||||
*/
|
||||
|
||||
uInt last_lit; /* running index in l_buf */
|
||||
|
||||
ushf * d_buf;
|
||||
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
||||
* the same number of elements. To use different lengths, an extra flag
|
||||
* array would be necessary.
|
||||
*/
|
||||
|
||||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
uInt matches; /* number of string matches in current block */
|
||||
uInt insert; /* bytes at end of window left to insert */
|
||||
|
||||
#ifdef ZLIB_DEBUG
|
||||
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
|
||||
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
|
||||
#endif
|
||||
|
||||
ush bi_buf;
|
||||
/* Output buffer. bits are inserted starting at the bottom (least
|
||||
* significant bits).
|
||||
*/
|
||||
int bi_valid;
|
||||
/* Number of valid bits in bi_buf. All bits above the last valid bit
|
||||
* are always zero.
|
||||
*/
|
||||
|
||||
ulg high_water;
|
||||
/* High water mark offset in window for initialized bytes -- bytes above
|
||||
* this are set to zero in order to avoid memory check warnings when
|
||||
* longest match routines access bytes past the input. This is then
|
||||
* updated to the new high water mark.
|
||||
*/
|
||||
|
||||
} FAR deflate_state;
|
||||
|
||||
/* Output a byte on the stream.
|
||||
* IN assertion: there is enough room in pending_buf.
|
||||
*/
|
||||
#define put_byte(s, c) \
|
||||
{ \
|
||||
s->pending_buf[s->pending++] = (Bytef)(c); \
|
||||
}
|
||||
|
||||
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
||||
/* Minimum amount of lookahead, except at the end of the input file.
|
||||
* See deflate.c for comments about the MIN_MATCH+1.
|
||||
*/
|
||||
|
||||
#define MAX_DIST(s) ((s)->w_size - MIN_LOOKAHEAD)
|
||||
/* In order to simplify the code, particularly on 16 bit machines, match
|
||||
* distances are limited to MAX_DIST instead of WSIZE.
|
||||
*/
|
||||
|
||||
#define WIN_INIT MAX_MATCH
|
||||
/* Number of bytes after end of data in window to initialize in order to avoid
|
||||
memory checker errors from longest match routines */
|
||||
|
||||
/* in trees.c */
|
||||
void ZLIB_INTERNAL _tr_init OF((deflate_state * s));
|
||||
int ZLIB_INTERNAL _tr_tally OF((deflate_state * s, unsigned dist, unsigned lc));
|
||||
void ZLIB_INTERNAL _tr_flush_block OF((deflate_state * s, charf * buf, ulg stored_len, int last));
|
||||
void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state * s));
|
||||
void ZLIB_INTERNAL _tr_align OF((deflate_state * s));
|
||||
void ZLIB_INTERNAL _tr_stored_block OF((deflate_state * s, charf * buf, ulg stored_len, int last));
|
||||
|
||||
#define d_code(dist) ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >> 7)])
|
||||
/* Mapping from a distance to a distance code. dist is the distance - 1 and
|
||||
* must not have side effects. _dist_code[256] and _dist_code[257] are never
|
||||
* used.
|
||||
*/
|
||||
|
||||
#ifndef ZLIB_DEBUG
|
||||
/* Inline versions of _tr_tally for speed: */
|
||||
|
||||
# if defined(GEN_TREES_H) || !defined(STDC)
|
||||
extern uch ZLIB_INTERNAL _length_code[];
|
||||
extern uch ZLIB_INTERNAL _dist_code[];
|
||||
# else
|
||||
extern const uch ZLIB_INTERNAL _length_code[];
|
||||
extern const uch ZLIB_INTERNAL _dist_code[];
|
||||
# endif
|
||||
|
||||
# define _tr_tally_lit(s, c, flush) \
|
||||
{ \
|
||||
uch cc = (c); \
|
||||
s->d_buf[s->last_lit] = 0; \
|
||||
s->l_buf[s->last_lit++] = cc; \
|
||||
s->dyn_ltree[cc].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize - 1); \
|
||||
}
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
{ \
|
||||
uch len = (uch)(length); \
|
||||
ush dist = (ush)(distance); \
|
||||
s->d_buf[s->last_lit] = dist; \
|
||||
s->l_buf[s->last_lit++] = len; \
|
||||
dist--; \
|
||||
s->dyn_ltree[_length_code[len] + LITERALS + 1].Freq++; \
|
||||
s->dyn_dtree[d_code(dist)].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize - 1); \
|
||||
}
|
||||
#else
|
||||
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
|
||||
# define _tr_tally_dist(s, distance, length, flush) flush = _tr_tally(s, distance, length)
|
||||
#endif
|
||||
|
||||
#endif /* DEFLATE_H */
|
@ -1,57 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#include "diy-fp.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
void DiyFp::Multiply(const DiyFp& other) {
|
||||
// Simply "emulates" a 128 bit multiplication.
|
||||
// However: the resulting number only contains 64 bits. The least
|
||||
// significant 64 bits are only used for rounding the most significant 64
|
||||
// bits.
|
||||
const uint64_t kM32 = 0xFFFFFFFFU;
|
||||
uint64_t a = f_ >> 32;
|
||||
uint64_t b = f_ & kM32;
|
||||
uint64_t c = other.f_ >> 32;
|
||||
uint64_t d = other.f_ & kM32;
|
||||
uint64_t ac = a * c;
|
||||
uint64_t bc = b * c;
|
||||
uint64_t ad = a * d;
|
||||
uint64_t bd = b * d;
|
||||
uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32);
|
||||
// By adding 1U << 31 to tmp we round the final result.
|
||||
// Halfway cases will be round up.
|
||||
tmp += 1U << 31;
|
||||
uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
|
||||
e_ += other.e_ + 64;
|
||||
f_ = result_f;
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
@ -1,127 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_DIY_FP_H_
|
||||
#define DOUBLE_CONVERSION_DIY_FP_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion
|
||||
{
|
||||
|
||||
// This "Do It Yourself Floating Point" class implements a floating-point number
|
||||
// with a uint64 significand and an int exponent. Normalized DiyFp numbers will
|
||||
// have the most significant bit of the significand set.
|
||||
// Multiplication and Subtraction do not normalize their results.
|
||||
// DiyFp are not designed to contain special doubles (NaN and Infinity).
|
||||
class DiyFp
|
||||
{
|
||||
public:
|
||||
static const int kSignificandSize = 64;
|
||||
|
||||
DiyFp() : f_(0), e_(0) { }
|
||||
DiyFp(uint64_t f, int e) : f_(f), e_(e) { }
|
||||
|
||||
// this = this - other.
|
||||
// The exponents of both numbers must be the same and the significand of this
|
||||
// must be bigger than the significand of other.
|
||||
// The result will not be normalized.
|
||||
void Subtract(const DiyFp & other)
|
||||
{
|
||||
ASSERT(e_ == other.e_);
|
||||
ASSERT(f_ >= other.f_);
|
||||
f_ -= other.f_;
|
||||
}
|
||||
|
||||
// Returns a - b.
|
||||
// The exponents of both numbers must be the same and this must be bigger
|
||||
// than other. The result will not be normalized.
|
||||
static DiyFp Minus(const DiyFp & a, const DiyFp & b)
|
||||
{
|
||||
DiyFp result = a;
|
||||
result.Subtract(b);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// this = this * other.
|
||||
void Multiply(const DiyFp & other);
|
||||
|
||||
// returns a * b;
|
||||
static DiyFp Times(const DiyFp & a, const DiyFp & b)
|
||||
{
|
||||
DiyFp result = a;
|
||||
result.Multiply(b);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Normalize()
|
||||
{
|
||||
ASSERT(f_ != 0);
|
||||
uint64_t f = f_;
|
||||
int e = e_;
|
||||
|
||||
// This method is mainly called for normalizing boundaries. In general
|
||||
// boundaries need to be shifted by 10 bits. We thus optimize for this case.
|
||||
const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000);
|
||||
while ((f & k10MSBits) == 0)
|
||||
{
|
||||
f <<= 10;
|
||||
e -= 10;
|
||||
}
|
||||
while ((f & kUint64MSB) == 0)
|
||||
{
|
||||
f <<= 1;
|
||||
e--;
|
||||
}
|
||||
f_ = f;
|
||||
e_ = e;
|
||||
}
|
||||
|
||||
static DiyFp Normalize(const DiyFp & a)
|
||||
{
|
||||
DiyFp result = a;
|
||||
result.Normalize();
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t f() const { return f_; }
|
||||
int e() const { return e_; }
|
||||
|
||||
void set_f(uint64_t new_value) { f_ = new_value; }
|
||||
void set_e(int new_value) { e_ = new_value; }
|
||||
|
||||
private:
|
||||
static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000);
|
||||
|
||||
uint64_t f_;
|
||||
int e_;
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_DIY_FP_H_
|
@ -1,911 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "double-conversion.h"
|
||||
|
||||
#include "bignum-dtoa.h"
|
||||
#include "fast-dtoa.h"
|
||||
#include "fixed-dtoa.h"
|
||||
#include "ieee.h"
|
||||
#include "strtod.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
|
||||
int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
|
||||
static DoubleToStringConverter converter(flags,
|
||||
"Infinity",
|
||||
"NaN",
|
||||
'e',
|
||||
-6, 21,
|
||||
6, 0);
|
||||
return converter;
|
||||
}
|
||||
|
||||
|
||||
bool DoubleToStringConverter::HandleSpecialValues(
|
||||
double value,
|
||||
StringBuilder* result_builder) const {
|
||||
Double double_inspect(value);
|
||||
if (double_inspect.IsInfinite()) {
|
||||
if (infinity_symbol_ == NULL) return false;
|
||||
if (value < 0) {
|
||||
result_builder->AddCharacter('-');
|
||||
}
|
||||
result_builder->AddString(infinity_symbol_);
|
||||
return true;
|
||||
}
|
||||
if (double_inspect.IsNan()) {
|
||||
if (nan_symbol_ == NULL) return false;
|
||||
result_builder->AddString(nan_symbol_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void DoubleToStringConverter::CreateExponentialRepresentation(
|
||||
const char* decimal_digits,
|
||||
int length,
|
||||
int exponent,
|
||||
StringBuilder* result_builder) const {
|
||||
ASSERT(length != 0);
|
||||
result_builder->AddCharacter(decimal_digits[0]);
|
||||
if (length != 1) {
|
||||
result_builder->AddCharacter('.');
|
||||
result_builder->AddSubstring(&decimal_digits[1], length-1);
|
||||
}
|
||||
result_builder->AddCharacter(exponent_character_);
|
||||
if (exponent < 0) {
|
||||
result_builder->AddCharacter('-');
|
||||
exponent = -exponent;
|
||||
} else {
|
||||
if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
|
||||
result_builder->AddCharacter('+');
|
||||
}
|
||||
}
|
||||
if (exponent == 0) {
|
||||
result_builder->AddCharacter('0');
|
||||
return;
|
||||
}
|
||||
ASSERT(exponent < 1e4);
|
||||
const int kMaxExponentLength = 5;
|
||||
char buffer[kMaxExponentLength + 1];
|
||||
buffer[kMaxExponentLength] = '\0';
|
||||
int first_char_pos = kMaxExponentLength;
|
||||
while (exponent > 0) {
|
||||
buffer[--first_char_pos] = '0' + (exponent % 10);
|
||||
exponent /= 10;
|
||||
}
|
||||
result_builder->AddSubstring(&buffer[first_char_pos],
|
||||
kMaxExponentLength - first_char_pos);
|
||||
}
|
||||
|
||||
|
||||
void DoubleToStringConverter::CreateDecimalRepresentation(
|
||||
const char* decimal_digits,
|
||||
int length,
|
||||
int decimal_point,
|
||||
int digits_after_point,
|
||||
StringBuilder* result_builder) const {
|
||||
// Create a representation that is padded with zeros if needed.
|
||||
if (decimal_point <= 0) {
|
||||
// "0.00000decimal_rep".
|
||||
result_builder->AddCharacter('0');
|
||||
if (digits_after_point > 0) {
|
||||
result_builder->AddCharacter('.');
|
||||
result_builder->AddPadding('0', -decimal_point);
|
||||
ASSERT(length <= digits_after_point - (-decimal_point));
|
||||
result_builder->AddSubstring(decimal_digits, length);
|
||||
int remaining_digits = digits_after_point - (-decimal_point) - length;
|
||||
result_builder->AddPadding('0', remaining_digits);
|
||||
}
|
||||
} else if (decimal_point >= length) {
|
||||
// "decimal_rep0000.00000" or "decimal_rep.0000"
|
||||
result_builder->AddSubstring(decimal_digits, length);
|
||||
result_builder->AddPadding('0', decimal_point - length);
|
||||
if (digits_after_point > 0) {
|
||||
result_builder->AddCharacter('.');
|
||||
result_builder->AddPadding('0', digits_after_point);
|
||||
}
|
||||
} else {
|
||||
// "decima.l_rep000"
|
||||
ASSERT(digits_after_point > 0);
|
||||
result_builder->AddSubstring(decimal_digits, decimal_point);
|
||||
result_builder->AddCharacter('.');
|
||||
ASSERT(length - decimal_point <= digits_after_point);
|
||||
result_builder->AddSubstring(&decimal_digits[decimal_point],
|
||||
length - decimal_point);
|
||||
int remaining_digits = digits_after_point - (length - decimal_point);
|
||||
result_builder->AddPadding('0', remaining_digits);
|
||||
}
|
||||
if (digits_after_point == 0) {
|
||||
if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
|
||||
result_builder->AddCharacter('.');
|
||||
}
|
||||
if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
|
||||
result_builder->AddCharacter('0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DoubleToStringConverter::ToShortestIeeeNumber(
|
||||
double value,
|
||||
StringBuilder* result_builder,
|
||||
DoubleToStringConverter::DtoaMode mode) const {
|
||||
ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);
|
||||
if (Double(value).IsSpecial()) {
|
||||
return HandleSpecialValues(value, result_builder);
|
||||
}
|
||||
|
||||
int decimal_point;
|
||||
bool sign;
|
||||
const int kDecimalRepCapacity = kBase10MaximalLength + 1;
|
||||
char decimal_rep[kDecimalRepCapacity];
|
||||
int decimal_rep_length;
|
||||
|
||||
DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
|
||||
&sign, &decimal_rep_length, &decimal_point);
|
||||
|
||||
bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
|
||||
if (sign && (value != 0.0 || !unique_zero)) {
|
||||
result_builder->AddCharacter('-');
|
||||
}
|
||||
|
||||
int exponent = decimal_point - 1;
|
||||
if ((decimal_in_shortest_low_ <= exponent) &&
|
||||
(exponent < decimal_in_shortest_high_)) {
|
||||
CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
|
||||
decimal_point,
|
||||
Max(0, decimal_rep_length - decimal_point),
|
||||
result_builder);
|
||||
} else {
|
||||
CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
|
||||
result_builder);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DoubleToStringConverter::ToFixed(double value,
|
||||
int requested_digits,
|
||||
StringBuilder* result_builder) const {
|
||||
ASSERT(kMaxFixedDigitsBeforePoint == 60);
|
||||
const double kFirstNonFixed = 1e60;
|
||||
|
||||
if (Double(value).IsSpecial()) {
|
||||
return HandleSpecialValues(value, result_builder);
|
||||
}
|
||||
|
||||
if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
|
||||
if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
|
||||
|
||||
// Find a sufficiently precise decimal representation of n.
|
||||
int decimal_point;
|
||||
bool sign;
|
||||
// Add space for the '\0' byte.
|
||||
const int kDecimalRepCapacity =
|
||||
kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
|
||||
char decimal_rep[kDecimalRepCapacity];
|
||||
int decimal_rep_length;
|
||||
DoubleToAscii(value, FIXED, requested_digits,
|
||||
decimal_rep, kDecimalRepCapacity,
|
||||
&sign, &decimal_rep_length, &decimal_point);
|
||||
|
||||
bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
|
||||
if (sign && (value != 0.0 || !unique_zero)) {
|
||||
result_builder->AddCharacter('-');
|
||||
}
|
||||
|
||||
CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
|
||||
requested_digits, result_builder);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DoubleToStringConverter::ToExponential(
|
||||
double value,
|
||||
int requested_digits,
|
||||
StringBuilder* result_builder) const {
|
||||
if (Double(value).IsSpecial()) {
|
||||
return HandleSpecialValues(value, result_builder);
|
||||
}
|
||||
|
||||
if (requested_digits < -1) return false;
|
||||
if (requested_digits > kMaxExponentialDigits) return false;
|
||||
|
||||
int decimal_point;
|
||||
bool sign;
|
||||
// Add space for digit before the decimal point and the '\0' character.
|
||||
const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
|
||||
ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
|
||||
char decimal_rep[kDecimalRepCapacity];
|
||||
int decimal_rep_length;
|
||||
|
||||
if (requested_digits == -1) {
|
||||
DoubleToAscii(value, SHORTEST, 0,
|
||||
decimal_rep, kDecimalRepCapacity,
|
||||
&sign, &decimal_rep_length, &decimal_point);
|
||||
} else {
|
||||
DoubleToAscii(value, PRECISION, requested_digits + 1,
|
||||
decimal_rep, kDecimalRepCapacity,
|
||||
&sign, &decimal_rep_length, &decimal_point);
|
||||
ASSERT(decimal_rep_length <= requested_digits + 1);
|
||||
|
||||
for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
|
||||
decimal_rep[i] = '0';
|
||||
}
|
||||
decimal_rep_length = requested_digits + 1;
|
||||
}
|
||||
|
||||
bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
|
||||
if (sign && (value != 0.0 || !unique_zero)) {
|
||||
result_builder->AddCharacter('-');
|
||||
}
|
||||
|
||||
int exponent = decimal_point - 1;
|
||||
CreateExponentialRepresentation(decimal_rep,
|
||||
decimal_rep_length,
|
||||
exponent,
|
||||
result_builder);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DoubleToStringConverter::ToPrecision(double value,
|
||||
int precision,
|
||||
StringBuilder* result_builder) const {
|
||||
if (Double(value).IsSpecial()) {
|
||||
return HandleSpecialValues(value, result_builder);
|
||||
}
|
||||
|
||||
if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find a sufficiently precise decimal representation of n.
|
||||
int decimal_point;
|
||||
bool sign;
|
||||
// Add one for the terminating null character.
|
||||
const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
|
||||
char decimal_rep[kDecimalRepCapacity];
|
||||
int decimal_rep_length;
|
||||
|
||||
DoubleToAscii(value, PRECISION, precision,
|
||||
decimal_rep, kDecimalRepCapacity,
|
||||
&sign, &decimal_rep_length, &decimal_point);
|
||||
ASSERT(decimal_rep_length <= precision);
|
||||
|
||||
bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
|
||||
if (sign && (value != 0.0 || !unique_zero)) {
|
||||
result_builder->AddCharacter('-');
|
||||
}
|
||||
|
||||
// The exponent if we print the number as x.xxeyyy. That is with the
|
||||
// decimal point after the first digit.
|
||||
int exponent = decimal_point - 1;
|
||||
|
||||
int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
|
||||
if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
|
||||
(decimal_point - precision + extra_zero >
|
||||
max_trailing_padding_zeroes_in_precision_mode_)) {
|
||||
// Fill buffer to contain 'precision' digits.
|
||||
// Usually the buffer is already at the correct length, but 'DoubleToAscii'
|
||||
// is allowed to return less characters.
|
||||
for (int i = decimal_rep_length; i < precision; ++i) {
|
||||
decimal_rep[i] = '0';
|
||||
}
|
||||
|
||||
CreateExponentialRepresentation(decimal_rep,
|
||||
precision,
|
||||
exponent,
|
||||
result_builder);
|
||||
} else {
|
||||
CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
|
||||
Max(0, precision - decimal_point),
|
||||
result_builder);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static BignumDtoaMode DtoaToBignumDtoaMode(
|
||||
DoubleToStringConverter::DtoaMode dtoa_mode) {
|
||||
switch (dtoa_mode) {
|
||||
case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST;
|
||||
case DoubleToStringConverter::SHORTEST_SINGLE:
|
||||
return BIGNUM_DTOA_SHORTEST_SINGLE;
|
||||
case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
|
||||
case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return BIGNUM_DTOA_SHORTEST;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DoubleToStringConverter::DoubleToAscii(double v,
|
||||
DtoaMode mode,
|
||||
int requested_digits,
|
||||
char* buffer,
|
||||
int buffer_length,
|
||||
bool* sign,
|
||||
int* length,
|
||||
int* point) {
|
||||
Vector<char> vector(buffer, buffer_length);
|
||||
ASSERT(!Double(v).IsSpecial());
|
||||
ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);
|
||||
|
||||
if (Double(v).Sign() < 0) {
|
||||
*sign = true;
|
||||
v = -v;
|
||||
} else {
|
||||
*sign = false;
|
||||
}
|
||||
|
||||
if (mode == PRECISION && requested_digits == 0) {
|
||||
vector[0] = '\0';
|
||||
*length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (v == 0) {
|
||||
vector[0] = '0';
|
||||
vector[1] = '\0';
|
||||
*length = 1;
|
||||
*point = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
bool fast_worked;
|
||||
switch (mode) {
|
||||
case SHORTEST:
|
||||
fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
|
||||
break;
|
||||
case SHORTEST_SINGLE:
|
||||
fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
|
||||
vector, length, point);
|
||||
break;
|
||||
case FIXED:
|
||||
fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
|
||||
break;
|
||||
case PRECISION:
|
||||
fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
|
||||
vector, length, point);
|
||||
break;
|
||||
default:
|
||||
fast_worked = false;
|
||||
UNREACHABLE();
|
||||
}
|
||||
if (fast_worked) return;
|
||||
|
||||
// If the fast dtoa didn't succeed use the slower bignum version.
|
||||
BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
|
||||
BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
|
||||
vector[*length] = '\0';
|
||||
}
|
||||
|
||||
|
||||
// Consumes the given substring from the iterator.
|
||||
// Returns false, if the substring does not match.
|
||||
static bool ConsumeSubString(const char** current,
|
||||
const char* end,
|
||||
const char* substring) {
|
||||
ASSERT(**current == *substring);
|
||||
for (substring++; *substring != '\0'; substring++) {
|
||||
++*current;
|
||||
if (*current == end || **current != *substring) return false;
|
||||
}
|
||||
++*current;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Maximum number of significant digits in decimal representation.
|
||||
// The longest possible double in decimal representation is
|
||||
// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
|
||||
// (768 digits). If we parse a number whose first digits are equal to a
|
||||
// mean of 2 adjacent doubles (that could have up to 769 digits) the result
|
||||
// must be rounded to the bigger one unless the tail consists of zeros, so
|
||||
// we don't need to preserve all the digits.
|
||||
const int kMaxSignificantDigits = 772;
|
||||
|
||||
|
||||
// Returns true if a nonspace found and false if the end has reached.
|
||||
static inline bool AdvanceToNonspace(const char** current, const char* end) {
|
||||
while (*current != end) {
|
||||
if (**current != ' ') return true;
|
||||
++*current;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool isDigit(int x, int radix) {
|
||||
return (x >= '0' && x <= '9' && x < '0' + radix)
|
||||
|| (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
|
||||
|| (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
|
||||
}
|
||||
|
||||
|
||||
static double SignedZero(bool sign) {
|
||||
return sign ? -0.0 : 0.0;
|
||||
}
|
||||
|
||||
|
||||
// Returns true if 'c' is a decimal digit that is valid for the given radix.
|
||||
//
|
||||
// The function is small and could be inlined, but VS2012 emitted a warning
|
||||
// because it constant-propagated the radix and concluded that the last
|
||||
// condition was always true. By moving it into a separate function the
|
||||
// compiler wouldn't warn anymore.
|
||||
static bool IsDecimalDigitForRadix(int c, int radix) {
|
||||
return '0' <= c && c <= '9' && (c - '0') < radix;
|
||||
}
|
||||
|
||||
// Returns true if 'c' is a character digit that is valid for the given radix.
|
||||
// The 'a_character' should be 'a' or 'A'.
|
||||
//
|
||||
// The function is small and could be inlined, but VS2012 emitted a warning
|
||||
// because it constant-propagated the radix and concluded that the first
|
||||
// condition was always false. By moving it into a separate function the
|
||||
// compiler wouldn't warn anymore.
|
||||
static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
|
||||
return radix > 10 && c >= a_character && c < a_character + radix - 10;
|
||||
}
|
||||
|
||||
|
||||
// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
|
||||
template <int radix_log_2>
|
||||
static double RadixStringToIeee(const char* current,
|
||||
const char* end,
|
||||
bool sign,
|
||||
bool allow_trailing_junk,
|
||||
double junk_string_value,
|
||||
bool read_as_double,
|
||||
const char** trailing_pointer) {
|
||||
ASSERT(current != end);
|
||||
|
||||
const int kDoubleSize = Double::kSignificandSize;
|
||||
const int kSingleSize = Single::kSignificandSize;
|
||||
const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
|
||||
|
||||
// Skip leading 0s.
|
||||
while (*current == '0') {
|
||||
++current;
|
||||
if (current == end) {
|
||||
*trailing_pointer = end;
|
||||
return SignedZero(sign);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t number = 0;
|
||||
int exponent = 0;
|
||||
const int radix = (1 << radix_log_2);
|
||||
|
||||
do {
|
||||
int digit;
|
||||
if (IsDecimalDigitForRadix(*current, radix)) {
|
||||
digit = static_cast<char>(*current) - '0';
|
||||
} else if (IsCharacterDigitForRadix(*current, radix, 'a')) {
|
||||
digit = static_cast<char>(*current) - 'a' + 10;
|
||||
} else if (IsCharacterDigitForRadix(*current, radix, 'A')) {
|
||||
digit = static_cast<char>(*current) - 'A' + 10;
|
||||
} else {
|
||||
if (allow_trailing_junk || !AdvanceToNonspace(¤t, end)) {
|
||||
break;
|
||||
} else {
|
||||
return junk_string_value;
|
||||
}
|
||||
}
|
||||
|
||||
number = number * radix + digit;
|
||||
int overflow = static_cast<int>(number >> kSignificandSize);
|
||||
if (overflow != 0) {
|
||||
// Overflow occurred. Need to determine which direction to round the
|
||||
// result.
|
||||
int overflow_bits_count = 1;
|
||||
while (overflow > 1) {
|
||||
overflow_bits_count++;
|
||||
overflow >>= 1;
|
||||
}
|
||||
|
||||
int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
|
||||
int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
|
||||
number >>= overflow_bits_count;
|
||||
exponent = overflow_bits_count;
|
||||
|
||||
bool zero_tail = true;
|
||||
for (;;) {
|
||||
++current;
|
||||
if (current == end || !isDigit(*current, radix)) break;
|
||||
zero_tail = zero_tail && *current == '0';
|
||||
exponent += radix_log_2;
|
||||
}
|
||||
|
||||
if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
|
||||
return junk_string_value;
|
||||
}
|
||||
|
||||
int middle_value = (1 << (overflow_bits_count - 1));
|
||||
if (dropped_bits > middle_value) {
|
||||
number++; // Rounding up.
|
||||
} else if (dropped_bits == middle_value) {
|
||||
// Rounding to even to consistency with decimals: half-way case rounds
|
||||
// up if significant part is odd and down otherwise.
|
||||
if ((number & 1) != 0 || !zero_tail) {
|
||||
number++; // Rounding up.
|
||||
}
|
||||
}
|
||||
|
||||
// Rounding up may cause overflow.
|
||||
if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
|
||||
exponent++;
|
||||
number >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
++current;
|
||||
} while (current != end);
|
||||
|
||||
ASSERT(number < ((int64_t)1 << kSignificandSize));
|
||||
ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
|
||||
|
||||
*trailing_pointer = current;
|
||||
|
||||
if (exponent == 0) {
|
||||
if (sign) {
|
||||
if (number == 0) return -0.0;
|
||||
number = -number;
|
||||
}
|
||||
return static_cast<double>(number);
|
||||
}
|
||||
|
||||
ASSERT(number != 0);
|
||||
return Double(DiyFp(number, exponent)).value();
|
||||
}
|
||||
|
||||
|
||||
double StringToDoubleConverter::StringToIeee(
|
||||
const char* input,
|
||||
int length,
|
||||
int* processed_characters_count,
|
||||
bool read_as_double) const {
|
||||
const char* current = input;
|
||||
const char* end = input + length;
|
||||
|
||||
*processed_characters_count = 0;
|
||||
|
||||
const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;
|
||||
const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
|
||||
const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
|
||||
const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
|
||||
|
||||
// To make sure that iterator dereferencing is valid the following
|
||||
// convention is used:
|
||||
// 1. Each '++current' statement is followed by check for equality to 'end'.
|
||||
// 2. If AdvanceToNonspace returned false then current == end.
|
||||
// 3. If 'current' becomes equal to 'end' the function returns or goes to
|
||||
// 'parsing_done'.
|
||||
// 4. 'current' is not dereferenced after the 'parsing_done' label.
|
||||
// 5. Code before 'parsing_done' may rely on 'current != end'.
|
||||
if (current == end) return empty_string_value_;
|
||||
|
||||
if (allow_leading_spaces || allow_trailing_spaces) {
|
||||
if (!AdvanceToNonspace(¤t, end)) {
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return empty_string_value_;
|
||||
}
|
||||
if (!allow_leading_spaces && (input != current)) {
|
||||
// No leading spaces allowed, but AdvanceToNonspace moved forward.
|
||||
return junk_string_value_;
|
||||
}
|
||||
}
|
||||
|
||||
// The longest form of simplified number is: "-<significant digits>.1eXXX\0".
|
||||
const int kBufferSize = kMaxSignificantDigits + 10;
|
||||
char buffer[kBufferSize]; // NOLINT: size is known at compile time.
|
||||
int buffer_pos = 0;
|
||||
|
||||
// Exponent will be adjusted if insignificant digits of the integer part
|
||||
// or insignificant leading zeros of the fractional part are dropped.
|
||||
int exponent = 0;
|
||||
int significant_digits = 0;
|
||||
int insignificant_digits = 0;
|
||||
bool nonzero_digit_dropped = false;
|
||||
|
||||
bool sign = false;
|
||||
|
||||
if (*current == '+' || *current == '-') {
|
||||
sign = (*current == '-');
|
||||
++current;
|
||||
const char* next_non_space = current;
|
||||
// Skip following spaces (if allowed).
|
||||
if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
|
||||
if (!allow_spaces_after_sign && (current != next_non_space)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
current = next_non_space;
|
||||
}
|
||||
|
||||
if (infinity_symbol_ != NULL) {
|
||||
if (*current == infinity_symbol_[0]) {
|
||||
if (!ConsumeSubString(¤t, end, infinity_symbol_)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
|
||||
if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
|
||||
ASSERT(buffer_pos == 0);
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return sign ? -Double::Infinity() : Double::Infinity();
|
||||
}
|
||||
}
|
||||
|
||||
if (nan_symbol_ != NULL) {
|
||||
if (*current == nan_symbol_[0]) {
|
||||
if (!ConsumeSubString(¤t, end, nan_symbol_)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
|
||||
if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
|
||||
ASSERT(buffer_pos == 0);
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return sign ? -Double::NaN() : Double::NaN();
|
||||
}
|
||||
}
|
||||
|
||||
bool leading_zero = false;
|
||||
if (*current == '0') {
|
||||
++current;
|
||||
if (current == end) {
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return SignedZero(sign);
|
||||
}
|
||||
|
||||
leading_zero = true;
|
||||
|
||||
// It could be hexadecimal value.
|
||||
if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
|
||||
++current;
|
||||
if (current == end || !isDigit(*current, 16)) {
|
||||
return junk_string_value_; // "0x".
|
||||
}
|
||||
|
||||
const char* tail_pointer = NULL;
|
||||
double result = RadixStringToIeee<4>(current,
|
||||
end,
|
||||
sign,
|
||||
allow_trailing_junk,
|
||||
junk_string_value_,
|
||||
read_as_double,
|
||||
&tail_pointer);
|
||||
if (tail_pointer != NULL) {
|
||||
if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end);
|
||||
*processed_characters_count = static_cast<int>(tail_pointer - input);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Ignore leading zeros in the integer part.
|
||||
while (*current == '0') {
|
||||
++current;
|
||||
if (current == end) {
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return SignedZero(sign);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;
|
||||
|
||||
// Copy significant digits of the integer part (if any) to the buffer.
|
||||
while (*current >= '0' && *current <= '9') {
|
||||
if (significant_digits < kMaxSignificantDigits) {
|
||||
ASSERT(buffer_pos < kBufferSize);
|
||||
buffer[buffer_pos++] = static_cast<char>(*current);
|
||||
significant_digits++;
|
||||
// Will later check if it's an octal in the buffer.
|
||||
} else {
|
||||
insignificant_digits++; // Move the digit into the exponential part.
|
||||
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
|
||||
}
|
||||
octal = octal && *current < '8';
|
||||
++current;
|
||||
if (current == end) goto parsing_done;
|
||||
}
|
||||
|
||||
if (significant_digits == 0) {
|
||||
octal = false;
|
||||
}
|
||||
|
||||
if (*current == '.') {
|
||||
if (octal && !allow_trailing_junk) return junk_string_value_;
|
||||
if (octal) goto parsing_done;
|
||||
|
||||
++current;
|
||||
if (current == end) {
|
||||
if (significant_digits == 0 && !leading_zero) {
|
||||
return junk_string_value_;
|
||||
} else {
|
||||
goto parsing_done;
|
||||
}
|
||||
}
|
||||
|
||||
if (significant_digits == 0) {
|
||||
// octal = false;
|
||||
// Integer part consists of 0 or is absent. Significant digits start after
|
||||
// leading zeros (if any).
|
||||
while (*current == '0') {
|
||||
++current;
|
||||
if (current == end) {
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return SignedZero(sign);
|
||||
}
|
||||
exponent--; // Move this 0 into the exponent.
|
||||
}
|
||||
}
|
||||
|
||||
// There is a fractional part.
|
||||
// We don't emit a '.', but adjust the exponent instead.
|
||||
while (*current >= '0' && *current <= '9') {
|
||||
if (significant_digits < kMaxSignificantDigits) {
|
||||
ASSERT(buffer_pos < kBufferSize);
|
||||
buffer[buffer_pos++] = static_cast<char>(*current);
|
||||
significant_digits++;
|
||||
exponent--;
|
||||
} else {
|
||||
// Ignore insignificant digits in the fractional part.
|
||||
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
|
||||
}
|
||||
++current;
|
||||
if (current == end) goto parsing_done;
|
||||
}
|
||||
}
|
||||
|
||||
if (!leading_zero && exponent == 0 && significant_digits == 0) {
|
||||
// If leading_zeros is true then the string contains zeros.
|
||||
// If exponent < 0 then string was [+-]\.0*...
|
||||
// If significant_digits != 0 the string is not equal to 0.
|
||||
// Otherwise there are no digits in the string.
|
||||
return junk_string_value_;
|
||||
}
|
||||
|
||||
// Parse exponential part.
|
||||
if (*current == 'e' || *current == 'E') {
|
||||
if (octal && !allow_trailing_junk) return junk_string_value_;
|
||||
if (octal) goto parsing_done;
|
||||
++current;
|
||||
if (current == end) {
|
||||
if (allow_trailing_junk) {
|
||||
goto parsing_done;
|
||||
} else {
|
||||
return junk_string_value_;
|
||||
}
|
||||
}
|
||||
char sign = '+';
|
||||
if (*current == '+' || *current == '-') {
|
||||
sign = static_cast<char>(*current);
|
||||
++current;
|
||||
if (current == end) {
|
||||
if (allow_trailing_junk) {
|
||||
goto parsing_done;
|
||||
} else {
|
||||
return junk_string_value_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current == end || *current < '0' || *current > '9') {
|
||||
if (allow_trailing_junk) {
|
||||
goto parsing_done;
|
||||
} else {
|
||||
return junk_string_value_;
|
||||
}
|
||||
}
|
||||
|
||||
const int max_exponent = INT_MAX / 2;
|
||||
ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
|
||||
int num = 0;
|
||||
do {
|
||||
// Check overflow.
|
||||
int digit = *current - '0';
|
||||
if (num >= max_exponent / 10
|
||||
&& !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
|
||||
num = max_exponent;
|
||||
} else {
|
||||
num = num * 10 + digit;
|
||||
}
|
||||
++current;
|
||||
} while (current != end && *current >= '0' && *current <= '9');
|
||||
|
||||
exponent += (sign == '-' ? -num : num);
|
||||
}
|
||||
|
||||
if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) {
|
||||
return junk_string_value_;
|
||||
}
|
||||
if (allow_trailing_spaces) {
|
||||
AdvanceToNonspace(¤t, end);
|
||||
}
|
||||
|
||||
parsing_done:
|
||||
exponent += insignificant_digits;
|
||||
|
||||
if (octal) {
|
||||
double result;
|
||||
const char* tail_pointer = NULL;
|
||||
result = RadixStringToIeee<3>(buffer,
|
||||
buffer + buffer_pos,
|
||||
sign,
|
||||
allow_trailing_junk,
|
||||
junk_string_value_,
|
||||
read_as_double,
|
||||
&tail_pointer);
|
||||
ASSERT(tail_pointer != NULL);
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (nonzero_digit_dropped) {
|
||||
buffer[buffer_pos++] = '1';
|
||||
exponent--;
|
||||
}
|
||||
|
||||
ASSERT(buffer_pos < kBufferSize);
|
||||
buffer[buffer_pos] = '\0';
|
||||
|
||||
double converted;
|
||||
if (read_as_double) {
|
||||
converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
|
||||
} else {
|
||||
converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
|
||||
}
|
||||
*processed_characters_count = static_cast<int>(current - input);
|
||||
return sign? -converted: converted;
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
@ -1,512 +0,0 @@
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
|
||||
#define DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion
|
||||
{
|
||||
|
||||
class DoubleToStringConverter
|
||||
{
|
||||
public:
|
||||
// When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint
|
||||
// or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the
|
||||
// function returns false.
|
||||
static const int kMaxFixedDigitsBeforePoint = 60;
|
||||
static const int kMaxFixedDigitsAfterPoint = 60;
|
||||
|
||||
// When calling ToExponential with a requested_digits
|
||||
// parameter > kMaxExponentialDigits then the function returns false.
|
||||
static const int kMaxExponentialDigits = 120;
|
||||
|
||||
// When calling ToPrecision with a requested_digits
|
||||
// parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits
|
||||
// then the function returns false.
|
||||
static const int kMinPrecisionDigits = 1;
|
||||
static const int kMaxPrecisionDigits = 120;
|
||||
|
||||
enum Flags
|
||||
{
|
||||
NO_FLAGS = 0,
|
||||
EMIT_POSITIVE_EXPONENT_SIGN = 1,
|
||||
EMIT_TRAILING_DECIMAL_POINT = 2,
|
||||
EMIT_TRAILING_ZERO_AFTER_POINT = 4,
|
||||
UNIQUE_ZERO = 8
|
||||
};
|
||||
|
||||
// Flags should be a bit-or combination of the possible Flags-enum.
|
||||
// - NO_FLAGS: no special flags.
|
||||
// - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent
|
||||
// form, emits a '+' for positive exponents. Example: 1.2e+2.
|
||||
// - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is
|
||||
// converted into decimal format then a trailing decimal point is appended.
|
||||
// Example: 2345.0 is converted to "2345.".
|
||||
// - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point
|
||||
// emits a trailing '0'-character. This flag requires the
|
||||
// EXMIT_TRAILING_DECIMAL_POINT flag.
|
||||
// Example: 2345.0 is converted to "2345.0".
|
||||
// - UNIQUE_ZERO: "-0.0" is converted to "0.0".
|
||||
//
|
||||
// Infinity symbol and nan_symbol provide the string representation for these
|
||||
// special values. If the string is NULL and the special value is encountered
|
||||
// then the conversion functions return false.
|
||||
//
|
||||
// The exponent_character is used in exponential representations. It is
|
||||
// usually 'e' or 'E'.
|
||||
//
|
||||
// When converting to the shortest representation the converter will
|
||||
// represent input numbers in decimal format if they are in the interval
|
||||
// [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[
|
||||
// (lower boundary included, greater boundary excluded).
|
||||
// Example: with decimal_in_shortest_low = -6 and
|
||||
// decimal_in_shortest_high = 21:
|
||||
// ToShortest(0.000001) -> "0.000001"
|
||||
// ToShortest(0.0000001) -> "1e-7"
|
||||
// ToShortest(111111111111111111111.0) -> "111111111111111110000"
|
||||
// ToShortest(100000000000000000000.0) -> "100000000000000000000"
|
||||
// ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
|
||||
//
|
||||
// When converting to precision mode the converter may add
|
||||
// max_leading_padding_zeroes before returning the number in exponential
|
||||
// format.
|
||||
// Example with max_leading_padding_zeroes_in_precision_mode = 6.
|
||||
// ToPrecision(0.0000012345, 2) -> "0.0000012"
|
||||
// ToPrecision(0.00000012345, 2) -> "1.2e-7"
|
||||
// Similarly the converter may add up to
|
||||
// max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
|
||||
// returning an exponential representation. A zero added by the
|
||||
// EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
|
||||
// Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
|
||||
// ToPrecision(230.0, 2) -> "230"
|
||||
// ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
|
||||
// ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
|
||||
DoubleToStringConverter(
|
||||
int flags,
|
||||
const char * infinity_symbol,
|
||||
const char * nan_symbol,
|
||||
char exponent_character,
|
||||
int decimal_in_shortest_low,
|
||||
int decimal_in_shortest_high,
|
||||
int max_leading_padding_zeroes_in_precision_mode,
|
||||
int max_trailing_padding_zeroes_in_precision_mode)
|
||||
: flags_(flags)
|
||||
, infinity_symbol_(infinity_symbol)
|
||||
, nan_symbol_(nan_symbol)
|
||||
, exponent_character_(exponent_character)
|
||||
, decimal_in_shortest_low_(decimal_in_shortest_low)
|
||||
, decimal_in_shortest_high_(decimal_in_shortest_high)
|
||||
, max_leading_padding_zeroes_in_precision_mode_(max_leading_padding_zeroes_in_precision_mode)
|
||||
, max_trailing_padding_zeroes_in_precision_mode_(max_trailing_padding_zeroes_in_precision_mode)
|
||||
{
|
||||
// When 'trailing zero after the point' is set, then 'trailing point'
|
||||
// must be set too.
|
||||
ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) || !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0));
|
||||
}
|
||||
|
||||
// Returns a converter following the EcmaScript specification.
|
||||
static const DoubleToStringConverter & EcmaScriptConverter();
|
||||
|
||||
// Computes the shortest string of digits that correctly represent the input
|
||||
// number. Depending on decimal_in_shortest_low and decimal_in_shortest_high
|
||||
// (see constructor) it then either returns a decimal representation, or an
|
||||
// exponential representation.
|
||||
// Example with decimal_in_shortest_low = -6,
|
||||
// decimal_in_shortest_high = 21,
|
||||
// EMIT_POSITIVE_EXPONENT_SIGN activated, and
|
||||
// EMIT_TRAILING_DECIMAL_POINT deactivated:
|
||||
// ToShortest(0.000001) -> "0.000001"
|
||||
// ToShortest(0.0000001) -> "1e-7"
|
||||
// ToShortest(111111111111111111111.0) -> "111111111111111110000"
|
||||
// ToShortest(100000000000000000000.0) -> "100000000000000000000"
|
||||
// ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
|
||||
//
|
||||
// Note: the conversion may round the output if the returned string
|
||||
// is accurate enough to uniquely identify the input-number.
|
||||
// For example the most precise representation of the double 9e59 equals
|
||||
// "899999999999999918767229449717619953810131273674690656206848", but
|
||||
// the converter will return the shorter (but still correct) "9e59".
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except when the input value is special and no infinity_symbol or
|
||||
// nan_symbol has been given to the constructor.
|
||||
bool ToShortest(double value, StringBuilder * result_builder) const { return ToShortestIeeeNumber(value, result_builder, SHORTEST); }
|
||||
|
||||
// Same as ToShortest, but for single-precision floats.
|
||||
bool ToShortestSingle(float value, StringBuilder * result_builder) const
|
||||
{
|
||||
return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE);
|
||||
}
|
||||
|
||||
|
||||
// Computes a decimal representation with a fixed number of digits after the
|
||||
// decimal point. The last emitted digit is rounded.
|
||||
//
|
||||
// Examples:
|
||||
// ToFixed(3.12, 1) -> "3.1"
|
||||
// ToFixed(3.1415, 3) -> "3.142"
|
||||
// ToFixed(1234.56789, 4) -> "1234.5679"
|
||||
// ToFixed(1.23, 5) -> "1.23000"
|
||||
// ToFixed(0.1, 4) -> "0.1000"
|
||||
// ToFixed(1e30, 2) -> "1000000000000000019884624838656.00"
|
||||
// ToFixed(0.1, 30) -> "0.100000000000000005551115123126"
|
||||
// ToFixed(0.1, 17) -> "0.10000000000000001"
|
||||
//
|
||||
// If requested_digits equals 0, then the tail of the result depends on
|
||||
// the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT.
|
||||
// Examples, for requested_digits == 0,
|
||||
// let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be
|
||||
// - false and false: then 123.45 -> 123
|
||||
// 0.678 -> 1
|
||||
// - true and false: then 123.45 -> 123.
|
||||
// 0.678 -> 1.
|
||||
// - true and true: then 123.45 -> 123.0
|
||||
// 0.678 -> 1.0
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except for the following cases:
|
||||
// - the input value is special and no infinity_symbol or nan_symbol has
|
||||
// been provided to the constructor,
|
||||
// - 'value' > 10^kMaxFixedDigitsBeforePoint, or
|
||||
// - 'requested_digits' > kMaxFixedDigitsAfterPoint.
|
||||
// The last two conditions imply that the result will never contain more than
|
||||
// 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
|
||||
// (one additional character for the sign, and one for the decimal point).
|
||||
bool ToFixed(double value, int requested_digits, StringBuilder * result_builder) const;
|
||||
|
||||
// Computes a representation in exponential format with requested_digits
|
||||
// after the decimal point. The last emitted digit is rounded.
|
||||
// If requested_digits equals -1, then the shortest exponential representation
|
||||
// is computed.
|
||||
//
|
||||
// Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and
|
||||
// exponent_character set to 'e'.
|
||||
// ToExponential(3.12, 1) -> "3.1e0"
|
||||
// ToExponential(5.0, 3) -> "5.000e0"
|
||||
// ToExponential(0.001, 2) -> "1.00e-3"
|
||||
// ToExponential(3.1415, -1) -> "3.1415e0"
|
||||
// ToExponential(3.1415, 4) -> "3.1415e0"
|
||||
// ToExponential(3.1415, 3) -> "3.142e0"
|
||||
// ToExponential(123456789000000, 3) -> "1.235e14"
|
||||
// ToExponential(1000000000000000019884624838656.0, -1) -> "1e30"
|
||||
// ToExponential(1000000000000000019884624838656.0, 32) ->
|
||||
// "1.00000000000000001988462483865600e30"
|
||||
// ToExponential(1234, 0) -> "1e3"
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except for the following cases:
|
||||
// - the input value is special and no infinity_symbol or nan_symbol has
|
||||
// been provided to the constructor,
|
||||
// - 'requested_digits' > kMaxExponentialDigits.
|
||||
// The last condition implies that the result will never contain more than
|
||||
// kMaxExponentialDigits + 8 characters (the sign, the digit before the
|
||||
// decimal point, the decimal point, the exponent character, the
|
||||
// exponent's sign, and at most 3 exponent digits).
|
||||
bool ToExponential(double value, int requested_digits, StringBuilder * result_builder) const;
|
||||
|
||||
// Computes 'precision' leading digits of the given 'value' and returns them
|
||||
// either in exponential or decimal format, depending on
|
||||
// max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the
|
||||
// constructor).
|
||||
// The last computed digit is rounded.
|
||||
//
|
||||
// Example with max_leading_padding_zeroes_in_precision_mode = 6.
|
||||
// ToPrecision(0.0000012345, 2) -> "0.0000012"
|
||||
// ToPrecision(0.00000012345, 2) -> "1.2e-7"
|
||||
// Similarly the converter may add up to
|
||||
// max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
|
||||
// returning an exponential representation. A zero added by the
|
||||
// EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
|
||||
// Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
|
||||
// ToPrecision(230.0, 2) -> "230"
|
||||
// ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
|
||||
// ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
|
||||
// Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no
|
||||
// EMIT_TRAILING_ZERO_AFTER_POINT:
|
||||
// ToPrecision(123450.0, 6) -> "123450"
|
||||
// ToPrecision(123450.0, 5) -> "123450"
|
||||
// ToPrecision(123450.0, 4) -> "123500"
|
||||
// ToPrecision(123450.0, 3) -> "123000"
|
||||
// ToPrecision(123450.0, 2) -> "1.2e5"
|
||||
//
|
||||
// Returns true if the conversion succeeds. The conversion always succeeds
|
||||
// except for the following cases:
|
||||
// - the input value is special and no infinity_symbol or nan_symbol has
|
||||
// been provided to the constructor,
|
||||
// - precision < kMinPericisionDigits
|
||||
// - precision > kMaxPrecisionDigits
|
||||
// The last condition implies that the result will never contain more than
|
||||
// kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the
|
||||
// exponent character, the exponent's sign, and at most 3 exponent digits).
|
||||
bool ToPrecision(double value, int precision, StringBuilder * result_builder) const;
|
||||
|
||||
enum DtoaMode
|
||||
{
|
||||
// Produce the shortest correct representation.
|
||||
// For example the output of 0.299999999999999988897 is (the less accurate
|
||||
// but correct) 0.3.
|
||||
SHORTEST,
|
||||
// Same as SHORTEST, but for single-precision floats.
|
||||
SHORTEST_SINGLE,
|
||||
// Produce a fixed number of digits after the decimal point.
|
||||
// For instance fixed(0.1, 4) becomes 0.1000
|
||||
// If the input number is big, the output will be big.
|
||||
FIXED,
|
||||
// Fixed number of digits (independent of the decimal point).
|
||||
PRECISION
|
||||
};
|
||||
|
||||
// The maximal number of digits that are needed to emit a double in base 10.
|
||||
// A higher precision can be achieved by using more digits, but the shortest
|
||||
// accurate representation of any double will never use more digits than
|
||||
// kBase10MaximalLength.
|
||||
// Note that DoubleToAscii null-terminates its input. So the given buffer
|
||||
// should be at least kBase10MaximalLength + 1 characters long.
|
||||
static const int kBase10MaximalLength = 17;
|
||||
|
||||
// Converts the given double 'v' to ascii. 'v' must not be NaN, +Infinity, or
|
||||
// -Infinity. In SHORTEST_SINGLE-mode this restriction also applies to 'v'
|
||||
// after it has been casted to a single-precision float. That is, in this
|
||||
// mode static_cast<float>(v) must not be NaN, +Infinity or -Infinity.
|
||||
//
|
||||
// The result should be interpreted as buffer * 10^(point-length).
|
||||
//
|
||||
// The output depends on the given mode:
|
||||
// - SHORTEST: produce the least amount of digits for which the internal
|
||||
// identity requirement is still satisfied. If the digits are printed
|
||||
// (together with the correct exponent) then reading this number will give
|
||||
// 'v' again. The buffer will choose the representation that is closest to
|
||||
// 'v'. If there are two at the same distance, than the one farther away
|
||||
// from 0 is chosen (halfway cases - ending with 5 - are rounded up).
|
||||
// In this mode the 'requested_digits' parameter is ignored.
|
||||
// - SHORTEST_SINGLE: same as SHORTEST but with single-precision.
|
||||
// - FIXED: produces digits necessary to print a given number with
|
||||
// 'requested_digits' digits after the decimal point. The produced digits
|
||||
// might be too short in which case the caller has to fill the remainder
|
||||
// with '0's.
|
||||
// Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
|
||||
// Halfway cases are rounded towards +/-Infinity (away from 0). The call
|
||||
// toFixed(0.15, 2) thus returns buffer="2", point=0.
|
||||
// The returned buffer may contain digits that would be truncated from the
|
||||
// shortest representation of the input.
|
||||
// - PRECISION: produces 'requested_digits' where the first digit is not '0'.
|
||||
// Even though the length of produced digits usually equals
|
||||
// 'requested_digits', the function is allowed to return fewer digits, in
|
||||
// which case the caller has to fill the missing digits with '0's.
|
||||
// Halfway cases are again rounded away from 0.
|
||||
// DoubleToAscii expects the given buffer to be big enough to hold all
|
||||
// digits and a terminating null-character. In SHORTEST-mode it expects a
|
||||
// buffer of at least kBase10MaximalLength + 1. In all other modes the
|
||||
// requested_digits parameter and the padding-zeroes limit the size of the
|
||||
// output. Don't forget the decimal point, the exponent character and the
|
||||
// terminating null-character when computing the maximal output size.
|
||||
// The given length is only used in debug mode to ensure the buffer is big
|
||||
// enough.
|
||||
static void
|
||||
DoubleToAscii(double v, DtoaMode mode, int requested_digits, char * buffer, int buffer_length, bool * sign, int * length, int * point);
|
||||
|
||||
private:
|
||||
// Implementation for ToShortest and ToShortestSingle.
|
||||
bool ToShortestIeeeNumber(double value, StringBuilder * result_builder, DtoaMode mode) const;
|
||||
|
||||
// If the value is a special value (NaN or Infinity) constructs the
|
||||
// corresponding string using the configured infinity/nan-symbol.
|
||||
// If either of them is NULL or the value is not special then the
|
||||
// function returns false.
|
||||
bool HandleSpecialValues(double value, StringBuilder * result_builder) const;
|
||||
// Constructs an exponential representation (i.e. 1.234e56).
|
||||
// The given exponent assumes a decimal point after the first decimal digit.
|
||||
void CreateExponentialRepresentation(const char * decimal_digits, int length, int exponent, StringBuilder * result_builder) const;
|
||||
// Creates a decimal representation (i.e 1234.5678).
|
||||
void CreateDecimalRepresentation(
|
||||
const char * decimal_digits, int length, int decimal_point, int digits_after_point, StringBuilder * result_builder) const;
|
||||
|
||||
const int flags_;
|
||||
const char * const infinity_symbol_;
|
||||
const char * const nan_symbol_;
|
||||
const char exponent_character_;
|
||||
const int decimal_in_shortest_low_;
|
||||
const int decimal_in_shortest_high_;
|
||||
const int max_leading_padding_zeroes_in_precision_mode_;
|
||||
const int max_trailing_padding_zeroes_in_precision_mode_;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
|
||||
};
|
||||
|
||||
|
||||
class StringToDoubleConverter
|
||||
{
|
||||
public:
|
||||
// Enumeration for allowing octals and ignoring junk when converting
|
||||
// strings to numbers.
|
||||
enum Flags
|
||||
{
|
||||
NO_FLAGS = 0,
|
||||
ALLOW_HEX = 1,
|
||||
ALLOW_OCTALS = 2,
|
||||
ALLOW_TRAILING_JUNK = 4,
|
||||
ALLOW_LEADING_SPACES = 8,
|
||||
ALLOW_TRAILING_SPACES = 16,
|
||||
ALLOW_SPACES_AFTER_SIGN = 32
|
||||
};
|
||||
|
||||
// Flags should be a bit-or combination of the possible Flags-enum.
|
||||
// - NO_FLAGS: no special flags.
|
||||
// - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
|
||||
// Ex: StringToDouble("0x1234") -> 4660.0
|
||||
// In StringToDouble("0x1234.56") the characters ".56" are trailing
|
||||
// junk. The result of the call is hence dependent on
|
||||
// the ALLOW_TRAILING_JUNK flag and/or the junk value.
|
||||
// With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK,
|
||||
// the string will not be parsed as "0" followed by junk.
|
||||
//
|
||||
// - ALLOW_OCTALS: recognizes the prefix "0" for octals:
|
||||
// If a sequence of octal digits starts with '0', then the number is
|
||||
// read as octal integer. Octal numbers may only be integers.
|
||||
// Ex: StringToDouble("01234") -> 668.0
|
||||
// StringToDouble("012349") -> 12349.0 // Not a sequence of octal
|
||||
// // digits.
|
||||
// In StringToDouble("01234.56") the characters ".56" are trailing
|
||||
// junk. The result of the call is hence dependent on
|
||||
// the ALLOW_TRAILING_JUNK flag and/or the junk value.
|
||||
// In StringToDouble("01234e56") the characters "e56" are trailing
|
||||
// junk, too.
|
||||
// - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of
|
||||
// a double literal.
|
||||
// - ALLOW_LEADING_SPACES: skip over leading spaces.
|
||||
// - ALLOW_TRAILING_SPACES: ignore trailing spaces.
|
||||
// - ALLOW_SPACES_AFTER_SIGN: ignore spaces after the sign.
|
||||
// Ex: StringToDouble("- 123.2") -> -123.2.
|
||||
// StringToDouble("+ 123.2") -> 123.2
|
||||
//
|
||||
// empty_string_value is returned when an empty string is given as input.
|
||||
// If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
|
||||
// containing only spaces is converted to the 'empty_string_value', too.
|
||||
//
|
||||
// junk_string_value is returned when
|
||||
// a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not
|
||||
// part of a double-literal) is found.
|
||||
// b) ALLOW_TRAILING_JUNK is set, but the string does not start with a
|
||||
// double literal.
|
||||
//
|
||||
// infinity_symbol and nan_symbol are strings that are used to detect
|
||||
// inputs that represent infinity and NaN. They can be null, in which case
|
||||
// they are ignored.
|
||||
// The conversion routine first reads any possible signs. Then it compares the
|
||||
// following character of the input-string with the first character of
|
||||
// the infinity, and nan-symbol. If either matches, the function assumes, that
|
||||
// a match has been found, and expects the following input characters to match
|
||||
// the remaining characters of the special-value symbol.
|
||||
// This means that the following restrictions apply to special-value symbols:
|
||||
// - they must not start with signs ('+', or '-'),
|
||||
// - they must not have the same first character.
|
||||
// - they must not start with digits.
|
||||
//
|
||||
// Examples:
|
||||
// flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
|
||||
// empty_string_value = 0.0,
|
||||
// junk_string_value = NaN,
|
||||
// infinity_symbol = "infinity",
|
||||
// nan_symbol = "nan":
|
||||
// StringToDouble("0x1234") -> 4660.0.
|
||||
// StringToDouble("0x1234K") -> 4660.0.
|
||||
// StringToDouble("") -> 0.0 // empty_string_value.
|
||||
// StringToDouble(" ") -> NaN // junk_string_value.
|
||||
// StringToDouble(" 1") -> NaN // junk_string_value.
|
||||
// StringToDouble("0x") -> NaN // junk_string_value.
|
||||
// StringToDouble("-123.45") -> -123.45.
|
||||
// StringToDouble("--123.45") -> NaN // junk_string_value.
|
||||
// StringToDouble("123e45") -> 123e45.
|
||||
// StringToDouble("123E45") -> 123e45.
|
||||
// StringToDouble("123e+45") -> 123e45.
|
||||
// StringToDouble("123E-45") -> 123e-45.
|
||||
// StringToDouble("123e") -> 123.0 // trailing junk ignored.
|
||||
// StringToDouble("123e-") -> 123.0 // trailing junk ignored.
|
||||
// StringToDouble("+NaN") -> NaN // NaN string literal.
|
||||
// StringToDouble("-infinity") -> -inf. // infinity literal.
|
||||
// StringToDouble("Infinity") -> NaN // junk_string_value.
|
||||
//
|
||||
// flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES,
|
||||
// empty_string_value = 0.0,
|
||||
// junk_string_value = NaN,
|
||||
// infinity_symbol = NULL,
|
||||
// nan_symbol = NULL:
|
||||
// StringToDouble("0x1234") -> NaN // junk_string_value.
|
||||
// StringToDouble("01234") -> 668.0.
|
||||
// StringToDouble("") -> 0.0 // empty_string_value.
|
||||
// StringToDouble(" ") -> 0.0 // empty_string_value.
|
||||
// StringToDouble(" 1") -> 1.0
|
||||
// StringToDouble("0x") -> NaN // junk_string_value.
|
||||
// StringToDouble("0123e45") -> NaN // junk_string_value.
|
||||
// StringToDouble("01239E45") -> 1239e45.
|
||||
// StringToDouble("-infinity") -> NaN // junk_string_value.
|
||||
// StringToDouble("NaN") -> NaN // junk_string_value.
|
||||
StringToDoubleConverter(
|
||||
int flags, double empty_string_value, double junk_string_value, const char * infinity_symbol, const char * nan_symbol)
|
||||
: flags_(flags)
|
||||
, empty_string_value_(empty_string_value)
|
||||
, junk_string_value_(junk_string_value)
|
||||
, infinity_symbol_(infinity_symbol)
|
||||
, nan_symbol_(nan_symbol)
|
||||
{
|
||||
}
|
||||
|
||||
// Performs the conversion.
|
||||
// The output parameter 'processed_characters_count' is set to the number
|
||||
// of characters that have been processed to read the number.
|
||||
// Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included
|
||||
// in the 'processed_characters_count'. Trailing junk is never included.
|
||||
double StringToDouble(const char * buffer, int length, int * processed_characters_count) const
|
||||
{
|
||||
return StringToIeee(buffer, length, processed_characters_count, true);
|
||||
}
|
||||
|
||||
// Same as StringToDouble but reads a float.
|
||||
// Note that this is not equivalent to static_cast<float>(StringToDouble(...))
|
||||
// due to potential double-rounding.
|
||||
float StringToFloat(const char * buffer, int length, int * processed_characters_count) const
|
||||
{
|
||||
return static_cast<float>(StringToIeee(buffer, length, processed_characters_count, false));
|
||||
}
|
||||
|
||||
private:
|
||||
const int flags_;
|
||||
const double empty_string_value_;
|
||||
const double junk_string_value_;
|
||||
const char * const infinity_symbol_;
|
||||
const char * const nan_symbol_;
|
||||
|
||||
double StringToIeee(const char * buffer, int length, int * processed_characters_count, bool read_as_double) const;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
|
@ -1,665 +0,0 @@
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "fast-dtoa.h"
|
||||
|
||||
#include "cached-powers.h"
|
||||
#include "diy-fp.h"
|
||||
#include "ieee.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
// The minimal and maximal target exponent define the range of w's binary
|
||||
// exponent, where 'w' is the result of multiplying the input by a cached power
|
||||
// of ten.
|
||||
//
|
||||
// A different range might be chosen on a different platform, to optimize digit
|
||||
// generation, but a smaller range requires more powers of ten to be cached.
|
||||
static const int kMinimalTargetExponent = -60;
|
||||
static const int kMaximalTargetExponent = -32;
|
||||
|
||||
|
||||
// Adjusts the last digit of the generated number, and screens out generated
|
||||
// solutions that may be inaccurate. A solution may be inaccurate if it is
|
||||
// outside the safe interval, or if we cannot prove that it is closer to the
|
||||
// input than a neighboring representation of the same length.
|
||||
//
|
||||
// Input: * buffer containing the digits of too_high / 10^kappa
|
||||
// * the buffer's length
|
||||
// * distance_too_high_w == (too_high - w).f() * unit
|
||||
// * unsafe_interval == (too_high - too_low).f() * unit
|
||||
// * rest = (too_high - buffer * 10^kappa).f() * unit
|
||||
// * ten_kappa = 10^kappa * unit
|
||||
// * unit = the common multiplier
|
||||
// Output: returns true if the buffer is guaranteed to contain the closest
|
||||
// representable number to the input.
|
||||
// Modifies the generated digits in the buffer to approach (round towards) w.
|
||||
static bool RoundWeed(Vector<char> buffer,
|
||||
int length,
|
||||
uint64_t distance_too_high_w,
|
||||
uint64_t unsafe_interval,
|
||||
uint64_t rest,
|
||||
uint64_t ten_kappa,
|
||||
uint64_t unit) {
|
||||
uint64_t small_distance = distance_too_high_w - unit;
|
||||
uint64_t big_distance = distance_too_high_w + unit;
|
||||
// Let w_low = too_high - big_distance, and
|
||||
// w_high = too_high - small_distance.
|
||||
// Note: w_low < w < w_high
|
||||
//
|
||||
// The real w (* unit) must lie somewhere inside the interval
|
||||
// ]w_low; w_high[ (often written as "(w_low; w_high)")
|
||||
|
||||
// Basically the buffer currently contains a number in the unsafe interval
|
||||
// ]too_low; too_high[ with too_low < w < too_high
|
||||
//
|
||||
// too_high - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// ^v 1 unit ^ ^ ^ ^
|
||||
// boundary_high --------------------- . . . .
|
||||
// ^v 1 unit . . . .
|
||||
// - - - - - - - - - - - - - - - - - - - + - - + - - - - - - . .
|
||||
// . . ^ . .
|
||||
// . big_distance . . .
|
||||
// . . . . rest
|
||||
// small_distance . . . .
|
||||
// v . . . .
|
||||
// w_high - - - - - - - - - - - - - - - - - - . . . .
|
||||
// ^v 1 unit . . . .
|
||||
// w ---------------------------------------- . . . .
|
||||
// ^v 1 unit v . . .
|
||||
// w_low - - - - - - - - - - - - - - - - - - - - - . . .
|
||||
// . . v
|
||||
// buffer --------------------------------------------------+-------+--------
|
||||
// . .
|
||||
// safe_interval .
|
||||
// v .
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .
|
||||
// ^v 1 unit .
|
||||
// boundary_low ------------------------- unsafe_interval
|
||||
// ^v 1 unit v
|
||||
// too_low - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
//
|
||||
//
|
||||
// Note that the value of buffer could lie anywhere inside the range too_low
|
||||
// to too_high.
|
||||
//
|
||||
// boundary_low, boundary_high and w are approximations of the real boundaries
|
||||
// and v (the input number). They are guaranteed to be precise up to one unit.
|
||||
// In fact the error is guaranteed to be strictly less than one unit.
|
||||
//
|
||||
// Anything that lies outside the unsafe interval is guaranteed not to round
|
||||
// to v when read again.
|
||||
// Anything that lies inside the safe interval is guaranteed to round to v
|
||||
// when read again.
|
||||
// If the number inside the buffer lies inside the unsafe interval but not
|
||||
// inside the safe interval then we simply do not know and bail out (returning
|
||||
// false).
|
||||
//
|
||||
// Similarly we have to take into account the imprecision of 'w' when finding
|
||||
// the closest representation of 'w'. If we have two potential
|
||||
// representations, and one is closer to both w_low and w_high, then we know
|
||||
// it is closer to the actual value v.
|
||||
//
|
||||
// By generating the digits of too_high we got the largest (closest to
|
||||
// too_high) buffer that is still in the unsafe interval. In the case where
|
||||
// w_high < buffer < too_high we try to decrement the buffer.
|
||||
// This way the buffer approaches (rounds towards) w.
|
||||
// There are 3 conditions that stop the decrementation process:
|
||||
// 1) the buffer is already below w_high
|
||||
// 2) decrementing the buffer would make it leave the unsafe interval
|
||||
// 3) decrementing the buffer would yield a number below w_high and farther
|
||||
// away than the current number. In other words:
|
||||
// (buffer{-1} < w_high) && w_high - buffer{-1} > buffer - w_high
|
||||
// Instead of using the buffer directly we use its distance to too_high.
|
||||
// Conceptually rest ~= too_high - buffer
|
||||
// We need to do the following tests in this order to avoid over- and
|
||||
// underflows.
|
||||
ASSERT(rest <= unsafe_interval);
|
||||
while (rest < small_distance && // Negated condition 1
|
||||
unsafe_interval - rest >= ten_kappa && // Negated condition 2
|
||||
(rest + ten_kappa < small_distance || // buffer{-1} > w_high
|
||||
small_distance - rest >= rest + ten_kappa - small_distance)) {
|
||||
buffer[length - 1]--;
|
||||
rest += ten_kappa;
|
||||
}
|
||||
|
||||
// We have approached w+ as much as possible. We now test if approaching w-
|
||||
// would require changing the buffer. If yes, then we have two possible
|
||||
// representations close to w, but we cannot decide which one is closer.
|
||||
if (rest < big_distance &&
|
||||
unsafe_interval - rest >= ten_kappa &&
|
||||
(rest + ten_kappa < big_distance ||
|
||||
big_distance - rest > rest + ten_kappa - big_distance)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Weeding test.
|
||||
// The safe interval is [too_low + 2 ulp; too_high - 2 ulp]
|
||||
// Since too_low = too_high - unsafe_interval this is equivalent to
|
||||
// [too_high - unsafe_interval + 4 ulp; too_high - 2 ulp]
|
||||
// Conceptually we have: rest ~= too_high - buffer
|
||||
return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit);
|
||||
}
|
||||
|
||||
|
||||
// Rounds the buffer upwards if the result is closer to v by possibly adding
|
||||
// 1 to the buffer. If the precision of the calculation is not sufficient to
|
||||
// round correctly, return false.
|
||||
// The rounding might shift the whole buffer in which case the kappa is
|
||||
// adjusted. For example "99", kappa = 3 might become "10", kappa = 4.
|
||||
//
|
||||
// If 2*rest > ten_kappa then the buffer needs to be round up.
|
||||
// rest can have an error of +/- 1 unit. This function accounts for the
|
||||
// imprecision and returns false, if the rounding direction cannot be
|
||||
// unambiguously determined.
|
||||
//
|
||||
// Precondition: rest < ten_kappa.
|
||||
static bool RoundWeedCounted(Vector<char> buffer,
|
||||
int length,
|
||||
uint64_t rest,
|
||||
uint64_t ten_kappa,
|
||||
uint64_t unit,
|
||||
int* kappa) {
|
||||
ASSERT(rest < ten_kappa);
|
||||
// The following tests are done in a specific order to avoid overflows. They
|
||||
// will work correctly with any uint64 values of rest < ten_kappa and unit.
|
||||
//
|
||||
// If the unit is too big, then we don't know which way to round. For example
|
||||
// a unit of 50 means that the real number lies within rest +/- 50. If
|
||||
// 10^kappa == 40 then there is no way to tell which way to round.
|
||||
if (unit >= ten_kappa) return false;
|
||||
// Even if unit is just half the size of 10^kappa we are already completely
|
||||
// lost. (And after the previous test we know that the expression will not
|
||||
// over/underflow.)
|
||||
if (ten_kappa - unit <= unit) return false;
|
||||
// If 2 * (rest + unit) <= 10^kappa we can safely round down.
|
||||
if ((ten_kappa - rest > rest) && (ten_kappa - 2 * rest >= 2 * unit)) {
|
||||
return true;
|
||||
}
|
||||
// If 2 * (rest - unit) >= 10^kappa, then we can safely round up.
|
||||
if ((rest > unit) && (ten_kappa - (rest - unit) <= (rest - unit))) {
|
||||
// Increment the last digit recursively until we find a non '9' digit.
|
||||
buffer[length - 1]++;
|
||||
for (int i = length - 1; i > 0; --i) {
|
||||
if (buffer[i] != '0' + 10) break;
|
||||
buffer[i] = '0';
|
||||
buffer[i - 1]++;
|
||||
}
|
||||
// If the first digit is now '0'+ 10 we had a buffer with all '9's. With the
|
||||
// exception of the first digit all digits are now '0'. Simply switch the
|
||||
// first digit to '1' and adjust the kappa. Example: "99" becomes "10" and
|
||||
// the power (the kappa) is increased.
|
||||
if (buffer[0] == '0' + 10) {
|
||||
buffer[0] = '1';
|
||||
(*kappa) += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the biggest power of ten that is less than or equal to the given
|
||||
// number. We furthermore receive the maximum number of bits 'number' has.
|
||||
//
|
||||
// Returns power == 10^(exponent_plus_one-1) such that
|
||||
// power <= number < power * 10.
|
||||
// If number_bits == 0 then 0^(0-1) is returned.
|
||||
// The number of bits must be <= 32.
|
||||
// Precondition: number < (1 << (number_bits + 1)).
|
||||
|
||||
// Inspired by the method for finding an integer log base 10 from here:
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
|
||||
static unsigned int const kSmallPowersOfTen[] =
|
||||
{0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,
|
||||
1000000000};
|
||||
|
||||
static void BiggestPowerTen(uint32_t number,
|
||||
int number_bits,
|
||||
uint32_t* power,
|
||||
int* exponent_plus_one) {
|
||||
ASSERT(number < (1u << (number_bits + 1)));
|
||||
// 1233/4096 is approximately 1/lg(10).
|
||||
int exponent_plus_one_guess = ((number_bits + 1) * 1233 >> 12);
|
||||
// We increment to skip over the first entry in the kPowersOf10 table.
|
||||
// Note: kPowersOf10[i] == 10^(i-1).
|
||||
exponent_plus_one_guess++;
|
||||
// We don't have any guarantees that 2^number_bits <= number.
|
||||
if (number < kSmallPowersOfTen[exponent_plus_one_guess] && exponent_plus_one_guess > 0) {
|
||||
exponent_plus_one_guess--;
|
||||
}
|
||||
*power = kSmallPowersOfTen[exponent_plus_one_guess];
|
||||
*exponent_plus_one = exponent_plus_one_guess;
|
||||
}
|
||||
|
||||
// Generates the digits of input number w.
|
||||
// w is a floating-point number (DiyFp), consisting of a significand and an
|
||||
// exponent. Its exponent is bounded by kMinimalTargetExponent and
|
||||
// kMaximalTargetExponent.
|
||||
// Hence -60 <= w.e() <= -32.
|
||||
//
|
||||
// Returns false if it fails, in which case the generated digits in the buffer
|
||||
// should not be used.
|
||||
// Preconditions:
|
||||
// * low, w and high are correct up to 1 ulp (unit in the last place). That
|
||||
// is, their error must be less than a unit of their last digits.
|
||||
// * low.e() == w.e() == high.e()
|
||||
// * low < w < high, and taking into account their error: low~ <= high~
|
||||
// * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent
|
||||
// Postconditions: returns false if procedure fails.
|
||||
// otherwise:
|
||||
// * buffer is not null-terminated, but len contains the number of digits.
|
||||
// * buffer contains the shortest possible decimal digit-sequence
|
||||
// such that LOW < buffer * 10^kappa < HIGH, where LOW and HIGH are the
|
||||
// correct values of low and high (without their error).
|
||||
// * if more than one decimal representation gives the minimal number of
|
||||
// decimal digits then the one closest to W (where W is the correct value
|
||||
// of w) is chosen.
|
||||
// Remark: this procedure takes into account the imprecision of its input
|
||||
// numbers. If the precision is not enough to guarantee all the postconditions
|
||||
// then false is returned. This usually happens rarely (~0.5%).
|
||||
//
|
||||
// Say, for the sake of example, that
|
||||
// w.e() == -48, and w.f() == 0x1234567890abcdef
|
||||
// w's value can be computed by w.f() * 2^w.e()
|
||||
// We can obtain w's integral digits by simply shifting w.f() by -w.e().
|
||||
// -> w's integral part is 0x1234
|
||||
// w's fractional part is therefore 0x567890abcdef.
|
||||
// Printing w's integral part is easy (simply print 0x1234 in decimal).
|
||||
// In order to print its fraction we repeatedly multiply the fraction by 10 and
|
||||
// get each digit. Example the first digit after the point would be computed by
|
||||
// (0x567890abcdef * 10) >> 48. -> 3
|
||||
// The whole thing becomes slightly more complicated because we want to stop
|
||||
// once we have enough digits. That is, once the digits inside the buffer
|
||||
// represent 'w' we can stop. Everything inside the interval low - high
|
||||
// represents w. However we have to pay attention to low, high and w's
|
||||
// imprecision.
|
||||
static bool DigitGen(DiyFp low,
|
||||
DiyFp w,
|
||||
DiyFp high,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* kappa) {
|
||||
ASSERT(low.e() == w.e() && w.e() == high.e());
|
||||
ASSERT(low.f() + 1 <= high.f() - 1);
|
||||
ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
|
||||
// low, w and high are imprecise, but by less than one ulp (unit in the last
|
||||
// place).
|
||||
// If we remove (resp. add) 1 ulp from low (resp. high) we are certain that
|
||||
// the new numbers are outside of the interval we want the final
|
||||
// representation to lie in.
|
||||
// Inversely adding (resp. removing) 1 ulp from low (resp. high) would yield
|
||||
// numbers that are certain to lie in the interval. We will use this fact
|
||||
// later on.
|
||||
// We will now start by generating the digits within the uncertain
|
||||
// interval. Later we will weed out representations that lie outside the safe
|
||||
// interval and thus _might_ lie outside the correct interval.
|
||||
uint64_t unit = 1;
|
||||
DiyFp too_low = DiyFp(low.f() - unit, low.e());
|
||||
DiyFp too_high = DiyFp(high.f() + unit, high.e());
|
||||
// too_low and too_high are guaranteed to lie outside the interval we want the
|
||||
// generated number in.
|
||||
DiyFp unsafe_interval = DiyFp::Minus(too_high, too_low);
|
||||
// We now cut the input number into two parts: the integral digits and the
|
||||
// fractionals. We will not write any decimal separator though, but adapt
|
||||
// kappa instead.
|
||||
// Reminder: we are currently computing the digits (stored inside the buffer)
|
||||
// such that: too_low < buffer * 10^kappa < too_high
|
||||
// We use too_high for the digit_generation and stop as soon as possible.
|
||||
// If we stop early we effectively round down.
|
||||
DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e());
|
||||
// Division by one is a shift.
|
||||
uint32_t integrals = static_cast<uint32_t>(too_high.f() >> -one.e());
|
||||
// Modulo by one is an and.
|
||||
uint64_t fractionals = too_high.f() & (one.f() - 1);
|
||||
uint32_t divisor;
|
||||
int divisor_exponent_plus_one;
|
||||
BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),
|
||||
&divisor, &divisor_exponent_plus_one);
|
||||
*kappa = divisor_exponent_plus_one;
|
||||
*length = 0;
|
||||
// Loop invariant: buffer = too_high / 10^kappa (integer division)
|
||||
// The invariant holds for the first iteration: kappa has been initialized
|
||||
// with the divisor exponent + 1. And the divisor is the biggest power of ten
|
||||
// that is smaller than integrals.
|
||||
while (*kappa > 0) {
|
||||
int digit = integrals / divisor;
|
||||
ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
integrals %= divisor;
|
||||
(*kappa)--;
|
||||
// Note that kappa now equals the exponent of the divisor and that the
|
||||
// invariant thus holds again.
|
||||
uint64_t rest =
|
||||
(static_cast<uint64_t>(integrals) << -one.e()) + fractionals;
|
||||
// Invariant: too_high = buffer * 10^kappa + DiyFp(rest, one.e())
|
||||
// Reminder: unsafe_interval.e() == one.e()
|
||||
if (rest < unsafe_interval.f()) {
|
||||
// Rounding down (by not emitting the remaining digits) yields a number
|
||||
// that lies within the unsafe interval.
|
||||
return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f(),
|
||||
unsafe_interval.f(), rest,
|
||||
static_cast<uint64_t>(divisor) << -one.e(), unit);
|
||||
}
|
||||
divisor /= 10;
|
||||
}
|
||||
|
||||
// The integrals have been generated. We are at the point of the decimal
|
||||
// separator. In the following loop we simply multiply the remaining digits by
|
||||
// 10 and divide by one. We just need to pay attention to multiply associated
|
||||
// data (like the interval or 'unit'), too.
|
||||
// Note that the multiplication by 10 does not overflow, because w.e >= -60
|
||||
// and thus one.e >= -60.
|
||||
ASSERT(one.e() >= -60);
|
||||
ASSERT(fractionals < one.f());
|
||||
ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
|
||||
for (;;) {
|
||||
fractionals *= 10;
|
||||
unit *= 10;
|
||||
unsafe_interval.set_f(unsafe_interval.f() * 10);
|
||||
// Integer division by one.
|
||||
int digit = static_cast<int>(fractionals >> -one.e());
|
||||
ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
fractionals &= one.f() - 1; // Modulo by one.
|
||||
(*kappa)--;
|
||||
if (fractionals < unsafe_interval.f()) {
|
||||
return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f() * unit,
|
||||
unsafe_interval.f(), fractionals, one.f(), unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Generates (at most) requested_digits digits of input number w.
|
||||
// w is a floating-point number (DiyFp), consisting of a significand and an
|
||||
// exponent. Its exponent is bounded by kMinimalTargetExponent and
|
||||
// kMaximalTargetExponent.
|
||||
// Hence -60 <= w.e() <= -32.
|
||||
//
|
||||
// Returns false if it fails, in which case the generated digits in the buffer
|
||||
// should not be used.
|
||||
// Preconditions:
|
||||
// * w is correct up to 1 ulp (unit in the last place). That
|
||||
// is, its error must be strictly less than a unit of its last digit.
|
||||
// * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent
|
||||
//
|
||||
// Postconditions: returns false if procedure fails.
|
||||
// otherwise:
|
||||
// * buffer is not null-terminated, but length contains the number of
|
||||
// digits.
|
||||
// * the representation in buffer is the most precise representation of
|
||||
// requested_digits digits.
|
||||
// * buffer contains at most requested_digits digits of w. If there are less
|
||||
// than requested_digits digits then some trailing '0's have been removed.
|
||||
// * kappa is such that
|
||||
// w = buffer * 10^kappa + eps with |eps| < 10^kappa / 2.
|
||||
//
|
||||
// Remark: This procedure takes into account the imprecision of its input
|
||||
// numbers. If the precision is not enough to guarantee all the postconditions
|
||||
// then false is returned. This usually happens rarely, but the failure-rate
|
||||
// increases with higher requested_digits.
|
||||
static bool DigitGenCounted(DiyFp w,
|
||||
int requested_digits,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* kappa) {
|
||||
ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
|
||||
ASSERT(kMinimalTargetExponent >= -60);
|
||||
ASSERT(kMaximalTargetExponent <= -32);
|
||||
// w is assumed to have an error less than 1 unit. Whenever w is scaled we
|
||||
// also scale its error.
|
||||
uint64_t w_error = 1;
|
||||
// We cut the input number into two parts: the integral digits and the
|
||||
// fractional digits. We don't emit any decimal separator, but adapt kappa
|
||||
// instead. Example: instead of writing "1.2" we put "12" into the buffer and
|
||||
// increase kappa by 1.
|
||||
DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e());
|
||||
// Division by one is a shift.
|
||||
uint32_t integrals = static_cast<uint32_t>(w.f() >> -one.e());
|
||||
// Modulo by one is an and.
|
||||
uint64_t fractionals = w.f() & (one.f() - 1);
|
||||
uint32_t divisor;
|
||||
int divisor_exponent_plus_one;
|
||||
BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),
|
||||
&divisor, &divisor_exponent_plus_one);
|
||||
*kappa = divisor_exponent_plus_one;
|
||||
*length = 0;
|
||||
|
||||
// Loop invariant: buffer = w / 10^kappa (integer division)
|
||||
// The invariant holds for the first iteration: kappa has been initialized
|
||||
// with the divisor exponent + 1. And the divisor is the biggest power of ten
|
||||
// that is smaller than 'integrals'.
|
||||
while (*kappa > 0) {
|
||||
int digit = integrals / divisor;
|
||||
ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
requested_digits--;
|
||||
integrals %= divisor;
|
||||
(*kappa)--;
|
||||
// Note that kappa now equals the exponent of the divisor and that the
|
||||
// invariant thus holds again.
|
||||
if (requested_digits == 0) break;
|
||||
divisor /= 10;
|
||||
}
|
||||
|
||||
if (requested_digits == 0) {
|
||||
uint64_t rest =
|
||||
(static_cast<uint64_t>(integrals) << -one.e()) + fractionals;
|
||||
return RoundWeedCounted(buffer, *length, rest,
|
||||
static_cast<uint64_t>(divisor) << -one.e(), w_error,
|
||||
kappa);
|
||||
}
|
||||
|
||||
// The integrals have been generated. We are at the point of the decimal
|
||||
// separator. In the following loop we simply multiply the remaining digits by
|
||||
// 10 and divide by one. We just need to pay attention to multiply associated
|
||||
// data (the 'unit'), too.
|
||||
// Note that the multiplication by 10 does not overflow, because w.e >= -60
|
||||
// and thus one.e >= -60.
|
||||
ASSERT(one.e() >= -60);
|
||||
ASSERT(fractionals < one.f());
|
||||
ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
|
||||
while (requested_digits > 0 && fractionals > w_error) {
|
||||
fractionals *= 10;
|
||||
w_error *= 10;
|
||||
// Integer division by one.
|
||||
int digit = static_cast<int>(fractionals >> -one.e());
|
||||
ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
requested_digits--;
|
||||
fractionals &= one.f() - 1; // Modulo by one.
|
||||
(*kappa)--;
|
||||
}
|
||||
if (requested_digits != 0) return false;
|
||||
return RoundWeedCounted(buffer, *length, fractionals, one.f(), w_error,
|
||||
kappa);
|
||||
}
|
||||
|
||||
|
||||
// Provides a decimal representation of v.
|
||||
// Returns true if it succeeds, otherwise the result cannot be trusted.
|
||||
// There will be *length digits inside the buffer (not null-terminated).
|
||||
// If the function returns true then
|
||||
// v == (double) (buffer * 10^decimal_exponent).
|
||||
// The digits in the buffer are the shortest representation possible: no
|
||||
// 0.09999999999999999 instead of 0.1. The shorter representation will even be
|
||||
// chosen even if the longer one would be closer to v.
|
||||
// The last digit will be closest to the actual v. That is, even if several
|
||||
// digits might correctly yield 'v' when read again, the closest will be
|
||||
// computed.
|
||||
static bool Grisu3(double v,
|
||||
FastDtoaMode mode,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* decimal_exponent) {
|
||||
DiyFp w = Double(v).AsNormalizedDiyFp();
|
||||
// boundary_minus and boundary_plus are the boundaries between v and its
|
||||
// closest floating-point neighbors. Any number strictly between
|
||||
// boundary_minus and boundary_plus will round to v when convert to a double.
|
||||
// Grisu3 will never output representations that lie exactly on a boundary.
|
||||
DiyFp boundary_minus, boundary_plus;
|
||||
if (mode == FAST_DTOA_SHORTEST) {
|
||||
Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
|
||||
} else {
|
||||
ASSERT(mode == FAST_DTOA_SHORTEST_SINGLE);
|
||||
float single_v = static_cast<float>(v);
|
||||
Single(single_v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
|
||||
}
|
||||
ASSERT(boundary_plus.e() == w.e());
|
||||
DiyFp ten_mk; // Cached power of ten: 10^-k
|
||||
int mk; // -k
|
||||
int ten_mk_minimal_binary_exponent =
|
||||
kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
|
||||
int ten_mk_maximal_binary_exponent =
|
||||
kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
|
||||
PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
|
||||
ten_mk_minimal_binary_exponent,
|
||||
ten_mk_maximal_binary_exponent,
|
||||
&ten_mk, &mk);
|
||||
ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
|
||||
DiyFp::kSignificandSize) &&
|
||||
(kMaximalTargetExponent >= w.e() + ten_mk.e() +
|
||||
DiyFp::kSignificandSize));
|
||||
// Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
|
||||
// 64 bit significand and ten_mk is thus only precise up to 64 bits.
|
||||
|
||||
// The DiyFp::Times procedure rounds its result, and ten_mk is approximated
|
||||
// too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
|
||||
// off by a small amount.
|
||||
// In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
|
||||
// In other words: let f = scaled_w.f() and e = scaled_w.e(), then
|
||||
// (f-1) * 2^e < w*10^k < (f+1) * 2^e
|
||||
DiyFp scaled_w = DiyFp::Times(w, ten_mk);
|
||||
ASSERT(scaled_w.e() ==
|
||||
boundary_plus.e() + ten_mk.e() + DiyFp::kSignificandSize);
|
||||
// In theory it would be possible to avoid some recomputations by computing
|
||||
// the difference between w and boundary_minus/plus (a power of 2) and to
|
||||
// compute scaled_boundary_minus/plus by subtracting/adding from
|
||||
// scaled_w. However the code becomes much less readable and the speed
|
||||
// enhancements are not terrific.
|
||||
DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk);
|
||||
DiyFp scaled_boundary_plus = DiyFp::Times(boundary_plus, ten_mk);
|
||||
|
||||
// DigitGen will generate the digits of scaled_w. Therefore we have
|
||||
// v == (double) (scaled_w * 10^-mk).
|
||||
// Set decimal_exponent == -mk and pass it to DigitGen. If scaled_w is not an
|
||||
// integer than it will be updated. For instance if scaled_w == 1.23 then
|
||||
// the buffer will be filled with "123" und the decimal_exponent will be
|
||||
// decreased by 2.
|
||||
int kappa;
|
||||
bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus,
|
||||
buffer, length, &kappa);
|
||||
*decimal_exponent = -mk + kappa;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// The "counted" version of grisu3 (see above) only generates requested_digits
|
||||
// number of digits. This version does not generate the shortest representation,
|
||||
// and with enough requested digits 0.1 will at some point print as 0.9999999...
|
||||
// Grisu3 is too imprecise for real halfway cases (1.5 will not work) and
|
||||
// therefore the rounding strategy for halfway cases is irrelevant.
|
||||
static bool Grisu3Counted(double v,
|
||||
int requested_digits,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* decimal_exponent) {
|
||||
DiyFp w = Double(v).AsNormalizedDiyFp();
|
||||
DiyFp ten_mk; // Cached power of ten: 10^-k
|
||||
int mk; // -k
|
||||
int ten_mk_minimal_binary_exponent =
|
||||
kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
|
||||
int ten_mk_maximal_binary_exponent =
|
||||
kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
|
||||
PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
|
||||
ten_mk_minimal_binary_exponent,
|
||||
ten_mk_maximal_binary_exponent,
|
||||
&ten_mk, &mk);
|
||||
ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
|
||||
DiyFp::kSignificandSize) &&
|
||||
(kMaximalTargetExponent >= w.e() + ten_mk.e() +
|
||||
DiyFp::kSignificandSize));
|
||||
// Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
|
||||
// 64 bit significand and ten_mk is thus only precise up to 64 bits.
|
||||
|
||||
// The DiyFp::Times procedure rounds its result, and ten_mk is approximated
|
||||
// too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
|
||||
// off by a small amount.
|
||||
// In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
|
||||
// In other words: let f = scaled_w.f() and e = scaled_w.e(), then
|
||||
// (f-1) * 2^e < w*10^k < (f+1) * 2^e
|
||||
DiyFp scaled_w = DiyFp::Times(w, ten_mk);
|
||||
|
||||
// We now have (double) (scaled_w * 10^-mk).
|
||||
// DigitGen will generate the first requested_digits digits of scaled_w and
|
||||
// return together with a kappa such that scaled_w ~= buffer * 10^kappa. (It
|
||||
// will not always be exactly the same since DigitGenCounted only produces a
|
||||
// limited number of digits.)
|
||||
int kappa;
|
||||
bool result = DigitGenCounted(scaled_w, requested_digits,
|
||||
buffer, length, &kappa);
|
||||
*decimal_exponent = -mk + kappa;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool FastDtoa(double v,
|
||||
FastDtoaMode mode,
|
||||
int requested_digits,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* decimal_point) {
|
||||
ASSERT(v > 0);
|
||||
ASSERT(!Double(v).IsSpecial());
|
||||
|
||||
bool result = false;
|
||||
int decimal_exponent = 0;
|
||||
switch (mode) {
|
||||
case FAST_DTOA_SHORTEST:
|
||||
case FAST_DTOA_SHORTEST_SINGLE:
|
||||
result = Grisu3(v, mode, buffer, length, &decimal_exponent);
|
||||
break;
|
||||
case FAST_DTOA_PRECISION:
|
||||
result = Grisu3Counted(v, requested_digits,
|
||||
buffer, length, &decimal_exponent);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
if (result) {
|
||||
*decimal_point = *length + decimal_exponent;
|
||||
buffer[*length] = '\0';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
@ -1,85 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_FAST_DTOA_H_
|
||||
#define DOUBLE_CONVERSION_FAST_DTOA_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion
|
||||
{
|
||||
|
||||
enum FastDtoaMode
|
||||
{
|
||||
// Computes the shortest representation of the given input. The returned
|
||||
// result will be the most accurate number of this length. Longer
|
||||
// representations might be more accurate.
|
||||
FAST_DTOA_SHORTEST,
|
||||
// Same as FAST_DTOA_SHORTEST but for single-precision floats.
|
||||
FAST_DTOA_SHORTEST_SINGLE,
|
||||
// Computes a representation where the precision (number of digits) is
|
||||
// given as input. The precision is independent of the decimal point.
|
||||
FAST_DTOA_PRECISION
|
||||
};
|
||||
|
||||
// FastDtoa will produce at most kFastDtoaMaximalLength digits. This does not
|
||||
// include the terminating '\0' character.
|
||||
static const int kFastDtoaMaximalLength = 17;
|
||||
// Same for single-precision numbers.
|
||||
static const int kFastDtoaMaximalSingleLength = 9;
|
||||
|
||||
// Provides a decimal representation of v.
|
||||
// The result should be interpreted as buffer * 10^(point - length).
|
||||
//
|
||||
// Precondition:
|
||||
// * v must be a strictly positive finite double.
|
||||
//
|
||||
// Returns true if it succeeds, otherwise the result can not be trusted.
|
||||
// There will be *length digits inside the buffer followed by a null terminator.
|
||||
// If the function returns true and mode equals
|
||||
// - FAST_DTOA_SHORTEST, then
|
||||
// the parameter requested_digits is ignored.
|
||||
// The result satisfies
|
||||
// v == (double) (buffer * 10^(point - length)).
|
||||
// The digits in the buffer are the shortest representation possible. E.g.
|
||||
// if 0.099999999999 and 0.1 represent the same double then "1" is returned
|
||||
// with point = 0.
|
||||
// The last digit will be closest to the actual v. That is, even if several
|
||||
// digits might correctly yield 'v' when read again, the buffer will contain
|
||||
// the one closest to v.
|
||||
// - FAST_DTOA_PRECISION, then
|
||||
// the buffer contains requested_digits digits.
|
||||
// the difference v - (buffer * 10^(point-length)) is closest to zero for
|
||||
// all possible representations of requested_digits digits.
|
||||
// If there are two values that are equally close, then FastDtoa returns
|
||||
// false.
|
||||
// For both modes the buffer must be large enough to hold the result.
|
||||
bool FastDtoa(double d, FastDtoaMode mode, int requested_digits, Vector<char> buffer, int * length, int * decimal_point);
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_FAST_DTOA_H_
|
@ -1,404 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "fixed-dtoa.h"
|
||||
#include "ieee.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
// Represents a 128bit type. This class should be replaced by a native type on
|
||||
// platforms that support 128bit integers.
|
||||
class UInt128 {
|
||||
public:
|
||||
UInt128() : high_bits_(0), low_bits_(0) { }
|
||||
UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) { }
|
||||
|
||||
void Multiply(uint32_t multiplicand) {
|
||||
uint64_t accumulator;
|
||||
|
||||
accumulator = (low_bits_ & kMask32) * multiplicand;
|
||||
uint32_t part = static_cast<uint32_t>(accumulator & kMask32);
|
||||
accumulator >>= 32;
|
||||
accumulator = accumulator + (low_bits_ >> 32) * multiplicand;
|
||||
low_bits_ = (accumulator << 32) + part;
|
||||
accumulator >>= 32;
|
||||
accumulator = accumulator + (high_bits_ & kMask32) * multiplicand;
|
||||
part = static_cast<uint32_t>(accumulator & kMask32);
|
||||
accumulator >>= 32;
|
||||
accumulator = accumulator + (high_bits_ >> 32) * multiplicand;
|
||||
high_bits_ = (accumulator << 32) + part;
|
||||
ASSERT((accumulator >> 32) == 0);
|
||||
}
|
||||
|
||||
void Shift(int shift_amount) {
|
||||
ASSERT(-64 <= shift_amount && shift_amount <= 64);
|
||||
if (shift_amount == 0) {
|
||||
return;
|
||||
} else if (shift_amount == -64) {
|
||||
high_bits_ = low_bits_;
|
||||
low_bits_ = 0;
|
||||
} else if (shift_amount == 64) {
|
||||
low_bits_ = high_bits_;
|
||||
high_bits_ = 0;
|
||||
} else if (shift_amount <= 0) {
|
||||
high_bits_ <<= -shift_amount;
|
||||
high_bits_ += low_bits_ >> (64 + shift_amount);
|
||||
low_bits_ <<= -shift_amount;
|
||||
} else {
|
||||
low_bits_ >>= shift_amount;
|
||||
low_bits_ += high_bits_ << (64 - shift_amount);
|
||||
high_bits_ >>= shift_amount;
|
||||
}
|
||||
}
|
||||
|
||||
// Modifies *this to *this MOD (2^power).
|
||||
// Returns *this DIV (2^power).
|
||||
int DivModPowerOf2(int power) {
|
||||
if (power >= 64) {
|
||||
int result = static_cast<int>(high_bits_ >> (power - 64));
|
||||
high_bits_ -= static_cast<uint64_t>(result) << (power - 64);
|
||||
return result;
|
||||
} else {
|
||||
uint64_t part_low = low_bits_ >> power;
|
||||
uint64_t part_high = high_bits_ << (64 - power);
|
||||
int result = static_cast<int>(part_low + part_high);
|
||||
high_bits_ = 0;
|
||||
low_bits_ -= part_low << power;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsZero() const {
|
||||
return high_bits_ == 0 && low_bits_ == 0;
|
||||
}
|
||||
|
||||
int BitAt(int position) {
|
||||
if (position >= 64) {
|
||||
return static_cast<int>(high_bits_ >> (position - 64)) & 1;
|
||||
} else {
|
||||
return static_cast<int>(low_bits_ >> position) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static const uint64_t kMask32 = 0xFFFFFFFF;
|
||||
// Value == (high_bits_ << 64) + low_bits_
|
||||
uint64_t high_bits_;
|
||||
uint64_t low_bits_;
|
||||
};
|
||||
|
||||
|
||||
static const int kDoubleSignificandSize = 53; // Includes the hidden bit.
|
||||
|
||||
|
||||
static void FillDigits32FixedLength(uint32_t number, int requested_length,
|
||||
Vector<char> buffer, int* length) {
|
||||
for (int i = requested_length - 1; i >= 0; --i) {
|
||||
buffer[(*length) + i] = '0' + number % 10;
|
||||
number /= 10;
|
||||
}
|
||||
*length += requested_length;
|
||||
}
|
||||
|
||||
|
||||
static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) {
|
||||
int number_length = 0;
|
||||
// We fill the digits in reverse order and exchange them afterwards.
|
||||
while (number != 0) {
|
||||
int digit = number % 10;
|
||||
number /= 10;
|
||||
buffer[(*length) + number_length] = static_cast<char>('0' + digit);
|
||||
number_length++;
|
||||
}
|
||||
// Exchange the digits.
|
||||
int i = *length;
|
||||
int j = *length + number_length - 1;
|
||||
while (i < j) {
|
||||
char tmp = buffer[i];
|
||||
buffer[i] = buffer[j];
|
||||
buffer[j] = tmp;
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
*length += number_length;
|
||||
}
|
||||
|
||||
|
||||
static void FillDigits64FixedLength(uint64_t number,
|
||||
Vector<char> buffer, int* length) {
|
||||
const uint32_t kTen7 = 10000000;
|
||||
// For efficiency cut the number into 3 uint32_t parts, and print those.
|
||||
uint32_t part2 = static_cast<uint32_t>(number % kTen7);
|
||||
number /= kTen7;
|
||||
uint32_t part1 = static_cast<uint32_t>(number % kTen7);
|
||||
uint32_t part0 = static_cast<uint32_t>(number / kTen7);
|
||||
|
||||
FillDigits32FixedLength(part0, 3, buffer, length);
|
||||
FillDigits32FixedLength(part1, 7, buffer, length);
|
||||
FillDigits32FixedLength(part2, 7, buffer, length);
|
||||
}
|
||||
|
||||
|
||||
static void FillDigits64(uint64_t number, Vector<char> buffer, int* length) {
|
||||
const uint32_t kTen7 = 10000000;
|
||||
// For efficiency cut the number into 3 uint32_t parts, and print those.
|
||||
uint32_t part2 = static_cast<uint32_t>(number % kTen7);
|
||||
number /= kTen7;
|
||||
uint32_t part1 = static_cast<uint32_t>(number % kTen7);
|
||||
uint32_t part0 = static_cast<uint32_t>(number / kTen7);
|
||||
|
||||
if (part0 != 0) {
|
||||
FillDigits32(part0, buffer, length);
|
||||
FillDigits32FixedLength(part1, 7, buffer, length);
|
||||
FillDigits32FixedLength(part2, 7, buffer, length);
|
||||
} else if (part1 != 0) {
|
||||
FillDigits32(part1, buffer, length);
|
||||
FillDigits32FixedLength(part2, 7, buffer, length);
|
||||
} else {
|
||||
FillDigits32(part2, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void RoundUp(Vector<char> buffer, int* length, int* decimal_point) {
|
||||
// An empty buffer represents 0.
|
||||
if (*length == 0) {
|
||||
buffer[0] = '1';
|
||||
*decimal_point = 1;
|
||||
*length = 1;
|
||||
return;
|
||||
}
|
||||
// Round the last digit until we either have a digit that was not '9' or until
|
||||
// we reached the first digit.
|
||||
buffer[(*length) - 1]++;
|
||||
for (int i = (*length) - 1; i > 0; --i) {
|
||||
if (buffer[i] != '0' + 10) {
|
||||
return;
|
||||
}
|
||||
buffer[i] = '0';
|
||||
buffer[i - 1]++;
|
||||
}
|
||||
// If the first digit is now '0' + 10, we would need to set it to '0' and add
|
||||
// a '1' in front. However we reach the first digit only if all following
|
||||
// digits had been '9' before rounding up. Now all trailing digits are '0' and
|
||||
// we simply switch the first digit to '1' and update the decimal-point
|
||||
// (indicating that the point is now one digit to the right).
|
||||
if (buffer[0] == '0' + 10) {
|
||||
buffer[0] = '1';
|
||||
(*decimal_point)++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The given fractionals number represents a fixed-point number with binary
|
||||
// point at bit (-exponent).
|
||||
// Preconditions:
|
||||
// -128 <= exponent <= 0.
|
||||
// 0 <= fractionals * 2^exponent < 1
|
||||
// The buffer holds the result.
|
||||
// The function will round its result. During the rounding-process digits not
|
||||
// generated by this function might be updated, and the decimal-point variable
|
||||
// might be updated. If this function generates the digits 99 and the buffer
|
||||
// already contained "199" (thus yielding a buffer of "19999") then a
|
||||
// rounding-up will change the contents of the buffer to "20000".
|
||||
static void FillFractionals(uint64_t fractionals, int exponent,
|
||||
int fractional_count, Vector<char> buffer,
|
||||
int* length, int* decimal_point) {
|
||||
ASSERT(-128 <= exponent && exponent <= 0);
|
||||
// 'fractionals' is a fixed-point number, with binary point at bit
|
||||
// (-exponent). Inside the function the non-converted remainder of fractionals
|
||||
// is a fixed-point number, with binary point at bit 'point'.
|
||||
if (-exponent <= 64) {
|
||||
// One 64 bit number is sufficient.
|
||||
ASSERT(fractionals >> 56 == 0);
|
||||
int point = -exponent;
|
||||
for (int i = 0; i < fractional_count; ++i) {
|
||||
if (fractionals == 0) break;
|
||||
// Instead of multiplying by 10 we multiply by 5 and adjust the point
|
||||
// location. This way the fractionals variable will not overflow.
|
||||
// Invariant at the beginning of the loop: fractionals < 2^point.
|
||||
// Initially we have: point <= 64 and fractionals < 2^56
|
||||
// After each iteration the point is decremented by one.
|
||||
// Note that 5^3 = 125 < 128 = 2^7.
|
||||
// Therefore three iterations of this loop will not overflow fractionals
|
||||
// (even without the subtraction at the end of the loop body). At this
|
||||
// time point will satisfy point <= 61 and therefore fractionals < 2^point
|
||||
// and any further multiplication of fractionals by 5 will not overflow.
|
||||
fractionals *= 5;
|
||||
point--;
|
||||
int digit = static_cast<int>(fractionals >> point);
|
||||
ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
fractionals -= static_cast<uint64_t>(digit) << point;
|
||||
}
|
||||
// If the first bit after the point is set we have to round up.
|
||||
if (((fractionals >> (point - 1)) & 1) == 1) {
|
||||
RoundUp(buffer, length, decimal_point);
|
||||
}
|
||||
} else { // We need 128 bits.
|
||||
ASSERT(64 < -exponent && -exponent <= 128);
|
||||
UInt128 fractionals128 = UInt128(fractionals, 0);
|
||||
fractionals128.Shift(-exponent - 64);
|
||||
int point = 128;
|
||||
for (int i = 0; i < fractional_count; ++i) {
|
||||
if (fractionals128.IsZero()) break;
|
||||
// As before: instead of multiplying by 10 we multiply by 5 and adjust the
|
||||
// point location.
|
||||
// This multiplication will not overflow for the same reasons as before.
|
||||
fractionals128.Multiply(5);
|
||||
point--;
|
||||
int digit = fractionals128.DivModPowerOf2(point);
|
||||
ASSERT(digit <= 9);
|
||||
buffer[*length] = static_cast<char>('0' + digit);
|
||||
(*length)++;
|
||||
}
|
||||
if (fractionals128.BitAt(point - 1) == 1) {
|
||||
RoundUp(buffer, length, decimal_point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Removes leading and trailing zeros.
|
||||
// If leading zeros are removed then the decimal point position is adjusted.
|
||||
static void TrimZeros(Vector<char> buffer, int* length, int* decimal_point) {
|
||||
while (*length > 0 && buffer[(*length) - 1] == '0') {
|
||||
(*length)--;
|
||||
}
|
||||
int first_non_zero = 0;
|
||||
while (first_non_zero < *length && buffer[first_non_zero] == '0') {
|
||||
first_non_zero++;
|
||||
}
|
||||
if (first_non_zero != 0) {
|
||||
for (int i = first_non_zero; i < *length; ++i) {
|
||||
buffer[i - first_non_zero] = buffer[i];
|
||||
}
|
||||
*length -= first_non_zero;
|
||||
*decimal_point -= first_non_zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FastFixedDtoa(double v,
|
||||
int fractional_count,
|
||||
Vector<char> buffer,
|
||||
int* length,
|
||||
int* decimal_point) {
|
||||
const uint32_t kMaxUInt32 = 0xFFFFFFFF;
|
||||
uint64_t significand = Double(v).Significand();
|
||||
int exponent = Double(v).Exponent();
|
||||
// v = significand * 2^exponent (with significand a 53bit integer).
|
||||
// If the exponent is larger than 20 (i.e. we may have a 73bit number) then we
|
||||
// don't know how to compute the representation. 2^73 ~= 9.5*10^21.
|
||||
// If necessary this limit could probably be increased, but we don't need
|
||||
// more.
|
||||
if (exponent > 20) return false;
|
||||
if (fractional_count > 20) return false;
|
||||
*length = 0;
|
||||
// At most kDoubleSignificandSize bits of the significand are non-zero.
|
||||
// Given a 64 bit integer we have 11 0s followed by 53 potentially non-zero
|
||||
// bits: 0..11*..0xxx..53*..xx
|
||||
if (exponent + kDoubleSignificandSize > 64) {
|
||||
// The exponent must be > 11.
|
||||
//
|
||||
// We know that v = significand * 2^exponent.
|
||||
// And the exponent > 11.
|
||||
// We simplify the task by dividing v by 10^17.
|
||||
// The quotient delivers the first digits, and the remainder fits into a 64
|
||||
// bit number.
|
||||
// Dividing by 10^17 is equivalent to dividing by 5^17*2^17.
|
||||
const uint64_t kFive17 = UINT64_2PART_C(0xB1, A2BC2EC5); // 5^17
|
||||
uint64_t divisor = kFive17;
|
||||
int divisor_power = 17;
|
||||
uint64_t dividend = significand;
|
||||
uint32_t quotient;
|
||||
uint64_t remainder;
|
||||
// Let v = f * 2^e with f == significand and e == exponent.
|
||||
// Then need q (quotient) and r (remainder) as follows:
|
||||
// v = q * 10^17 + r
|
||||
// f * 2^e = q * 10^17 + r
|
||||
// f * 2^e = q * 5^17 * 2^17 + r
|
||||
// If e > 17 then
|
||||
// f * 2^(e-17) = q * 5^17 + r/2^17
|
||||
// else
|
||||
// f = q * 5^17 * 2^(17-e) + r/2^e
|
||||
if (exponent > divisor_power) {
|
||||
// We only allow exponents of up to 20 and therefore (17 - e) <= 3
|
||||
dividend <<= exponent - divisor_power;
|
||||
quotient = static_cast<uint32_t>(dividend / divisor);
|
||||
remainder = (dividend % divisor) << divisor_power;
|
||||
} else {
|
||||
divisor <<= divisor_power - exponent;
|
||||
quotient = static_cast<uint32_t>(dividend / divisor);
|
||||
remainder = (dividend % divisor) << exponent;
|
||||
}
|
||||
FillDigits32(quotient, buffer, length);
|
||||
FillDigits64FixedLength(remainder, buffer, length);
|
||||
*decimal_point = *length;
|
||||
} else if (exponent >= 0) {
|
||||
// 0 <= exponent <= 11
|
||||
significand <<= exponent;
|
||||
FillDigits64(significand, buffer, length);
|
||||
*decimal_point = *length;
|
||||
} else if (exponent > -kDoubleSignificandSize) {
|
||||
// We have to cut the number.
|
||||
uint64_t integrals = significand >> -exponent;
|
||||
uint64_t fractionals = significand - (integrals << -exponent);
|
||||
if (integrals > kMaxUInt32) {
|
||||
FillDigits64(integrals, buffer, length);
|
||||
} else {
|
||||
FillDigits32(static_cast<uint32_t>(integrals), buffer, length);
|
||||
}
|
||||
*decimal_point = *length;
|
||||
FillFractionals(fractionals, exponent, fractional_count,
|
||||
buffer, length, decimal_point);
|
||||
} else if (exponent < -128) {
|
||||
// This configuration (with at most 20 digits) means that all digits must be
|
||||
// 0.
|
||||
ASSERT(fractional_count <= 20);
|
||||
buffer[0] = '\0';
|
||||
*length = 0;
|
||||
*decimal_point = -fractional_count;
|
||||
} else {
|
||||
*decimal_point = 0;
|
||||
FillFractionals(significand, exponent, fractional_count,
|
||||
buffer, length, decimal_point);
|
||||
}
|
||||
TrimZeros(buffer, length, decimal_point);
|
||||
buffer[*length] = '\0';
|
||||
if ((*length) == 0) {
|
||||
// The string is empty and the decimal_point thus has no importance. Mimic
|
||||
// Gay's dtoa and and set it to -fractional_count.
|
||||
*decimal_point = -fractional_count;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
@ -1,56 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_FIXED_DTOA_H_
|
||||
#define DOUBLE_CONVERSION_FIXED_DTOA_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion
|
||||
{
|
||||
|
||||
// Produces digits necessary to print a given number with
|
||||
// 'fractional_count' digits after the decimal point.
|
||||
// The buffer must be big enough to hold the result plus one terminating null
|
||||
// character.
|
||||
//
|
||||
// The produced digits might be too short in which case the caller has to fill
|
||||
// the gaps with '0's.
|
||||
// Example: FastFixedDtoa(0.001, 5, ...) is allowed to return buffer = "1", and
|
||||
// decimal_point = -2.
|
||||
// Halfway cases are rounded towards +/-Infinity (away from 0). The call
|
||||
// FastFixedDtoa(0.15, 2, ...) thus returns buffer = "2", decimal_point = 0.
|
||||
// The returned buffer may contain digits that would be truncated from the
|
||||
// shortest representation of the input.
|
||||
//
|
||||
// This method only works for some parameters. If it can't handle the input it
|
||||
// returns false. The output is null-terminated when the function succeeds.
|
||||
bool FastFixedDtoa(double v, int fractional_count, Vector<char> buffer, int * length, int * decimal_point);
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_FIXED_DTOA_H_
|
@ -1,194 +0,0 @@
|
||||
/* gzguts.h -- zlib internal header definitions for gz* operations
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef _LARGEFILE64_SOURCE
|
||||
# ifndef _LARGEFILE_SOURCE
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
# endif
|
||||
# ifdef _FILE_OFFSET_BITS
|
||||
# undef _FILE_OFFSET_BITS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HIDDEN
|
||||
# define ZLIB_INTERNAL __attribute__((visibility("hidden")))
|
||||
#else
|
||||
# define ZLIB_INTERNAL
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "zlib.h"
|
||||
#ifdef STDC
|
||||
# include <limits.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_SOURCE
|
||||
# define _POSIX_SOURCE
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
# if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
|
||||
# include <io.h>
|
||||
# endif
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
# define WIDECHAR
|
||||
#endif
|
||||
|
||||
#ifdef WINAPI_FAMILY
|
||||
# define open _open
|
||||
# define read _read
|
||||
# define write _write
|
||||
# define close _close
|
||||
#endif
|
||||
|
||||
#ifdef NO_DEFLATE /* for compatibility with old definition */
|
||||
# define NO_GZCOMPRESS
|
||||
#endif
|
||||
|
||||
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
# ifdef __TURBOC__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef WIN32
|
||||
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
|
||||
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __SASC
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef VMS
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __OS400__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __MVS__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* unlike snprintf (which is required in C99), _snprintf does not guarantee
|
||||
null termination of the result -- however this is only used in gzlib.c where
|
||||
the result is assured to fit in the space provided */
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
/* since "static" is used to mean two completely different things in C, we
|
||||
define "local" for the non-static meaning of "static", for readability
|
||||
(compile with -Dlocal if your debugger can't find static symbols) */
|
||||
|
||||
/* gz* functions always use library allocation functions */
|
||||
#ifndef STDC
|
||||
extern voidp malloc OF((uInt size));
|
||||
extern void free OF((voidpf ptr));
|
||||
#endif
|
||||
|
||||
/* get errno and strerror definition */
|
||||
#if defined UNDER_CE
|
||||
# include <windows.h>
|
||||
# define zstrerror() gz_strwinerror((DWORD)GetLastError())
|
||||
#else
|
||||
# ifndef NO_STRERROR
|
||||
# include <errno.h>
|
||||
# define zstrerror() strerror(errno)
|
||||
# else
|
||||
# define zstrerror() "stdio error (consult errno)"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* provide prototypes for these when building zlib without LFS */
|
||||
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE - 0 == 0
|
||||
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
|
||||
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
|
||||
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
|
||||
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
|
||||
#endif
|
||||
|
||||
/* default memLevel */
|
||||
#if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
#else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
#endif
|
||||
|
||||
/* default i/o buffer size -- double this for output when reading (this and
|
||||
twice this must be able to fit in an unsigned type) */
|
||||
#define GZBUFSIZE 8192
|
||||
|
||||
/* gzip modes, also provide a little integrity check on the passed structure */
|
||||
#define GZ_NONE 0
|
||||
#define GZ_READ 7247
|
||||
#define GZ_WRITE 31153
|
||||
#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
|
||||
|
||||
/* values for gz_state how */
|
||||
#define LOOK 0 /* look for a gzip header */
|
||||
#define COPY 1 /* copy input directly */
|
||||
#define GZIP 2 /* decompress a gzip stream */
|
||||
|
||||
/* internal gzip file state data structure */
|
||||
typedef struct
|
||||
{
|
||||
/* exposed contents for gzgetc() macro */
|
||||
struct gzFile_s x; /* "x" for exposed */
|
||||
/* x.have: number of bytes available at x.next */
|
||||
/* x.next: next output data to deliver or write */
|
||||
/* x.pos: current position in uncompressed data */
|
||||
/* used for both reading and writing */
|
||||
int mode; /* see gzip modes above */
|
||||
int fd; /* file descriptor */
|
||||
char * path; /* path or fd for error messages */
|
||||
unsigned size; /* buffer size, zero if not allocated yet */
|
||||
unsigned want; /* requested buffer size, default is GZBUFSIZE */
|
||||
unsigned char * in; /* input buffer (double-sized when writing) */
|
||||
unsigned char * out; /* output buffer (double-sized when reading) */
|
||||
int direct; /* 0 if processing gzip, 1 if transparent */
|
||||
/* just for reading */
|
||||
int how; /* 0: get header, 1: copy, 2: decompress */
|
||||
z_off64_t start; /* where the gzip data started, for rewinding */
|
||||
int eof; /* true if end of input file reached */
|
||||
int past; /* true if read requested past end */
|
||||
/* just for writing */
|
||||
int level; /* compression level */
|
||||
int strategy; /* compression strategy */
|
||||
/* seek request */
|
||||
z_off64_t skip; /* amount to skip (already rewound if backwards) */
|
||||
int seek; /* true if seek request pending */
|
||||
/* error information */
|
||||
int err; /* error code */
|
||||
char * msg; /* error message */
|
||||
/* zlib inflate or deflate stream */
|
||||
z_stream strm; /* stream structure in-place (not a pointer) */
|
||||
} gz_state;
|
||||
typedef gz_state FAR * gz_statep;
|
||||
|
||||
/* shared functions */
|
||||
void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
|
||||
#if defined UNDER_CE
|
||||
char ZLIB_INTERNAL * gz_strwinerror OF((DWORD error));
|
||||
#endif
|
||||
|
||||
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
|
||||
value -- needed when comparing unsigned to z_off64_t, which is signed
|
||||
(possible z_off64_t types off_t, off64_t, and long are all signed) */
|
||||
#ifdef INT_MAX
|
||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
|
||||
#else
|
||||
unsigned ZLIB_INTERNAL gz_intmax OF((void));
|
||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
|
||||
#endif
|
@ -1,458 +0,0 @@
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_DOUBLE_H_
|
||||
#define DOUBLE_CONVERSION_DOUBLE_H_
|
||||
|
||||
#include "diy-fp.h"
|
||||
|
||||
namespace double_conversion
|
||||
{
|
||||
|
||||
// We assume that doubles and uint64_t have the same endianness.
|
||||
static uint64_t double_to_uint64(double d)
|
||||
{
|
||||
return BitCast<uint64_t>(d);
|
||||
}
|
||||
static double uint64_to_double(uint64_t d64)
|
||||
{
|
||||
return BitCast<double>(d64);
|
||||
}
|
||||
static uint32_t float_to_uint32(float f)
|
||||
{
|
||||
return BitCast<uint32_t>(f);
|
||||
}
|
||||
static float uint32_to_float(uint32_t d32)
|
||||
{
|
||||
return BitCast<float>(d32);
|
||||
}
|
||||
|
||||
// Helper functions for doubles.
|
||||
class Double
|
||||
{
|
||||
public:
|
||||
static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000);
|
||||
static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000);
|
||||
static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
|
||||
static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000);
|
||||
static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
|
||||
static const int kSignificandSize = 53;
|
||||
|
||||
Double() : d64_(0) { }
|
||||
explicit Double(double d) : d64_(double_to_uint64(d)) { }
|
||||
explicit Double(uint64_t d64) : d64_(d64) { }
|
||||
explicit Double(DiyFp diy_fp) : d64_(DiyFpToUint64(diy_fp)) { }
|
||||
|
||||
// The value encoded by this Double must be greater or equal to +0.0.
|
||||
// It must not be special (infinity, or NaN).
|
||||
DiyFp AsDiyFp() const
|
||||
{
|
||||
ASSERT(Sign() > 0);
|
||||
ASSERT(!IsSpecial());
|
||||
return DiyFp(Significand(), Exponent());
|
||||
}
|
||||
|
||||
// The value encoded by this Double must be strictly greater than 0.
|
||||
DiyFp AsNormalizedDiyFp() const
|
||||
{
|
||||
ASSERT(value() > 0.0);
|
||||
uint64_t f = Significand();
|
||||
int e = Exponent();
|
||||
|
||||
// The current double could be a denormal.
|
||||
while ((f & kHiddenBit) == 0)
|
||||
{
|
||||
f <<= 1;
|
||||
e--;
|
||||
}
|
||||
// Do the final shifts in one go.
|
||||
f <<= DiyFp::kSignificandSize - kSignificandSize;
|
||||
e -= DiyFp::kSignificandSize - kSignificandSize;
|
||||
return DiyFp(f, e);
|
||||
}
|
||||
|
||||
// Returns the double's bit as uint64.
|
||||
uint64_t AsUint64() const { return d64_; }
|
||||
|
||||
// Returns the next greater double. Returns +infinity on input +infinity.
|
||||
double NextDouble() const
|
||||
{
|
||||
if (d64_ == kInfinity)
|
||||
return Double(kInfinity).value();
|
||||
if (Sign() < 0 && Significand() == 0)
|
||||
{
|
||||
// -0.0
|
||||
return 0.0;
|
||||
}
|
||||
if (Sign() < 0)
|
||||
{
|
||||
return Double(d64_ - 1).value();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Double(d64_ + 1).value();
|
||||
}
|
||||
}
|
||||
|
||||
double PreviousDouble() const
|
||||
{
|
||||
if (d64_ == (kInfinity | kSignMask))
|
||||
return -Double::Infinity();
|
||||
if (Sign() < 0)
|
||||
{
|
||||
return Double(d64_ + 1).value();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Significand() == 0)
|
||||
return -0.0;
|
||||
return Double(d64_ - 1).value();
|
||||
}
|
||||
}
|
||||
|
||||
int Exponent() const
|
||||
{
|
||||
if (IsDenormal())
|
||||
return kDenormalExponent;
|
||||
|
||||
uint64_t d64 = AsUint64();
|
||||
int biased_e = static_cast<int>((d64 & kExponentMask) >> kPhysicalSignificandSize);
|
||||
return biased_e - kExponentBias;
|
||||
}
|
||||
|
||||
uint64_t Significand() const
|
||||
{
|
||||
uint64_t d64 = AsUint64();
|
||||
uint64_t significand = d64 & kSignificandMask;
|
||||
if (!IsDenormal())
|
||||
{
|
||||
return significand + kHiddenBit;
|
||||
}
|
||||
else
|
||||
{
|
||||
return significand;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the double is a denormal.
|
||||
bool IsDenormal() const
|
||||
{
|
||||
uint64_t d64 = AsUint64();
|
||||
return (d64 & kExponentMask) == 0;
|
||||
}
|
||||
|
||||
// We consider denormals not to be special.
|
||||
// Hence only Infinity and NaN are special.
|
||||
bool IsSpecial() const
|
||||
{
|
||||
uint64_t d64 = AsUint64();
|
||||
return (d64 & kExponentMask) == kExponentMask;
|
||||
}
|
||||
|
||||
bool IsNan() const
|
||||
{
|
||||
uint64_t d64 = AsUint64();
|
||||
return ((d64 & kExponentMask) == kExponentMask) && ((d64 & kSignificandMask) != 0);
|
||||
}
|
||||
|
||||
bool IsInfinite() const
|
||||
{
|
||||
uint64_t d64 = AsUint64();
|
||||
return ((d64 & kExponentMask) == kExponentMask) && ((d64 & kSignificandMask) == 0);
|
||||
}
|
||||
|
||||
int Sign() const
|
||||
{
|
||||
uint64_t d64 = AsUint64();
|
||||
return (d64 & kSignMask) == 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
// Precondition: the value encoded by this Double must be greater or equal
|
||||
// than +0.0.
|
||||
DiyFp UpperBoundary() const
|
||||
{
|
||||
ASSERT(Sign() > 0);
|
||||
return DiyFp(Significand() * 2 + 1, Exponent() - 1);
|
||||
}
|
||||
|
||||
// Computes the two boundaries of this.
|
||||
// The bigger boundary (m_plus) is normalized. The lower boundary has the same
|
||||
// exponent as m_plus.
|
||||
// Precondition: the value encoded by this Double must be greater than 0.
|
||||
void NormalizedBoundaries(DiyFp * out_m_minus, DiyFp * out_m_plus) const
|
||||
{
|
||||
ASSERT(value() > 0.0);
|
||||
DiyFp v = this->AsDiyFp();
|
||||
DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
|
||||
DiyFp m_minus;
|
||||
if (LowerBoundaryIsCloser())
|
||||
{
|
||||
m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
|
||||
}
|
||||
m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
|
||||
m_minus.set_e(m_plus.e());
|
||||
*out_m_plus = m_plus;
|
||||
*out_m_minus = m_minus;
|
||||
}
|
||||
|
||||
bool LowerBoundaryIsCloser() const
|
||||
{
|
||||
// The boundary is closer if the significand is of the form f == 2^p-1 then
|
||||
// the lower boundary is closer.
|
||||
// Think of v = 1000e10 and v- = 9999e9.
|
||||
// Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
|
||||
// at a distance of 1e8.
|
||||
// The only exception is for the smallest normal: the largest denormal is
|
||||
// at the same distance as its successor.
|
||||
// Note: denormals have the same exponent as the smallest normals.
|
||||
bool physical_significand_is_zero = ((AsUint64() & kSignificandMask) == 0);
|
||||
return physical_significand_is_zero && (Exponent() != kDenormalExponent);
|
||||
}
|
||||
|
||||
double value() const { return uint64_to_double(d64_); }
|
||||
|
||||
// Returns the significand size for a given order of magnitude.
|
||||
// If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude.
|
||||
// This function returns the number of significant binary digits v will have
|
||||
// once it's encoded into a double. In almost all cases this is equal to
|
||||
// kSignificandSize. The only exceptions are denormals. They start with
|
||||
// leading zeroes and their effective significand-size is hence smaller.
|
||||
static int SignificandSizeForOrderOfMagnitude(int order)
|
||||
{
|
||||
if (order >= (kDenormalExponent + kSignificandSize))
|
||||
{
|
||||
return kSignificandSize;
|
||||
}
|
||||
if (order <= kDenormalExponent)
|
||||
return 0;
|
||||
return order - kDenormalExponent;
|
||||
}
|
||||
|
||||
static double Infinity() { return Double(kInfinity).value(); }
|
||||
|
||||
static double NaN() { return Double(kNaN).value(); }
|
||||
|
||||
private:
|
||||
static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
|
||||
static const int kDenormalExponent = -kExponentBias + 1;
|
||||
static const int kMaxExponent = 0x7FF - kExponentBias;
|
||||
static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000);
|
||||
static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000);
|
||||
|
||||
const uint64_t d64_;
|
||||
|
||||
static uint64_t DiyFpToUint64(DiyFp diy_fp)
|
||||
{
|
||||
uint64_t significand = diy_fp.f();
|
||||
int exponent = diy_fp.e();
|
||||
while (significand > kHiddenBit + kSignificandMask)
|
||||
{
|
||||
significand >>= 1;
|
||||
exponent++;
|
||||
}
|
||||
if (exponent >= kMaxExponent)
|
||||
{
|
||||
return kInfinity;
|
||||
}
|
||||
if (exponent < kDenormalExponent)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0)
|
||||
{
|
||||
significand <<= 1;
|
||||
exponent--;
|
||||
}
|
||||
uint64_t biased_exponent;
|
||||
if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0)
|
||||
{
|
||||
biased_exponent = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
biased_exponent = static_cast<uint64_t>(exponent + kExponentBias);
|
||||
}
|
||||
return (significand & kSignificandMask) | (biased_exponent << kPhysicalSignificandSize);
|
||||
}
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Double);
|
||||
};
|
||||
|
||||
class Single
|
||||
{
|
||||
public:
|
||||
static const uint32_t kSignMask = 0x80000000;
|
||||
static const uint32_t kExponentMask = 0x7F800000;
|
||||
static const uint32_t kSignificandMask = 0x007FFFFF;
|
||||
static const uint32_t kHiddenBit = 0x00800000;
|
||||
static const int kPhysicalSignificandSize = 23; // Excludes the hidden bit.
|
||||
static const int kSignificandSize = 24;
|
||||
|
||||
Single() : d32_(0) { }
|
||||
explicit Single(float f) : d32_(float_to_uint32(f)) { }
|
||||
explicit Single(uint32_t d32) : d32_(d32) { }
|
||||
|
||||
// The value encoded by this Single must be greater or equal to +0.0.
|
||||
// It must not be special (infinity, or NaN).
|
||||
DiyFp AsDiyFp() const
|
||||
{
|
||||
ASSERT(Sign() > 0);
|
||||
ASSERT(!IsSpecial());
|
||||
return DiyFp(Significand(), Exponent());
|
||||
}
|
||||
|
||||
// Returns the single's bit as uint64.
|
||||
uint32_t AsUint32() const { return d32_; }
|
||||
|
||||
int Exponent() const
|
||||
{
|
||||
if (IsDenormal())
|
||||
return kDenormalExponent;
|
||||
|
||||
uint32_t d32 = AsUint32();
|
||||
int biased_e = static_cast<int>((d32 & kExponentMask) >> kPhysicalSignificandSize);
|
||||
return biased_e - kExponentBias;
|
||||
}
|
||||
|
||||
uint32_t Significand() const
|
||||
{
|
||||
uint32_t d32 = AsUint32();
|
||||
uint32_t significand = d32 & kSignificandMask;
|
||||
if (!IsDenormal())
|
||||
{
|
||||
return significand + kHiddenBit;
|
||||
}
|
||||
else
|
||||
{
|
||||
return significand;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the single is a denormal.
|
||||
bool IsDenormal() const
|
||||
{
|
||||
uint32_t d32 = AsUint32();
|
||||
return (d32 & kExponentMask) == 0;
|
||||
}
|
||||
|
||||
// We consider denormals not to be special.
|
||||
// Hence only Infinity and NaN are special.
|
||||
bool IsSpecial() const
|
||||
{
|
||||
uint32_t d32 = AsUint32();
|
||||
return (d32 & kExponentMask) == kExponentMask;
|
||||
}
|
||||
|
||||
bool IsNan() const
|
||||
{
|
||||
uint32_t d32 = AsUint32();
|
||||
return ((d32 & kExponentMask) == kExponentMask) && ((d32 & kSignificandMask) != 0);
|
||||
}
|
||||
|
||||
bool IsInfinite() const
|
||||
{
|
||||
uint32_t d32 = AsUint32();
|
||||
return ((d32 & kExponentMask) == kExponentMask) && ((d32 & kSignificandMask) == 0);
|
||||
}
|
||||
|
||||
int Sign() const
|
||||
{
|
||||
uint32_t d32 = AsUint32();
|
||||
return (d32 & kSignMask) == 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
// Computes the two boundaries of this.
|
||||
// The bigger boundary (m_plus) is normalized. The lower boundary has the same
|
||||
// exponent as m_plus.
|
||||
// Precondition: the value encoded by this Single must be greater than 0.
|
||||
void NormalizedBoundaries(DiyFp * out_m_minus, DiyFp * out_m_plus) const
|
||||
{
|
||||
ASSERT(value() > 0.0);
|
||||
DiyFp v = this->AsDiyFp();
|
||||
DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
|
||||
DiyFp m_minus;
|
||||
if (LowerBoundaryIsCloser())
|
||||
{
|
||||
m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
|
||||
}
|
||||
m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
|
||||
m_minus.set_e(m_plus.e());
|
||||
*out_m_plus = m_plus;
|
||||
*out_m_minus = m_minus;
|
||||
}
|
||||
|
||||
// Precondition: the value encoded by this Single must be greater or equal
|
||||
// than +0.0.
|
||||
DiyFp UpperBoundary() const
|
||||
{
|
||||
ASSERT(Sign() > 0);
|
||||
return DiyFp(Significand() * 2 + 1, Exponent() - 1);
|
||||
}
|
||||
|
||||
bool LowerBoundaryIsCloser() const
|
||||
{
|
||||
// The boundary is closer if the significand is of the form f == 2^p-1 then
|
||||
// the lower boundary is closer.
|
||||
// Think of v = 1000e10 and v- = 9999e9.
|
||||
// Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
|
||||
// at a distance of 1e8.
|
||||
// The only exception is for the smallest normal: the largest denormal is
|
||||
// at the same distance as its successor.
|
||||
// Note: denormals have the same exponent as the smallest normals.
|
||||
bool physical_significand_is_zero = ((AsUint32() & kSignificandMask) == 0);
|
||||
return physical_significand_is_zero && (Exponent() != kDenormalExponent);
|
||||
}
|
||||
|
||||
float value() const { return uint32_to_float(d32_); }
|
||||
|
||||
static float Infinity() { return Single(kInfinity).value(); }
|
||||
|
||||
static float NaN() { return Single(kNaN).value(); }
|
||||
|
||||
private:
|
||||
static const int kExponentBias = 0x7F + kPhysicalSignificandSize;
|
||||
static const int kDenormalExponent = -kExponentBias + 1;
|
||||
static const int kMaxExponent = 0xFF - kExponentBias;
|
||||
static const uint32_t kInfinity = 0x7F800000;
|
||||
static const uint32_t kNaN = 0x7FC00000;
|
||||
|
||||
const uint32_t d32_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Single);
|
||||
};
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_DOUBLE_H_
|
@ -1,640 +0,0 @@
|
||||
/* infback.c -- inflate using a call-back interface
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/*
|
||||
This code is largely copied from inflate.c. Normally either infback.o or
|
||||
inflate.o would be linked into an application--not both. The interface
|
||||
with inffast.c is retained so that optimized assembler-coded versions of
|
||||
inflate_fast() can be used with either inflate.c or infback.c.
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
/* function prototypes */
|
||||
local void fixedtables OF((struct inflate_state FAR *state));
|
||||
|
||||
/*
|
||||
strm provides memory allocation functions in zalloc and zfree, or
|
||||
Z_NULL to use the library memory allocation functions.
|
||||
|
||||
windowBits is in the range 8..15, and window is a user-supplied
|
||||
window and output buffer that is 2**windowBits bytes.
|
||||
*/
|
||||
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
|
||||
z_streamp strm;
|
||||
int windowBits;
|
||||
unsigned char FAR *window;
|
||||
const char *version;
|
||||
int stream_size;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
|
||||
stream_size != (int)(sizeof(z_stream)))
|
||||
return Z_VERSION_ERROR;
|
||||
if (strm == Z_NULL || window == Z_NULL ||
|
||||
windowBits < 8 || windowBits > 15)
|
||||
return Z_STREAM_ERROR;
|
||||
strm->msg = Z_NULL; /* in case we return an error */
|
||||
if (strm->zalloc == (alloc_func)0) {
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zalloc = zcalloc;
|
||||
strm->opaque = (voidpf)0;
|
||||
#endif
|
||||
}
|
||||
if (strm->zfree == (free_func)0)
|
||||
#ifdef Z_SOLO
|
||||
return Z_STREAM_ERROR;
|
||||
#else
|
||||
strm->zfree = zcfree;
|
||||
#endif
|
||||
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
|
||||
sizeof(struct inflate_state));
|
||||
if (state == Z_NULL) return Z_MEM_ERROR;
|
||||
Tracev((stderr, "inflate: allocated\n"));
|
||||
strm->state = (struct internal_state FAR *)state;
|
||||
state->dmax = 32768U;
|
||||
state->wbits = (uInt)windowBits;
|
||||
state->wsize = 1U << windowBits;
|
||||
state->window = window;
|
||||
state->wnext = 0;
|
||||
state->whave = 0;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Return state with length and distance decoding tables and index sizes set to
|
||||
fixed code decoding. Normally this returns fixed tables from inffixed.h.
|
||||
If BUILDFIXED is defined, then instead this routine builds the tables the
|
||||
first time it's called, and returns those tables the first time and
|
||||
thereafter. This reduces the size of the code by about 2K bytes, in
|
||||
exchange for a little execution time. However, BUILDFIXED should not be
|
||||
used for threaded applications, since the rewriting of the tables and virgin
|
||||
may not be thread-safe.
|
||||
*/
|
||||
local void fixedtables(state)
|
||||
struct inflate_state FAR *state;
|
||||
{
|
||||
#ifdef BUILDFIXED
|
||||
static int virgin = 1;
|
||||
static code *lenfix, *distfix;
|
||||
static code fixed[544];
|
||||
|
||||
/* build fixed huffman tables if first call (may not be thread safe) */
|
||||
if (virgin) {
|
||||
unsigned sym, bits;
|
||||
static code *next;
|
||||
|
||||
/* literal/length table */
|
||||
sym = 0;
|
||||
while (sym < 144) state->lens[sym++] = 8;
|
||||
while (sym < 256) state->lens[sym++] = 9;
|
||||
while (sym < 280) state->lens[sym++] = 7;
|
||||
while (sym < 288) state->lens[sym++] = 8;
|
||||
next = fixed;
|
||||
lenfix = next;
|
||||
bits = 9;
|
||||
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
|
||||
|
||||
/* distance table */
|
||||
sym = 0;
|
||||
while (sym < 32) state->lens[sym++] = 5;
|
||||
distfix = next;
|
||||
bits = 5;
|
||||
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
|
||||
|
||||
/* do this just once */
|
||||
virgin = 0;
|
||||
}
|
||||
#else /* !BUILDFIXED */
|
||||
# include "inffixed.h"
|
||||
#endif /* BUILDFIXED */
|
||||
state->lencode = lenfix;
|
||||
state->lenbits = 9;
|
||||
state->distcode = distfix;
|
||||
state->distbits = 5;
|
||||
}
|
||||
|
||||
/* Macros for inflateBack(): */
|
||||
|
||||
/* Load returned state from inflate_fast() */
|
||||
#define LOAD() \
|
||||
do { \
|
||||
put = strm->next_out; \
|
||||
left = strm->avail_out; \
|
||||
next = strm->next_in; \
|
||||
have = strm->avail_in; \
|
||||
hold = state->hold; \
|
||||
bits = state->bits; \
|
||||
} while (0)
|
||||
|
||||
/* Set state from registers for inflate_fast() */
|
||||
#define RESTORE() \
|
||||
do { \
|
||||
strm->next_out = put; \
|
||||
strm->avail_out = left; \
|
||||
strm->next_in = next; \
|
||||
strm->avail_in = have; \
|
||||
state->hold = hold; \
|
||||
state->bits = bits; \
|
||||
} while (0)
|
||||
|
||||
/* Clear the input bit accumulator */
|
||||
#define INITBITS() \
|
||||
do { \
|
||||
hold = 0; \
|
||||
bits = 0; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some input is available. If input is requested, but denied,
|
||||
then return a Z_BUF_ERROR from inflateBack(). */
|
||||
#define PULL() \
|
||||
do { \
|
||||
if (have == 0) { \
|
||||
have = in(in_desc, &next); \
|
||||
if (have == 0) { \
|
||||
next = Z_NULL; \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Get a byte of input into the bit accumulator, or return from inflateBack()
|
||||
with an error if there is no input available. */
|
||||
#define PULLBYTE() \
|
||||
do { \
|
||||
PULL(); \
|
||||
have--; \
|
||||
hold += (unsigned long)(*next++) << bits; \
|
||||
bits += 8; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that there are at least n bits in the bit accumulator. If there is
|
||||
not enough available input to do that, then return from inflateBack() with
|
||||
an error. */
|
||||
#define NEEDBITS(n) \
|
||||
do { \
|
||||
while (bits < (unsigned)(n)) \
|
||||
PULLBYTE(); \
|
||||
} while (0)
|
||||
|
||||
/* Return the low n bits of the bit accumulator (n < 16) */
|
||||
#define BITS(n) \
|
||||
((unsigned)hold & ((1U << (n)) - 1))
|
||||
|
||||
/* Remove n bits from the bit accumulator */
|
||||
#define DROPBITS(n) \
|
||||
do { \
|
||||
hold >>= (n); \
|
||||
bits -= (unsigned)(n); \
|
||||
} while (0)
|
||||
|
||||
/* Remove zero to seven bits as needed to go to a byte boundary */
|
||||
#define BYTEBITS() \
|
||||
do { \
|
||||
hold >>= bits & 7; \
|
||||
bits -= bits & 7; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some output space is available, by writing out the window
|
||||
if it's full. If the write fails, return from inflateBack() with a
|
||||
Z_BUF_ERROR. */
|
||||
#define ROOM() \
|
||||
do { \
|
||||
if (left == 0) { \
|
||||
put = state->window; \
|
||||
left = state->wsize; \
|
||||
state->whave = left; \
|
||||
if (out(out_desc, put, left)) { \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
strm provides the memory allocation functions and window buffer on input,
|
||||
and provides information on the unused input on return. For Z_DATA_ERROR
|
||||
returns, strm will also provide an error message.
|
||||
|
||||
in() and out() are the call-back input and output functions. When
|
||||
inflateBack() needs more input, it calls in(). When inflateBack() has
|
||||
filled the window with output, or when it completes with data in the
|
||||
window, it calls out() to write out the data. The application must not
|
||||
change the provided input until in() is called again or inflateBack()
|
||||
returns. The application must not change the window/output buffer until
|
||||
inflateBack() returns.
|
||||
|
||||
in() and out() are called with a descriptor parameter provided in the
|
||||
inflateBack() call. This parameter can be a structure that provides the
|
||||
information required to do the read or write, as well as accumulated
|
||||
information on the input and output such as totals and check values.
|
||||
|
||||
in() should return zero on failure. out() should return non-zero on
|
||||
failure. If either in() or out() fails, than inflateBack() returns a
|
||||
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
|
||||
was in() or out() that caused in the error. Otherwise, inflateBack()
|
||||
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
|
||||
error, or Z_MEM_ERROR if it could not allocate memory for the state.
|
||||
inflateBack() can also return Z_STREAM_ERROR if the input parameters
|
||||
are not correct, i.e. strm is Z_NULL or the state was not initialized.
|
||||
*/
|
||||
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
|
||||
z_streamp strm;
|
||||
in_func in;
|
||||
void FAR *in_desc;
|
||||
out_func out;
|
||||
void FAR *out_desc;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
z_const unsigned char FAR *next; /* next input */
|
||||
unsigned char FAR *put; /* next output */
|
||||
unsigned have, left; /* available input and output */
|
||||
unsigned long hold; /* bit buffer */
|
||||
unsigned bits; /* bits in bit buffer */
|
||||
unsigned copy; /* number of stored or match bytes to copy */
|
||||
unsigned char FAR *from; /* where to copy match bytes from */
|
||||
code here; /* current decoding table entry */
|
||||
code last; /* parent table entry */
|
||||
unsigned len; /* length to copy for repeats, bits to drop */
|
||||
int ret; /* return code */
|
||||
static const unsigned short order[19] = /* permutation of code lengths */
|
||||
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
|
||||
/* Check that the strm exists and that the state was initialized */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
|
||||
/* Reset the state */
|
||||
strm->msg = Z_NULL;
|
||||
state->mode = TYPE;
|
||||
state->last = 0;
|
||||
state->whave = 0;
|
||||
next = strm->next_in;
|
||||
have = next != Z_NULL ? strm->avail_in : 0;
|
||||
hold = 0;
|
||||
bits = 0;
|
||||
put = state->window;
|
||||
left = state->wsize;
|
||||
|
||||
/* Inflate until end of block marked as last */
|
||||
for (;;)
|
||||
switch (state->mode) {
|
||||
case TYPE:
|
||||
/* determine and dispatch block type */
|
||||
if (state->last) {
|
||||
BYTEBITS();
|
||||
state->mode = DONE;
|
||||
break;
|
||||
}
|
||||
NEEDBITS(3);
|
||||
state->last = BITS(1);
|
||||
DROPBITS(1);
|
||||
switch (BITS(2)) {
|
||||
case 0: /* stored block */
|
||||
Tracev((stderr, "inflate: stored block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = STORED;
|
||||
break;
|
||||
case 1: /* fixed block */
|
||||
fixedtables(state);
|
||||
Tracev((stderr, "inflate: fixed codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = LEN; /* decode codes */
|
||||
break;
|
||||
case 2: /* dynamic block */
|
||||
Tracev((stderr, "inflate: dynamic codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = TABLE;
|
||||
break;
|
||||
case 3:
|
||||
strm->msg = (char *)"invalid block type";
|
||||
state->mode = BAD;
|
||||
}
|
||||
DROPBITS(2);
|
||||
break;
|
||||
|
||||
case STORED:
|
||||
/* get and verify stored block length */
|
||||
BYTEBITS(); /* go to byte boundary */
|
||||
NEEDBITS(32);
|
||||
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
|
||||
strm->msg = (char *)"invalid stored block lengths";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->length = (unsigned)hold & 0xffff;
|
||||
Tracev((stderr, "inflate: stored length %u\n",
|
||||
state->length));
|
||||
INITBITS();
|
||||
|
||||
/* copy stored block from input to output */
|
||||
while (state->length != 0) {
|
||||
copy = state->length;
|
||||
PULL();
|
||||
ROOM();
|
||||
if (copy > have) copy = have;
|
||||
if (copy > left) copy = left;
|
||||
zmemcpy(put, next, copy);
|
||||
have -= copy;
|
||||
next += copy;
|
||||
left -= copy;
|
||||
put += copy;
|
||||
state->length -= copy;
|
||||
}
|
||||
Tracev((stderr, "inflate: stored end\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
|
||||
case TABLE:
|
||||
/* get dynamic table entries descriptor */
|
||||
NEEDBITS(14);
|
||||
state->nlen = BITS(5) + 257;
|
||||
DROPBITS(5);
|
||||
state->ndist = BITS(5) + 1;
|
||||
DROPBITS(5);
|
||||
state->ncode = BITS(4) + 4;
|
||||
DROPBITS(4);
|
||||
#ifndef PKZIP_BUG_WORKAROUND
|
||||
if (state->nlen > 286 || state->ndist > 30) {
|
||||
strm->msg = (char *)"too many length or distance symbols";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
Tracev((stderr, "inflate: table sizes ok\n"));
|
||||
|
||||
/* get code length code lengths (not a typo) */
|
||||
state->have = 0;
|
||||
while (state->have < state->ncode) {
|
||||
NEEDBITS(3);
|
||||
state->lens[order[state->have++]] = (unsigned short)BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
while (state->have < 19)
|
||||
state->lens[order[state->have++]] = 0;
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 7;
|
||||
ret = inflate_table(CODES, state->lens, 19, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid code lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: code lengths ok\n"));
|
||||
|
||||
/* get length and distance code code lengths */
|
||||
state->have = 0;
|
||||
while (state->have < state->nlen + state->ndist) {
|
||||
for (;;) {
|
||||
here = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (here.val < 16) {
|
||||
DROPBITS(here.bits);
|
||||
state->lens[state->have++] = here.val;
|
||||
}
|
||||
else {
|
||||
if (here.val == 16) {
|
||||
NEEDBITS(here.bits + 2);
|
||||
DROPBITS(here.bits);
|
||||
if (state->have == 0) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
len = (unsigned)(state->lens[state->have - 1]);
|
||||
copy = 3 + BITS(2);
|
||||
DROPBITS(2);
|
||||
}
|
||||
else if (here.val == 17) {
|
||||
NEEDBITS(here.bits + 3);
|
||||
DROPBITS(here.bits);
|
||||
len = 0;
|
||||
copy = 3 + BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
else {
|
||||
NEEDBITS(here.bits + 7);
|
||||
DROPBITS(here.bits);
|
||||
len = 0;
|
||||
copy = 11 + BITS(7);
|
||||
DROPBITS(7);
|
||||
}
|
||||
if (state->have + copy > state->nlen + state->ndist) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
while (copy--)
|
||||
state->lens[state->have++] = (unsigned short)len;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle error breaks in while */
|
||||
if (state->mode == BAD) break;
|
||||
|
||||
/* check for end-of-block code (better have one) */
|
||||
if (state->lens[256] == 0) {
|
||||
strm->msg = (char *)"invalid code -- missing end-of-block";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* build code tables -- note: do not change the lenbits or distbits
|
||||
values here (9 and 6) without reading the comments in inftrees.h
|
||||
concerning the ENOUGH constants, which depend on those values */
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 9;
|
||||
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid literal/lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->distcode = (code const FAR *)(state->next);
|
||||
state->distbits = 6;
|
||||
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
|
||||
&(state->next), &(state->distbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid distances set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: codes ok\n"));
|
||||
state->mode = LEN;
|
||||
|
||||
case LEN:
|
||||
/* use inflate_fast() if we have enough input and output */
|
||||
if (have >= 6 && left >= 258) {
|
||||
RESTORE();
|
||||
if (state->whave < state->wsize)
|
||||
state->whave = state->wsize - left;
|
||||
inflate_fast(strm, state->wsize);
|
||||
LOAD();
|
||||
break;
|
||||
}
|
||||
|
||||
/* get a literal, length, or end-of-block code */
|
||||
for (;;) {
|
||||
here = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (here.op && (here.op & 0xf0) == 0) {
|
||||
last = here;
|
||||
for (;;) {
|
||||
here = state->lencode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(here.bits);
|
||||
state->length = (unsigned)here.val;
|
||||
|
||||
/* process literal */
|
||||
if (here.op == 0) {
|
||||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", here.val));
|
||||
ROOM();
|
||||
*put++ = (unsigned char)(state->length);
|
||||
left--;
|
||||
state->mode = LEN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* process end of block */
|
||||
if (here.op & 32) {
|
||||
Tracevv((stderr, "inflate: end of block\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* invalid code */
|
||||
if (here.op & 64) {
|
||||
strm->msg = (char *)"invalid literal/length code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* length code -- get extra bits, if any */
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->length += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", state->length));
|
||||
|
||||
/* get distance code */
|
||||
for (;;) {
|
||||
here = state->distcode[BITS(state->distbits)];
|
||||
if ((unsigned)(here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if ((here.op & 0xf0) == 0) {
|
||||
last = here;
|
||||
for (;;) {
|
||||
here = state->distcode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + here.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(here.bits);
|
||||
if (here.op & 64) {
|
||||
strm->msg = (char *)"invalid distance code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->offset = (unsigned)here.val;
|
||||
|
||||
/* get distance extra bits, if any */
|
||||
state->extra = (unsigned)(here.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->offset += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
if (state->offset > state->wsize - (state->whave < state->wsize ?
|
||||
left : 0)) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracevv((stderr, "inflate: distance %u\n", state->offset));
|
||||
|
||||
/* copy match from window to output */
|
||||
do {
|
||||
ROOM();
|
||||
copy = state->wsize - state->offset;
|
||||
if (copy < left) {
|
||||
from = put + copy;
|
||||
copy = left - copy;
|
||||
}
|
||||
else {
|
||||
from = put - state->offset;
|
||||
copy = left;
|
||||
}
|
||||
if (copy > state->length) copy = state->length;
|
||||
state->length -= copy;
|
||||
left -= copy;
|
||||
do {
|
||||
*put++ = *from++;
|
||||
} while (--copy);
|
||||
} while (state->length != 0);
|
||||
break;
|
||||
|
||||
case DONE:
|
||||
/* inflate stream terminated properly -- write leftover output */
|
||||
ret = Z_STREAM_END;
|
||||
if (left < state->wsize) {
|
||||
if (out(out_desc, state->window, state->wsize - left))
|
||||
ret = Z_BUF_ERROR;
|
||||
}
|
||||
goto inf_leave;
|
||||
|
||||
case BAD:
|
||||
ret = Z_DATA_ERROR;
|
||||
goto inf_leave;
|
||||
|
||||
default: /* can't happen, but makes compilers happy */
|
||||
ret = Z_STREAM_ERROR;
|
||||
goto inf_leave;
|
||||
}
|
||||
|
||||
/* Return unused input */
|
||||
inf_leave:
|
||||
strm->next_in = next;
|
||||
strm->avail_in = have;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateBackEnd(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
|
||||
return Z_STREAM_ERROR;
|
||||
ZFREE(strm, strm->state);
|
||||
strm->state = Z_NULL;
|
||||
Tracev((stderr, "inflate: end\n"));
|
||||
return Z_OK;
|
||||
}
|
@ -1,323 +0,0 @@
|
||||
/* inffast.c -- fast decoding
|
||||
* Copyright (C) 1995-2017 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
#ifdef ASMINF
|
||||
# pragma message("Assembler code may have bugs -- use at your own risk")
|
||||
#else
|
||||
|
||||
/*
|
||||
Decode literal, length, and distance codes and write out the resulting
|
||||
literal and match bytes until either not enough input or output is
|
||||
available, an end-of-block is encountered, or a data error is encountered.
|
||||
When large enough input and output buffers are supplied to inflate(), for
|
||||
example, a 16K input buffer and a 64K output buffer, more than 95% of the
|
||||
inflate execution time is spent in this routine.
|
||||
|
||||
Entry assumptions:
|
||||
|
||||
state->mode == LEN
|
||||
strm->avail_in >= 6
|
||||
strm->avail_out >= 258
|
||||
start >= strm->avail_out
|
||||
state->bits < 8
|
||||
|
||||
On return, state->mode is one of:
|
||||
|
||||
LEN -- ran out of enough output space or enough available input
|
||||
TYPE -- reached end of block code, inflate() to interpret next block
|
||||
BAD -- error in block data
|
||||
|
||||
Notes:
|
||||
|
||||
- The maximum input bits used by a length/distance pair is 15 bits for the
|
||||
length code, 5 bits for the length extra, 15 bits for the distance code,
|
||||
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
|
||||
Therefore if strm->avail_in >= 6, then there is enough input to avoid
|
||||
checking for available input while decoding.
|
||||
|
||||
- The maximum bytes that a single length/distance pair can output is 258
|
||||
bytes, which is the maximum length that can be coded. inflate_fast()
|
||||
requires strm->avail_out >= 258 for each loop to avoid checking for
|
||||
output space.
|
||||
*/
|
||||
void ZLIB_INTERNAL inflate_fast(strm, start)
|
||||
z_streamp strm;
|
||||
unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
z_const unsigned char FAR *in; /* local strm->next_in */
|
||||
z_const unsigned char FAR *last; /* have enough input while in < last */
|
||||
unsigned char FAR *out; /* local strm->next_out */
|
||||
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
|
||||
unsigned char FAR *end; /* while out < end, enough space available */
|
||||
#ifdef INFLATE_STRICT
|
||||
unsigned dmax; /* maximum distance from zlib header */
|
||||
#endif
|
||||
unsigned wsize; /* window size or zero if not using window */
|
||||
unsigned whave; /* valid bytes in the window */
|
||||
unsigned wnext; /* window write index */
|
||||
unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
|
||||
unsigned long hold; /* local strm->hold */
|
||||
unsigned bits; /* local strm->bits */
|
||||
code const FAR *lcode; /* local strm->lencode */
|
||||
code const FAR *dcode; /* local strm->distcode */
|
||||
unsigned lmask; /* mask for first level of length codes */
|
||||
unsigned dmask; /* mask for first level of distance codes */
|
||||
code here; /* retrieved table entry */
|
||||
unsigned op; /* code bits, operation, extra bits, or */
|
||||
/* window position, window bytes to copy */
|
||||
unsigned len; /* match length, unused bytes */
|
||||
unsigned dist; /* match distance */
|
||||
unsigned char FAR *from; /* where to copy match from */
|
||||
|
||||
/* copy state to local variables */
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
in = strm->next_in;
|
||||
last = in + (strm->avail_in - 5);
|
||||
out = strm->next_out;
|
||||
beg = out - (start - strm->avail_out);
|
||||
end = out + (strm->avail_out - 257);
|
||||
#ifdef INFLATE_STRICT
|
||||
dmax = state->dmax;
|
||||
#endif
|
||||
wsize = state->wsize;
|
||||
whave = state->whave;
|
||||
wnext = state->wnext;
|
||||
window = state->window;
|
||||
hold = state->hold;
|
||||
bits = state->bits;
|
||||
lcode = state->lencode;
|
||||
dcode = state->distcode;
|
||||
lmask = (1U << state->lenbits) - 1;
|
||||
dmask = (1U << state->distbits) - 1;
|
||||
|
||||
/* decode literals and length/distances until end-of-block or not enough
|
||||
input data or output space */
|
||||
do {
|
||||
if (bits < 15) {
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
here = lcode[hold & lmask];
|
||||
dolen:
|
||||
op = (unsigned)(here.bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(here.op);
|
||||
if (op == 0) { /* literal */
|
||||
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", here.val));
|
||||
*out++ = (unsigned char)(here.val);
|
||||
}
|
||||
else if (op & 16) { /* length base */
|
||||
len = (unsigned)(here.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (op) {
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
len += (unsigned)hold & ((1U << op) - 1);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", len));
|
||||
if (bits < 15) {
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
here = dcode[hold & dmask];
|
||||
dodist:
|
||||
op = (unsigned)(here.bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(here.op);
|
||||
if (op & 16) { /* distance base */
|
||||
dist = (unsigned)(here.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(*in++) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
}
|
||||
dist += (unsigned)hold & ((1U << op) - 1);
|
||||
#ifdef INFLATE_STRICT
|
||||
if (dist > dmax) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
Tracevv((stderr, "inflate: distance %u\n", dist));
|
||||
op = (unsigned)(out - beg); /* max distance in output */
|
||||
if (dist > op) { /* see if copy from window */
|
||||
op = dist - op; /* distance back in window */
|
||||
if (op > whave) {
|
||||
if (state->sane) {
|
||||
strm->msg =
|
||||
(char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
|
||||
if (len <= op - whave) {
|
||||
do {
|
||||
*out++ = 0;
|
||||
} while (--len);
|
||||
continue;
|
||||
}
|
||||
len -= op - whave;
|
||||
do {
|
||||
*out++ = 0;
|
||||
} while (--op > whave);
|
||||
if (op == 0) {
|
||||
from = out - dist;
|
||||
do {
|
||||
*out++ = *from++;
|
||||
} while (--len);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
from = window;
|
||||
if (wnext == 0) { /* very common case */
|
||||
from += wsize - op;
|
||||
if (op < len) { /* some from window */
|
||||
len -= op;
|
||||
do {
|
||||
*out++ = *from++;
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
else if (wnext < op) { /* wrap around window */
|
||||
from += wsize + wnext - op;
|
||||
op -= wnext;
|
||||
if (op < len) { /* some from end of window */
|
||||
len -= op;
|
||||
do {
|
||||
*out++ = *from++;
|
||||
} while (--op);
|
||||
from = window;
|
||||
if (wnext < len) { /* some from start of window */
|
||||
op = wnext;
|
||||
len -= op;
|
||||
do {
|
||||
*out++ = *from++;
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* contiguous in window */
|
||||
from += wnext - op;
|
||||
if (op < len) { /* some from window */
|
||||
len -= op;
|
||||
do {
|
||||
*out++ = *from++;
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
while (len > 2) {
|
||||
*out++ = *from++;
|
||||
*out++ = *from++;
|
||||
*out++ = *from++;
|
||||
len -= 3;
|
||||
}
|
||||
if (len) {
|
||||
*out++ = *from++;
|
||||
if (len > 1)
|
||||
*out++ = *from++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
from = out - dist; /* copy direct from output */
|
||||
do { /* minimum length is three */
|
||||
*out++ = *from++;
|
||||
*out++ = *from++;
|
||||
*out++ = *from++;
|
||||
len -= 3;
|
||||
} while (len > 2);
|
||||
if (len) {
|
||||
*out++ = *from++;
|
||||
if (len > 1)
|
||||
*out++ = *from++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level distance code */
|
||||
here = dcode[here.val + (hold & ((1U << op) - 1))];
|
||||
goto dodist;
|
||||
}
|
||||
else {
|
||||
strm->msg = (char *)"invalid distance code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level length code */
|
||||
here = lcode[here.val + (hold & ((1U << op) - 1))];
|
||||
goto dolen;
|
||||
}
|
||||
else if (op & 32) { /* end-of-block */
|
||||
Tracevv((stderr, "inflate: end of block\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
strm->msg = (char *)"invalid literal/length code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
} while (in < last && out < end);
|
||||
|
||||
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
|
||||
len = bits >> 3;
|
||||
in -= len;
|
||||
bits -= len << 3;
|
||||
hold &= (1U << bits) - 1;
|
||||
|
||||
/* update state and return */
|
||||
strm->next_in = in;
|
||||
strm->next_out = out;
|
||||
strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
|
||||
strm->avail_out = (unsigned)(out < end ?
|
||||
257 + (end - out) : 257 - (out - end));
|
||||
state->hold = hold;
|
||||
state->bits = bits;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
|
||||
- Using bit fields for code structure
|
||||
- Different op definition to avoid & for extra bits (do & for table bits)
|
||||
- Three separate decoding do-loops for direct, window, and wnext == 0
|
||||
- Special case for distance > 1 copies to do overlapped load and store copy
|
||||
- Explicit branch predictions (based on measured branch probabilities)
|
||||
- Deferring match copy and interspersed it with decoding subsequent codes
|
||||
- Swapping literal/length else
|
||||
- Swapping window/direct else
|
||||
- Larger unrolled copy loops (three is about right)
|
||||
- Moving len -= 3 statement into middle of loop
|
||||
*/
|
||||
|
||||
#endif /* !ASMINF */
|
@ -1,11 +0,0 @@
|
||||
/* inffast.h -- header to use inffast.c
|
||||
* Copyright (C) 1995-2003, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
|
@ -1,68 +0,0 @@
|
||||
/* inffixed.h -- table for decoding fixed codes
|
||||
* Generated automatically by makefixed().
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications.
|
||||
It is part of the implementation of this library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
static const code lenfix[512] = {
|
||||
{96, 7, 0}, {0, 8, 80}, {0, 8, 16}, {20, 8, 115}, {18, 7, 31}, {0, 8, 112}, {0, 8, 48}, {0, 9, 192}, {16, 7, 10}, {0, 8, 96},
|
||||
{0, 8, 32}, {0, 9, 160}, {0, 8, 0}, {0, 8, 128}, {0, 8, 64}, {0, 9, 224}, {16, 7, 6}, {0, 8, 88}, {0, 8, 24}, {0, 9, 144},
|
||||
{19, 7, 59}, {0, 8, 120}, {0, 8, 56}, {0, 9, 208}, {17, 7, 17}, {0, 8, 104}, {0, 8, 40}, {0, 9, 176}, {0, 8, 8}, {0, 8, 136},
|
||||
{0, 8, 72}, {0, 9, 240}, {16, 7, 4}, {0, 8, 84}, {0, 8, 20}, {21, 8, 227}, {19, 7, 43}, {0, 8, 116}, {0, 8, 52}, {0, 9, 200},
|
||||
{17, 7, 13}, {0, 8, 100}, {0, 8, 36}, {0, 9, 168}, {0, 8, 4}, {0, 8, 132}, {0, 8, 68}, {0, 9, 232}, {16, 7, 8}, {0, 8, 92},
|
||||
{0, 8, 28}, {0, 9, 152}, {20, 7, 83}, {0, 8, 124}, {0, 8, 60}, {0, 9, 216}, {18, 7, 23}, {0, 8, 108}, {0, 8, 44}, {0, 9, 184},
|
||||
{0, 8, 12}, {0, 8, 140}, {0, 8, 76}, {0, 9, 248}, {16, 7, 3}, {0, 8, 82}, {0, 8, 18}, {21, 8, 163}, {19, 7, 35}, {0, 8, 114},
|
||||
{0, 8, 50}, {0, 9, 196}, {17, 7, 11}, {0, 8, 98}, {0, 8, 34}, {0, 9, 164}, {0, 8, 2}, {0, 8, 130}, {0, 8, 66}, {0, 9, 228},
|
||||
{16, 7, 7}, {0, 8, 90}, {0, 8, 26}, {0, 9, 148}, {20, 7, 67}, {0, 8, 122}, {0, 8, 58}, {0, 9, 212}, {18, 7, 19}, {0, 8, 106},
|
||||
{0, 8, 42}, {0, 9, 180}, {0, 8, 10}, {0, 8, 138}, {0, 8, 74}, {0, 9, 244}, {16, 7, 5}, {0, 8, 86}, {0, 8, 22}, {64, 8, 0},
|
||||
{19, 7, 51}, {0, 8, 118}, {0, 8, 54}, {0, 9, 204}, {17, 7, 15}, {0, 8, 102}, {0, 8, 38}, {0, 9, 172}, {0, 8, 6}, {0, 8, 134},
|
||||
{0, 8, 70}, {0, 9, 236}, {16, 7, 9}, {0, 8, 94}, {0, 8, 30}, {0, 9, 156}, {20, 7, 99}, {0, 8, 126}, {0, 8, 62}, {0, 9, 220},
|
||||
{18, 7, 27}, {0, 8, 110}, {0, 8, 46}, {0, 9, 188}, {0, 8, 14}, {0, 8, 142}, {0, 8, 78}, {0, 9, 252}, {96, 7, 0}, {0, 8, 81},
|
||||
{0, 8, 17}, {21, 8, 131}, {18, 7, 31}, {0, 8, 113}, {0, 8, 49}, {0, 9, 194}, {16, 7, 10}, {0, 8, 97}, {0, 8, 33}, {0, 9, 162},
|
||||
{0, 8, 1}, {0, 8, 129}, {0, 8, 65}, {0, 9, 226}, {16, 7, 6}, {0, 8, 89}, {0, 8, 25}, {0, 9, 146}, {19, 7, 59}, {0, 8, 121},
|
||||
{0, 8, 57}, {0, 9, 210}, {17, 7, 17}, {0, 8, 105}, {0, 8, 41}, {0, 9, 178}, {0, 8, 9}, {0, 8, 137}, {0, 8, 73}, {0, 9, 242},
|
||||
{16, 7, 4}, {0, 8, 85}, {0, 8, 21}, {16, 8, 258}, {19, 7, 43}, {0, 8, 117}, {0, 8, 53}, {0, 9, 202}, {17, 7, 13}, {0, 8, 101},
|
||||
{0, 8, 37}, {0, 9, 170}, {0, 8, 5}, {0, 8, 133}, {0, 8, 69}, {0, 9, 234}, {16, 7, 8}, {0, 8, 93}, {0, 8, 29}, {0, 9, 154},
|
||||
{20, 7, 83}, {0, 8, 125}, {0, 8, 61}, {0, 9, 218}, {18, 7, 23}, {0, 8, 109}, {0, 8, 45}, {0, 9, 186}, {0, 8, 13}, {0, 8, 141},
|
||||
{0, 8, 77}, {0, 9, 250}, {16, 7, 3}, {0, 8, 83}, {0, 8, 19}, {21, 8, 195}, {19, 7, 35}, {0, 8, 115}, {0, 8, 51}, {0, 9, 198},
|
||||
{17, 7, 11}, {0, 8, 99}, {0, 8, 35}, {0, 9, 166}, {0, 8, 3}, {0, 8, 131}, {0, 8, 67}, {0, 9, 230}, {16, 7, 7}, {0, 8, 91},
|
||||
{0, 8, 27}, {0, 9, 150}, {20, 7, 67}, {0, 8, 123}, {0, 8, 59}, {0, 9, 214}, {18, 7, 19}, {0, 8, 107}, {0, 8, 43}, {0, 9, 182},
|
||||
{0, 8, 11}, {0, 8, 139}, {0, 8, 75}, {0, 9, 246}, {16, 7, 5}, {0, 8, 87}, {0, 8, 23}, {64, 8, 0}, {19, 7, 51}, {0, 8, 119},
|
||||
{0, 8, 55}, {0, 9, 206}, {17, 7, 15}, {0, 8, 103}, {0, 8, 39}, {0, 9, 174}, {0, 8, 7}, {0, 8, 135}, {0, 8, 71}, {0, 9, 238},
|
||||
{16, 7, 9}, {0, 8, 95}, {0, 8, 31}, {0, 9, 158}, {20, 7, 99}, {0, 8, 127}, {0, 8, 63}, {0, 9, 222}, {18, 7, 27}, {0, 8, 111},
|
||||
{0, 8, 47}, {0, 9, 190}, {0, 8, 15}, {0, 8, 143}, {0, 8, 79}, {0, 9, 254}, {96, 7, 0}, {0, 8, 80}, {0, 8, 16}, {20, 8, 115},
|
||||
{18, 7, 31}, {0, 8, 112}, {0, 8, 48}, {0, 9, 193}, {16, 7, 10}, {0, 8, 96}, {0, 8, 32}, {0, 9, 161}, {0, 8, 0}, {0, 8, 128},
|
||||
{0, 8, 64}, {0, 9, 225}, {16, 7, 6}, {0, 8, 88}, {0, 8, 24}, {0, 9, 145}, {19, 7, 59}, {0, 8, 120}, {0, 8, 56}, {0, 9, 209},
|
||||
{17, 7, 17}, {0, 8, 104}, {0, 8, 40}, {0, 9, 177}, {0, 8, 8}, {0, 8, 136}, {0, 8, 72}, {0, 9, 241}, {16, 7, 4}, {0, 8, 84},
|
||||
{0, 8, 20}, {21, 8, 227}, {19, 7, 43}, {0, 8, 116}, {0, 8, 52}, {0, 9, 201}, {17, 7, 13}, {0, 8, 100}, {0, 8, 36}, {0, 9, 169},
|
||||
{0, 8, 4}, {0, 8, 132}, {0, 8, 68}, {0, 9, 233}, {16, 7, 8}, {0, 8, 92}, {0, 8, 28}, {0, 9, 153}, {20, 7, 83}, {0, 8, 124},
|
||||
{0, 8, 60}, {0, 9, 217}, {18, 7, 23}, {0, 8, 108}, {0, 8, 44}, {0, 9, 185}, {0, 8, 12}, {0, 8, 140}, {0, 8, 76}, {0, 9, 249},
|
||||
{16, 7, 3}, {0, 8, 82}, {0, 8, 18}, {21, 8, 163}, {19, 7, 35}, {0, 8, 114}, {0, 8, 50}, {0, 9, 197}, {17, 7, 11}, {0, 8, 98},
|
||||
{0, 8, 34}, {0, 9, 165}, {0, 8, 2}, {0, 8, 130}, {0, 8, 66}, {0, 9, 229}, {16, 7, 7}, {0, 8, 90}, {0, 8, 26}, {0, 9, 149},
|
||||
{20, 7, 67}, {0, 8, 122}, {0, 8, 58}, {0, 9, 213}, {18, 7, 19}, {0, 8, 106}, {0, 8, 42}, {0, 9, 181}, {0, 8, 10}, {0, 8, 138},
|
||||
{0, 8, 74}, {0, 9, 245}, {16, 7, 5}, {0, 8, 86}, {0, 8, 22}, {64, 8, 0}, {19, 7, 51}, {0, 8, 118}, {0, 8, 54}, {0, 9, 205},
|
||||
{17, 7, 15}, {0, 8, 102}, {0, 8, 38}, {0, 9, 173}, {0, 8, 6}, {0, 8, 134}, {0, 8, 70}, {0, 9, 237}, {16, 7, 9}, {0, 8, 94},
|
||||
{0, 8, 30}, {0, 9, 157}, {20, 7, 99}, {0, 8, 126}, {0, 8, 62}, {0, 9, 221}, {18, 7, 27}, {0, 8, 110}, {0, 8, 46}, {0, 9, 189},
|
||||
{0, 8, 14}, {0, 8, 142}, {0, 8, 78}, {0, 9, 253}, {96, 7, 0}, {0, 8, 81}, {0, 8, 17}, {21, 8, 131}, {18, 7, 31}, {0, 8, 113},
|
||||
{0, 8, 49}, {0, 9, 195}, {16, 7, 10}, {0, 8, 97}, {0, 8, 33}, {0, 9, 163}, {0, 8, 1}, {0, 8, 129}, {0, 8, 65}, {0, 9, 227},
|
||||
{16, 7, 6}, {0, 8, 89}, {0, 8, 25}, {0, 9, 147}, {19, 7, 59}, {0, 8, 121}, {0, 8, 57}, {0, 9, 211}, {17, 7, 17}, {0, 8, 105},
|
||||
{0, 8, 41}, {0, 9, 179}, {0, 8, 9}, {0, 8, 137}, {0, 8, 73}, {0, 9, 243}, {16, 7, 4}, {0, 8, 85}, {0, 8, 21}, {16, 8, 258},
|
||||
{19, 7, 43}, {0, 8, 117}, {0, 8, 53}, {0, 9, 203}, {17, 7, 13}, {0, 8, 101}, {0, 8, 37}, {0, 9, 171}, {0, 8, 5}, {0, 8, 133},
|
||||
{0, 8, 69}, {0, 9, 235}, {16, 7, 8}, {0, 8, 93}, {0, 8, 29}, {0, 9, 155}, {20, 7, 83}, {0, 8, 125}, {0, 8, 61}, {0, 9, 219},
|
||||
{18, 7, 23}, {0, 8, 109}, {0, 8, 45}, {0, 9, 187}, {0, 8, 13}, {0, 8, 141}, {0, 8, 77}, {0, 9, 251}, {16, 7, 3}, {0, 8, 83},
|
||||
{0, 8, 19}, {21, 8, 195}, {19, 7, 35}, {0, 8, 115}, {0, 8, 51}, {0, 9, 199}, {17, 7, 11}, {0, 8, 99}, {0, 8, 35}, {0, 9, 167},
|
||||
{0, 8, 3}, {0, 8, 131}, {0, 8, 67}, {0, 9, 231}, {16, 7, 7}, {0, 8, 91}, {0, 8, 27}, {0, 9, 151}, {20, 7, 67}, {0, 8, 123},
|
||||
{0, 8, 59}, {0, 9, 215}, {18, 7, 19}, {0, 8, 107}, {0, 8, 43}, {0, 9, 183}, {0, 8, 11}, {0, 8, 139}, {0, 8, 75}, {0, 9, 247},
|
||||
{16, 7, 5}, {0, 8, 87}, {0, 8, 23}, {64, 8, 0}, {19, 7, 51}, {0, 8, 119}, {0, 8, 55}, {0, 9, 207}, {17, 7, 15}, {0, 8, 103},
|
||||
{0, 8, 39}, {0, 9, 175}, {0, 8, 7}, {0, 8, 135}, {0, 8, 71}, {0, 9, 239}, {16, 7, 9}, {0, 8, 95}, {0, 8, 31}, {0, 9, 159},
|
||||
{20, 7, 99}, {0, 8, 127}, {0, 8, 63}, {0, 9, 223}, {18, 7, 27}, {0, 8, 111}, {0, 8, 47}, {0, 9, 191}, {0, 8, 15}, {0, 8, 143},
|
||||
{0, 8, 79}, {0, 9, 255}};
|
||||
|
||||
static const code distfix[32]
|
||||
= {{16, 5, 1}, {23, 5, 257}, {19, 5, 17}, {27, 5, 4097}, {17, 5, 5}, {25, 5, 1025}, {21, 5, 65}, {29, 5, 16385},
|
||||
{16, 5, 3}, {24, 5, 513}, {20, 5, 33}, {28, 5, 8193}, {18, 5, 9}, {26, 5, 2049}, {22, 5, 129}, {64, 5, 0},
|
||||
{16, 5, 2}, {23, 5, 385}, {19, 5, 25}, {27, 5, 6145}, {17, 5, 7}, {25, 5, 1537}, {21, 5, 97}, {29, 5, 24577},
|
||||
{16, 5, 4}, {24, 5, 769}, {20, 5, 49}, {28, 5, 12289}, {18, 5, 13}, {26, 5, 3073}, {22, 5, 193}, {64, 5, 0}};
|
File diff suppressed because it is too large
Load Diff
@ -1,127 +0,0 @@
|
||||
/* inflate.h -- internal inflate state definition
|
||||
* Copyright (C) 1995-2016 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* define NO_GZIP when compiling if you want to disable gzip header and
|
||||
trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
|
||||
the crc code when it is not needed. For shared libraries, gzip decoding
|
||||
should be left enabled. */
|
||||
#ifndef NO_GZIP
|
||||
# define GUNZIP
|
||||
#endif
|
||||
|
||||
/* Possible inflate modes between inflate() calls */
|
||||
typedef enum
|
||||
{
|
||||
HEAD = 16180, /* i: waiting for magic header */
|
||||
FLAGS, /* i: waiting for method and flags (gzip) */
|
||||
TIME, /* i: waiting for modification time (gzip) */
|
||||
OS, /* i: waiting for extra flags and operating system (gzip) */
|
||||
EXLEN, /* i: waiting for extra length (gzip) */
|
||||
EXTRA, /* i: waiting for extra bytes (gzip) */
|
||||
NAME, /* i: waiting for end of file name (gzip) */
|
||||
COMMENT, /* i: waiting for end of comment (gzip) */
|
||||
HCRC, /* i: waiting for header crc (gzip) */
|
||||
DICTID, /* i: waiting for dictionary check value */
|
||||
DICT, /* waiting for inflateSetDictionary() call */
|
||||
TYPE, /* i: waiting for type bits, including last-flag bit */
|
||||
TYPEDO, /* i: same, but skip check to exit inflate on new block */
|
||||
STORED, /* i: waiting for stored size (length and complement) */
|
||||
COPY_, /* i/o: same as COPY below, but only first time in */
|
||||
COPY, /* i/o: waiting for input or output to copy stored block */
|
||||
TABLE, /* i: waiting for dynamic block table lengths */
|
||||
LENLENS, /* i: waiting for code length code lengths */
|
||||
CODELENS, /* i: waiting for length/lit and distance code lengths */
|
||||
LEN_, /* i: same as LEN below, but only first time in */
|
||||
LEN, /* i: waiting for length/lit/eob code */
|
||||
LENEXT, /* i: waiting for length extra bits */
|
||||
DIST, /* i: waiting for distance code */
|
||||
DISTEXT, /* i: waiting for distance extra bits */
|
||||
MATCH, /* o: waiting for output space to copy string */
|
||||
LIT, /* o: waiting for output space to write literal */
|
||||
CHECK, /* i: waiting for 32-bit check value */
|
||||
LENGTH, /* i: waiting for 32-bit length (gzip) */
|
||||
DONE, /* finished check, done -- remain here until reset */
|
||||
BAD, /* got a data error -- remain here until reset */
|
||||
MEM, /* got an inflate() memory error -- remain here until reset */
|
||||
SYNC /* looking for synchronization bytes to restart inflate() */
|
||||
} inflate_mode;
|
||||
|
||||
/*
|
||||
State transitions between above modes -
|
||||
|
||||
(most modes can go to BAD or MEM on error -- not shown for clarity)
|
||||
|
||||
Process header:
|
||||
HEAD -> (gzip) or (zlib) or (raw)
|
||||
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
|
||||
HCRC -> TYPE
|
||||
(zlib) -> DICTID or TYPE
|
||||
DICTID -> DICT -> TYPE
|
||||
(raw) -> TYPEDO
|
||||
Read deflate blocks:
|
||||
TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
|
||||
STORED -> COPY_ -> COPY -> TYPE
|
||||
TABLE -> LENLENS -> CODELENS -> LEN_
|
||||
LEN_ -> LEN
|
||||
Read deflate codes in fixed or dynamic block:
|
||||
LEN -> LENEXT or LIT or TYPE
|
||||
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
|
||||
LIT -> LEN
|
||||
Process trailer:
|
||||
CHECK -> LENGTH -> DONE
|
||||
*/
|
||||
|
||||
/* State maintained between inflate() calls -- approximately 7K bytes, not
|
||||
including the allocated sliding window, which is up to 32K bytes. */
|
||||
struct inflate_state
|
||||
{
|
||||
z_streamp strm; /* pointer back to this zlib stream */
|
||||
inflate_mode mode; /* current inflate mode */
|
||||
int last; /* true if processing last block */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
|
||||
bit 2 true to validate check value */
|
||||
int havedict; /* true if dictionary provided */
|
||||
int flags; /* gzip header method and flags (0 if zlib) */
|
||||
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
|
||||
unsigned long check; /* protected copy of check value */
|
||||
unsigned long total; /* protected copy of output count */
|
||||
gz_headerp head; /* where to save gzip header information */
|
||||
/* sliding window */
|
||||
unsigned wbits; /* log base 2 of requested window size */
|
||||
unsigned wsize; /* window size or zero if not using window */
|
||||
unsigned whave; /* valid bytes in the window */
|
||||
unsigned wnext; /* window write index */
|
||||
unsigned char FAR * window; /* allocated sliding window, if needed */
|
||||
/* bit accumulator */
|
||||
unsigned long hold; /* input bit accumulator */
|
||||
unsigned bits; /* number of bits in "in" */
|
||||
/* for string and stored block copying */
|
||||
unsigned length; /* literal or length of data to copy */
|
||||
unsigned offset; /* distance back to copy string from */
|
||||
/* for table and code decoding */
|
||||
unsigned extra; /* extra bits needed */
|
||||
/* fixed and dynamic code tables */
|
||||
code const FAR * lencode; /* starting table for length/literal codes */
|
||||
code const FAR * distcode; /* starting table for distance codes */
|
||||
unsigned lenbits; /* index bits for lencode */
|
||||
unsigned distbits; /* index bits for distcode */
|
||||
/* dynamic table building */
|
||||
unsigned ncode; /* number of code length code lengths */
|
||||
unsigned nlen; /* number of length code lengths */
|
||||
unsigned ndist; /* number of distance code lengths */
|
||||
unsigned have; /* number of code lengths in lens[] */
|
||||
code FAR * next; /* next available space in codes[] */
|
||||
unsigned short lens[320]; /* temporary storage for code lengths */
|
||||
unsigned short work[288]; /* work area for code table building */
|
||||
code codes[ENOUGH]; /* space for code tables */
|
||||
int sane; /* if false, allow invalid distance too far */
|
||||
int back; /* bits back of last unprocessed length/lit */
|
||||
unsigned was; /* initial length of match */
|
||||
};
|
@ -1,304 +0,0 @@
|
||||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-2017 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
|
||||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] =
|
||||
" inflate 1.2.11 Copyright 1995-2017 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
include such an acknowledgment, I would appreciate that you keep this
|
||||
copyright string in the executable of your product.
|
||||
*/
|
||||
|
||||
/*
|
||||
Build a set of tables to decode the provided canonical Huffman code.
|
||||
The code lengths are lens[0..codes-1]. The result starts at *table,
|
||||
whose indices are 0..2^bits-1. work is a writable array of at least
|
||||
lens shorts, which is used as a work area. type is the type of code
|
||||
to be generated, CODES, LENS, or DISTS. On return, zero is success,
|
||||
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
|
||||
on return points to the next available entry's address. bits is the
|
||||
requested root table index bits, and on return it is the actual root
|
||||
table index bits. It will differ if the request is greater than the
|
||||
longest code or if it is less than the shortest code.
|
||||
*/
|
||||
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
|
||||
codetype type;
|
||||
unsigned short FAR *lens;
|
||||
unsigned codes;
|
||||
code FAR * FAR *table;
|
||||
unsigned FAR *bits;
|
||||
unsigned short FAR *work;
|
||||
{
|
||||
unsigned len; /* a code's length in bits */
|
||||
unsigned sym; /* index of code symbols */
|
||||
unsigned min, max; /* minimum and maximum code lengths */
|
||||
unsigned root; /* number of index bits for root table */
|
||||
unsigned curr; /* number of index bits for current table */
|
||||
unsigned drop; /* code bits to drop for sub-table */
|
||||
int left; /* number of prefix codes available */
|
||||
unsigned used; /* code entries in table used */
|
||||
unsigned huff; /* Huffman code */
|
||||
unsigned incr; /* for incrementing code, index */
|
||||
unsigned fill; /* index for replicating entries */
|
||||
unsigned low; /* low bits for current root entry */
|
||||
unsigned mask; /* mask for low root bits */
|
||||
code here; /* table entry for duplication */
|
||||
code FAR *next; /* next available space in table */
|
||||
const unsigned short FAR *base; /* base value table to use */
|
||||
const unsigned short FAR *extra; /* extra bits table to use */
|
||||
unsigned match; /* use base and extra for symbol >= match */
|
||||
unsigned short count[MAXBITS+1]; /* number of codes of each length */
|
||||
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
|
||||
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
8193, 12289, 16385, 24577, 0, 0};
|
||||
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
|
||||
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
|
||||
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
|
||||
28, 28, 29, 29, 64, 64};
|
||||
|
||||
/*
|
||||
Process a set of code lengths to create a canonical Huffman code. The
|
||||
code lengths are lens[0..codes-1]. Each length corresponds to the
|
||||
symbols 0..codes-1. The Huffman code is generated by first sorting the
|
||||
symbols by length from short to long, and retaining the symbol order
|
||||
for codes with equal lengths. Then the code starts with all zero bits
|
||||
for the first code of the shortest length, and the codes are integer
|
||||
increments for the same length, and zeros are appended as the length
|
||||
increases. For the deflate format, these bits are stored backwards
|
||||
from their more natural integer increment ordering, and so when the
|
||||
decoding tables are built in the large loop below, the integer codes
|
||||
are incremented backwards.
|
||||
|
||||
This routine assumes, but does not check, that all of the entries in
|
||||
lens[] are in the range 0..MAXBITS. The caller must assure this.
|
||||
1..MAXBITS is interpreted as that code length. zero means that that
|
||||
symbol does not occur in this code.
|
||||
|
||||
The codes are sorted by computing a count of codes for each length,
|
||||
creating from that a table of starting indices for each length in the
|
||||
sorted table, and then entering the symbols in order in the sorted
|
||||
table. The sorted table is work[], with that space being provided by
|
||||
the caller.
|
||||
|
||||
The length counts are used for other purposes as well, i.e. finding
|
||||
the minimum and maximum length codes, determining if there are any
|
||||
codes at all, checking for a valid set of lengths, and looking ahead
|
||||
at length counts to determine sub-table sizes when building the
|
||||
decoding tables.
|
||||
*/
|
||||
|
||||
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
|
||||
for (len = 0; len <= MAXBITS; len++)
|
||||
count[len] = 0;
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
count[lens[sym]]++;
|
||||
|
||||
/* bound code lengths, force root to be within code lengths */
|
||||
root = *bits;
|
||||
for (max = MAXBITS; max >= 1; max--)
|
||||
if (count[max] != 0) break;
|
||||
if (root > max) root = max;
|
||||
if (max == 0) { /* no symbols to code at all */
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)1;
|
||||
here.val = (unsigned short)0;
|
||||
*(*table)++ = here; /* make a table to force an error */
|
||||
*(*table)++ = here;
|
||||
*bits = 1;
|
||||
return 0; /* no symbols, but wait for decoding to report error */
|
||||
}
|
||||
for (min = 1; min < max; min++)
|
||||
if (count[min] != 0) break;
|
||||
if (root < min) root = min;
|
||||
|
||||
/* check for an over-subscribed or incomplete set of lengths */
|
||||
left = 1;
|
||||
for (len = 1; len <= MAXBITS; len++) {
|
||||
left <<= 1;
|
||||
left -= count[len];
|
||||
if (left < 0) return -1; /* over-subscribed */
|
||||
}
|
||||
if (left > 0 && (type == CODES || max != 1))
|
||||
return -1; /* incomplete set */
|
||||
|
||||
/* generate offsets into symbol table for each length for sorting */
|
||||
offs[1] = 0;
|
||||
for (len = 1; len < MAXBITS; len++)
|
||||
offs[len + 1] = offs[len] + count[len];
|
||||
|
||||
/* sort symbols by length, by symbol order within each length */
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
|
||||
|
||||
/*
|
||||
Create and fill in decoding tables. In this loop, the table being
|
||||
filled is at next and has curr index bits. The code being used is huff
|
||||
with length len. That code is converted to an index by dropping drop
|
||||
bits off of the bottom. For codes where len is less than drop + curr,
|
||||
those top drop + curr - len bits are incremented through all values to
|
||||
fill the table with replicated entries.
|
||||
|
||||
root is the number of index bits for the root table. When len exceeds
|
||||
root, sub-tables are created pointed to by the root entry with an index
|
||||
of the low root bits of huff. This is saved in low to check for when a
|
||||
new sub-table should be started. drop is zero when the root table is
|
||||
being filled, and drop is root when sub-tables are being filled.
|
||||
|
||||
When a new sub-table is needed, it is necessary to look ahead in the
|
||||
code lengths to determine what size sub-table is needed. The length
|
||||
counts are used for this, and so count[] is decremented as codes are
|
||||
entered in the tables.
|
||||
|
||||
used keeps track of how many table entries have been allocated from the
|
||||
provided *table space. It is checked for LENS and DIST tables against
|
||||
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
|
||||
the initial root table size constants. See the comments in inftrees.h
|
||||
for more information.
|
||||
|
||||
sym increments through all symbols, and the loop terminates when
|
||||
all codes of length max, i.e. all codes, have been processed. This
|
||||
routine permits incomplete codes, so another loop after this one fills
|
||||
in the rest of the decoding tables with invalid code markers.
|
||||
*/
|
||||
|
||||
/* set up for code type */
|
||||
switch (type) {
|
||||
case CODES:
|
||||
base = extra = work; /* dummy value--not used */
|
||||
match = 20;
|
||||
break;
|
||||
case LENS:
|
||||
base = lbase;
|
||||
extra = lext;
|
||||
match = 257;
|
||||
break;
|
||||
default: /* DISTS */
|
||||
base = dbase;
|
||||
extra = dext;
|
||||
match = 0;
|
||||
}
|
||||
|
||||
/* initialize state for loop */
|
||||
huff = 0; /* starting code */
|
||||
sym = 0; /* starting code symbol */
|
||||
len = min; /* starting code length */
|
||||
next = *table; /* current table to fill in */
|
||||
curr = root; /* current table index bits */
|
||||
drop = 0; /* current bits to drop from code for index */
|
||||
low = (unsigned)(-1); /* trigger new sub-table when len > root */
|
||||
used = 1U << root; /* use root table entries */
|
||||
mask = used - 1; /* mask for comparing low */
|
||||
|
||||
/* check available table space */
|
||||
if ((type == LENS && used > ENOUGH_LENS) ||
|
||||
(type == DISTS && used > ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* process all codes and make table entries */
|
||||
for (;;) {
|
||||
/* create table entry */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
if (work[sym] + 1U < match) {
|
||||
here.op = (unsigned char)0;
|
||||
here.val = work[sym];
|
||||
}
|
||||
else if (work[sym] >= match) {
|
||||
here.op = (unsigned char)(extra[work[sym] - match]);
|
||||
here.val = base[work[sym] - match];
|
||||
}
|
||||
else {
|
||||
here.op = (unsigned char)(32 + 64); /* end of block */
|
||||
here.val = 0;
|
||||
}
|
||||
|
||||
/* replicate for those indices with low len bits equal to huff */
|
||||
incr = 1U << (len - drop);
|
||||
fill = 1U << curr;
|
||||
min = fill; /* save offset to next table */
|
||||
do {
|
||||
fill -= incr;
|
||||
next[(huff >> drop) + fill] = here;
|
||||
} while (fill != 0);
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
|
||||
/* go to next symbol, update count, len */
|
||||
sym++;
|
||||
if (--(count[len]) == 0) {
|
||||
if (len == max) break;
|
||||
len = lens[work[sym]];
|
||||
}
|
||||
|
||||
/* create new sub-table if needed */
|
||||
if (len > root && (huff & mask) != low) {
|
||||
/* if first time, transition to sub-tables */
|
||||
if (drop == 0)
|
||||
drop = root;
|
||||
|
||||
/* increment past last table */
|
||||
next += min; /* here min is 1 << curr */
|
||||
|
||||
/* determine length of next table */
|
||||
curr = len - drop;
|
||||
left = (int)(1 << curr);
|
||||
while (curr + drop < max) {
|
||||
left -= count[curr + drop];
|
||||
if (left <= 0) break;
|
||||
curr++;
|
||||
left <<= 1;
|
||||
}
|
||||
|
||||
/* check for enough space */
|
||||
used += 1U << curr;
|
||||
if ((type == LENS && used > ENOUGH_LENS) ||
|
||||
(type == DISTS && used > ENOUGH_DISTS))
|
||||
return 1;
|
||||
|
||||
/* point entry in root table to sub-table */
|
||||
low = huff & mask;
|
||||
(*table)[low].op = (unsigned char)curr;
|
||||
(*table)[low].bits = (unsigned char)root;
|
||||
(*table)[low].val = (unsigned short)(next - *table);
|
||||
}
|
||||
}
|
||||
|
||||
/* fill in remaining table entry if code is incomplete (guaranteed to have
|
||||
at most one remaining entry, since if the code is incomplete, the
|
||||
maximum code length that was allowed to get this far is one bit) */
|
||||
if (huff != 0) {
|
||||
here.op = (unsigned char)64; /* invalid code marker */
|
||||
here.bits = (unsigned char)(len - drop);
|
||||
here.val = (unsigned short)0;
|
||||
next[huff] = here;
|
||||
}
|
||||
|
||||
/* set return parameters */
|
||||
*table += used;
|
||||
*bits = root;
|
||||
return 0;
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/* inftrees.h -- header to use inftrees.c
|
||||
* Copyright (C) 1995-2005, 2010 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* Structure for decoding tables. Each entry provides either the
|
||||
information needed to do the operation requested by the code that
|
||||
indexed that table entry, or it provides a pointer to another
|
||||
table that indexes more bits of the code. op indicates whether
|
||||
the entry is a pointer to another table, a literal, a length or
|
||||
distance, an end-of-block, or an invalid code. For a table
|
||||
pointer, the low four bits of op is the number of index bits of
|
||||
that table. For a length or distance, the low four bits of op
|
||||
is the number of extra bits to get after the code. bits is
|
||||
the number of bits in this code or part of the code to drop off
|
||||
of the bit buffer. val is the actual byte to output in the case
|
||||
of a literal, the base length or distance, or the offset from
|
||||
the current table to the next table. Each entry is four bytes. */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char op; /* operation, extra bits, table bits */
|
||||
unsigned char bits; /* bits in this part of the code */
|
||||
unsigned short val; /* offset in table or code value */
|
||||
} code;
|
||||
|
||||
/* op values as set by inflate_table():
|
||||
00000000 - literal
|
||||
0000tttt - table link, tttt != 0 is the number of table index bits
|
||||
0001eeee - length or distance, eeee is the number of extra bits
|
||||
01100000 - end of block
|
||||
01000000 - invalid code
|
||||
*/
|
||||
|
||||
/* Maximum size of the dynamic table. The maximum number of code structures is
|
||||
1444, which is the sum of 852 for literal/length codes and 592 for distance
|
||||
codes. These values were found by exhaustive searches using the program
|
||||
examples/enough.c found in the zlib distribution. The arguments to that
|
||||
program are the number of symbols, the initial root table size, and the
|
||||
maximum bit length of a code. "enough 286 9 15" for literal/length codes
|
||||
returns returns 852, and "enough 30 6 15" for distance codes returns 592.
|
||||
The initial root table size (9 or 6) is found in the fifth argument of the
|
||||
inflate_table() calls in inflate.c and infback.c. If the root table size is
|
||||
changed, then these maximum sizes would be need to be recalculated and
|
||||
updated. */
|
||||
#define ENOUGH_LENS 852
|
||||
#define ENOUGH_DISTS 592
|
||||
#define ENOUGH (ENOUGH_LENS + ENOUGH_DISTS)
|
||||
|
||||
/* Type of code to build for inflate_table() */
|
||||
typedef enum
|
||||
{
|
||||
CODES,
|
||||
LENS,
|
||||
DISTS
|
||||
} codetype;
|
||||
|
||||
int ZLIB_INTERNAL inflate_table
|
||||
OF((codetype type, unsigned short FAR * lens, unsigned codes, code FAR * FAR * table, unsigned FAR * bits, unsigned short FAR * work));
|
@ -1,87 +0,0 @@
|
||||
;//
|
||||
;// pocomsg.mc[.h]
|
||||
;//
|
||||
;// The Poco message source/header file.
|
||||
;//
|
||||
;// NOTE: pocomsg.h is automatically generated from pocomsg.mc.
|
||||
;// Never edit pocomsg.h directly!
|
||||
;//
|
||||
;// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
|
||||
;// and Contributors.
|
||||
;//
|
||||
;// Permission is hereby granted, free of charge, to any person or organization
|
||||
;// obtaining a copy of the software and accompanying documentation covered by
|
||||
;// this license (the "Software") to use, reproduce, display, distribute,
|
||||
;// execute, and transmit the Software, and to prepare derivative works of the
|
||||
;// Software, and to permit third-parties to whom the Software is furnished to
|
||||
;// do so, all subject to the following:
|
||||
;//
|
||||
;// The copyright notices in the Software and this entire statement, including
|
||||
;// the above license grant, this restriction and the following disclaimer,
|
||||
;// must be included in all copies of the Software, in whole or in part, and
|
||||
;// all derivative works of the Software, unless such copies or derivative
|
||||
;// works are solely in the form of machine-executable object code generated by
|
||||
;// a source language processor.
|
||||
;//
|
||||
;// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
;// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
;// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
;// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
;// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
;// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;// DEALINGS IN THE SOFTWARE.
|
||||
;//
|
||||
|
||||
|
||||
;//
|
||||
;// Categories
|
||||
;//
|
||||
MessageId=0x1
|
||||
SymbolicName=POCO_CTG_FATAL
|
||||
Language=English
|
||||
Fatal
|
||||
.
|
||||
MessageId=0x2
|
||||
SymbolicName=POCO_CTG_CRITICAL
|
||||
Language=English
|
||||
Critical
|
||||
.
|
||||
MessageId=0x3
|
||||
SymbolicName=POCO_CTG_ERROR
|
||||
Language=English
|
||||
Error
|
||||
.
|
||||
MessageId=0x4
|
||||
SymbolicName=POCO_CTG_WARNING
|
||||
Language=English
|
||||
Warning
|
||||
.
|
||||
MessageId=0x5
|
||||
SymbolicName=POCO_CTG_NOTICE
|
||||
Language=English
|
||||
Notice
|
||||
.
|
||||
MessageId=0x6
|
||||
SymbolicName=POCO_CTG_INFORMATION
|
||||
Language=English
|
||||
Information
|
||||
.
|
||||
MessageId=0x7
|
||||
SymbolicName=POCO_CTG_DEBUG
|
||||
Language=English
|
||||
Debug
|
||||
.
|
||||
MessageId=0x8
|
||||
SymbolicName=POCO_CTG_TRACE
|
||||
Language=English
|
||||
Trace
|
||||
.
|
||||
|
||||
;//
|
||||
;// Event Identifiers
|
||||
;//
|
||||
MessageId=0x1000
|
||||
SymbolicName=POCO_MSG_LOG
|
||||
Language=English
|
||||
%1
|
||||
.
|
@ -1,556 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "strtod.h"
|
||||
#include "bignum.h"
|
||||
#include "cached-powers.h"
|
||||
#include "ieee.h"
|
||||
|
||||
namespace double_conversion {
|
||||
|
||||
// 2^53 = 9007199254740992.
|
||||
// Any integer with at most 15 decimal digits will hence fit into a double
|
||||
// (which has a 53bit significand) without loss of precision.
|
||||
static const int kMaxExactDoubleIntegerDecimalDigits = 15;
|
||||
// 2^64 = 18446744073709551616 > 10^19
|
||||
static const int kMaxUint64DecimalDigits = 19;
|
||||
|
||||
// Max double: 1.7976931348623157 x 10^308
|
||||
// Min non-zero double: 4.9406564584124654 x 10^-324
|
||||
// Any x >= 10^309 is interpreted as +infinity.
|
||||
// Any x <= 10^-324 is interpreted as 0.
|
||||
// Note that 2.5e-324 (despite being smaller than the min double) will be read
|
||||
// as non-zero (equal to the min non-zero double).
|
||||
static const int kMaxDecimalPower = 309;
|
||||
static const int kMinDecimalPower = -324;
|
||||
|
||||
// 2^64 = 18446744073709551616
|
||||
static const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF);
|
||||
|
||||
|
||||
static const double exact_powers_of_ten[] = {
|
||||
1.0, // 10^0
|
||||
10.0,
|
||||
100.0,
|
||||
1000.0,
|
||||
10000.0,
|
||||
100000.0,
|
||||
1000000.0,
|
||||
10000000.0,
|
||||
100000000.0,
|
||||
1000000000.0,
|
||||
10000000000.0, // 10^10
|
||||
100000000000.0,
|
||||
1000000000000.0,
|
||||
10000000000000.0,
|
||||
100000000000000.0,
|
||||
1000000000000000.0,
|
||||
10000000000000000.0,
|
||||
100000000000000000.0,
|
||||
1000000000000000000.0,
|
||||
10000000000000000000.0,
|
||||
100000000000000000000.0, // 10^20
|
||||
1000000000000000000000.0,
|
||||
// 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22
|
||||
10000000000000000000000.0
|
||||
};
|
||||
static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten);
|
||||
|
||||
// Maximum number of significant digits in the decimal representation.
|
||||
// In fact the value is 772 (see conversions.cc), but to give us some margin
|
||||
// we round up to 780.
|
||||
static const int kMaxSignificantDecimalDigits = 780;
|
||||
|
||||
static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
|
||||
for (int i = 0; i < buffer.length(); i++) {
|
||||
if (buffer[i] != '0') {
|
||||
return buffer.SubVector(i, buffer.length());
|
||||
}
|
||||
}
|
||||
return Vector<const char>(buffer.start(), 0);
|
||||
}
|
||||
|
||||
|
||||
static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
|
||||
for (int i = buffer.length() - 1; i >= 0; --i) {
|
||||
if (buffer[i] != '0') {
|
||||
return buffer.SubVector(0, i + 1);
|
||||
}
|
||||
}
|
||||
return Vector<const char>(buffer.start(), 0);
|
||||
}
|
||||
|
||||
|
||||
static void CutToMaxSignificantDigits(Vector<const char> buffer,
|
||||
int exponent,
|
||||
char* significant_buffer,
|
||||
int* significant_exponent) {
|
||||
for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) {
|
||||
significant_buffer[i] = buffer[i];
|
||||
}
|
||||
// The input buffer has been trimmed. Therefore the last digit must be
|
||||
// different from '0'.
|
||||
ASSERT(buffer[buffer.length() - 1] != '0');
|
||||
// Set the last digit to be non-zero. This is sufficient to guarantee
|
||||
// correct rounding.
|
||||
significant_buffer[kMaxSignificantDecimalDigits - 1] = '1';
|
||||
*significant_exponent =
|
||||
exponent + (buffer.length() - kMaxSignificantDecimalDigits);
|
||||
}
|
||||
|
||||
|
||||
// Trims the buffer and cuts it to at most kMaxSignificantDecimalDigits.
|
||||
// If possible the input-buffer is reused, but if the buffer needs to be
|
||||
// modified (due to cutting), then the input needs to be copied into the
|
||||
// buffer_copy_space.
|
||||
static void TrimAndCut(Vector<const char> buffer, int exponent,
|
||||
char* buffer_copy_space, int space_size,
|
||||
Vector<const char>* trimmed, int* updated_exponent) {
|
||||
Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
|
||||
Vector<const char> right_trimmed = TrimTrailingZeros(left_trimmed);
|
||||
exponent += left_trimmed.length() - right_trimmed.length();
|
||||
if (right_trimmed.length() > kMaxSignificantDecimalDigits) {
|
||||
(void) space_size; // Mark variable as used.
|
||||
ASSERT(space_size >= kMaxSignificantDecimalDigits);
|
||||
CutToMaxSignificantDigits(right_trimmed, exponent,
|
||||
buffer_copy_space, updated_exponent);
|
||||
*trimmed = Vector<const char>(buffer_copy_space,
|
||||
kMaxSignificantDecimalDigits);
|
||||
} else {
|
||||
*trimmed = right_trimmed;
|
||||
*updated_exponent = exponent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reads digits from the buffer and converts them to a uint64.
|
||||
// Reads in as many digits as fit into a uint64.
|
||||
// When the string starts with "1844674407370955161" no further digit is read.
|
||||
// Since 2^64 = 18446744073709551616 it would still be possible read another
|
||||
// digit if it was less or equal than 6, but this would complicate the code.
|
||||
static uint64_t ReadUint64(Vector<const char> buffer,
|
||||
int* number_of_read_digits) {
|
||||
uint64_t result = 0;
|
||||
int i = 0;
|
||||
while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) {
|
||||
int digit = buffer[i++] - '0';
|
||||
ASSERT(0 <= digit && digit <= 9);
|
||||
result = 10 * result + digit;
|
||||
}
|
||||
*number_of_read_digits = i;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Reads a DiyFp from the buffer.
|
||||
// The returned DiyFp is not necessarily normalized.
|
||||
// If remaining_decimals is zero then the returned DiyFp is accurate.
|
||||
// Otherwise it has been rounded and has error of at most 1/2 ulp.
|
||||
static void ReadDiyFp(Vector<const char> buffer,
|
||||
DiyFp* result,
|
||||
int* remaining_decimals) {
|
||||
int read_digits;
|
||||
uint64_t significand = ReadUint64(buffer, &read_digits);
|
||||
if (buffer.length() == read_digits) {
|
||||
*result = DiyFp(significand, 0);
|
||||
*remaining_decimals = 0;
|
||||
} else {
|
||||
// Round the significand.
|
||||
if (buffer[read_digits] >= '5') {
|
||||
significand++;
|
||||
}
|
||||
// Compute the binary exponent.
|
||||
int exponent = 0;
|
||||
*result = DiyFp(significand, exponent);
|
||||
*remaining_decimals = buffer.length() - read_digits;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool DoubleStrtod(Vector<const char> trimmed,
|
||||
int exponent,
|
||||
double* result) {
|
||||
#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS)
|
||||
// On x86 the floating-point stack can be 64 or 80 bits wide. If it is
|
||||
// 80 bits wide (as is the case on Linux) then double-rounding occurs and the
|
||||
// result is not accurate.
|
||||
// We know that Windows32 uses 64 bits and is therefore accurate.
|
||||
// Note that the ARM simulator is compiled for 32bits. It therefore exhibits
|
||||
// the same problem.
|
||||
return false;
|
||||
#endif
|
||||
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
|
||||
int read_digits;
|
||||
// The trimmed input fits into a double.
|
||||
// If the 10^exponent (resp. 10^-exponent) fits into a double too then we
|
||||
// can compute the result-double simply by multiplying (resp. dividing) the
|
||||
// two numbers.
|
||||
// This is possible because IEEE guarantees that floating-point operations
|
||||
// return the best possible approximation.
|
||||
if (exponent < 0 && -exponent < kExactPowersOfTenSize) {
|
||||
// 10^-exponent fits into a double.
|
||||
*result = static_cast<double>(ReadUint64(trimmed, &read_digits));
|
||||
ASSERT(read_digits == trimmed.length());
|
||||
*result /= exact_powers_of_ten[-exponent];
|
||||
return true;
|
||||
}
|
||||
if (0 <= exponent && exponent < kExactPowersOfTenSize) {
|
||||
// 10^exponent fits into a double.
|
||||
*result = static_cast<double>(ReadUint64(trimmed, &read_digits));
|
||||
ASSERT(read_digits == trimmed.length());
|
||||
*result *= exact_powers_of_ten[exponent];
|
||||
return true;
|
||||
}
|
||||
int remaining_digits =
|
||||
kMaxExactDoubleIntegerDecimalDigits - trimmed.length();
|
||||
if ((0 <= exponent) &&
|
||||
(exponent - remaining_digits < kExactPowersOfTenSize)) {
|
||||
// The trimmed string was short and we can multiply it with
|
||||
// 10^remaining_digits. As a result the remaining exponent now fits
|
||||
// into a double too.
|
||||
*result = static_cast<double>(ReadUint64(trimmed, &read_digits));
|
||||
ASSERT(read_digits == trimmed.length());
|
||||
*result *= exact_powers_of_ten[remaining_digits];
|
||||
*result *= exact_powers_of_ten[exponent - remaining_digits];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Returns 10^exponent as an exact DiyFp.
|
||||
// The given exponent must be in the range [1; kDecimalExponentDistance[.
|
||||
static DiyFp AdjustmentPowerOfTen(int exponent) {
|
||||
ASSERT(0 < exponent);
|
||||
ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance);
|
||||
// Simply hardcode the remaining powers for the given decimal exponent
|
||||
// distance.
|
||||
ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8);
|
||||
switch (exponent) {
|
||||
case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60);
|
||||
case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57);
|
||||
case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54);
|
||||
case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50);
|
||||
case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47);
|
||||
case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44);
|
||||
case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return DiyFp(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the function returns true then the result is the correct double.
|
||||
// Otherwise it is either the correct double or the double that is just below
|
||||
// the correct double.
|
||||
static bool DiyFpStrtod(Vector<const char> buffer,
|
||||
int exponent,
|
||||
double* result) {
|
||||
DiyFp input;
|
||||
int remaining_decimals;
|
||||
ReadDiyFp(buffer, &input, &remaining_decimals);
|
||||
// Since we may have dropped some digits the input is not accurate.
|
||||
// If remaining_decimals is different than 0 than the error is at most
|
||||
// .5 ulp (unit in the last place).
|
||||
// We don't want to deal with fractions and therefore keep a common
|
||||
// denominator.
|
||||
const int kDenominatorLog = 3;
|
||||
const int kDenominator = 1 << kDenominatorLog;
|
||||
// Move the remaining decimals into the exponent.
|
||||
exponent += remaining_decimals;
|
||||
int error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
|
||||
|
||||
int old_e = input.e();
|
||||
input.Normalize();
|
||||
error <<= old_e - input.e();
|
||||
|
||||
ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent);
|
||||
if (exponent < PowersOfTenCache::kMinDecimalExponent) {
|
||||
*result = 0.0;
|
||||
return true;
|
||||
}
|
||||
DiyFp cached_power;
|
||||
int cached_decimal_exponent;
|
||||
PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent,
|
||||
&cached_power,
|
||||
&cached_decimal_exponent);
|
||||
|
||||
if (cached_decimal_exponent != exponent) {
|
||||
int adjustment_exponent = exponent - cached_decimal_exponent;
|
||||
DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent);
|
||||
input.Multiply(adjustment_power);
|
||||
if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) {
|
||||
// The product of input with the adjustment power fits into a 64 bit
|
||||
// integer.
|
||||
ASSERT(DiyFp::kSignificandSize == 64);
|
||||
} else {
|
||||
// The adjustment power is exact. There is hence only an error of 0.5.
|
||||
error += kDenominator / 2;
|
||||
}
|
||||
}
|
||||
|
||||
input.Multiply(cached_power);
|
||||
// The error introduced by a multiplication of a*b equals
|
||||
// error_a + error_b + error_a*error_b/2^64 + 0.5
|
||||
// Substituting a with 'input' and b with 'cached_power' we have
|
||||
// error_b = 0.5 (all cached powers have an error of less than 0.5 ulp),
|
||||
// error_ab = 0 or 1 / kDenominator > error_a*error_b/ 2^64
|
||||
int error_b = kDenominator / 2;
|
||||
int error_ab = (error == 0 ? 0 : 1); // We round up to 1.
|
||||
int fixed_error = kDenominator / 2;
|
||||
error += error_b + error_ab + fixed_error;
|
||||
|
||||
old_e = input.e();
|
||||
input.Normalize();
|
||||
error <<= old_e - input.e();
|
||||
|
||||
// See if the double's significand changes if we add/subtract the error.
|
||||
int order_of_magnitude = DiyFp::kSignificandSize + input.e();
|
||||
int effective_significand_size =
|
||||
Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude);
|
||||
int precision_digits_count =
|
||||
DiyFp::kSignificandSize - effective_significand_size;
|
||||
if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) {
|
||||
// This can only happen for very small denormals. In this case the
|
||||
// half-way multiplied by the denominator exceeds the range of an uint64.
|
||||
// Simply shift everything to the right.
|
||||
int shift_amount = (precision_digits_count + kDenominatorLog) -
|
||||
DiyFp::kSignificandSize + 1;
|
||||
input.set_f(input.f() >> shift_amount);
|
||||
input.set_e(input.e() + shift_amount);
|
||||
// We add 1 for the lost precision of error, and kDenominator for
|
||||
// the lost precision of input.f().
|
||||
error = (error >> shift_amount) + 1 + kDenominator;
|
||||
precision_digits_count -= shift_amount;
|
||||
}
|
||||
// We use uint64_ts now. This only works if the DiyFp uses uint64_ts too.
|
||||
ASSERT(DiyFp::kSignificandSize == 64);
|
||||
ASSERT(precision_digits_count < 64);
|
||||
uint64_t one64 = 1;
|
||||
uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1;
|
||||
uint64_t precision_bits = input.f() & precision_bits_mask;
|
||||
uint64_t half_way = one64 << (precision_digits_count - 1);
|
||||
precision_bits *= kDenominator;
|
||||
half_way *= kDenominator;
|
||||
DiyFp rounded_input(input.f() >> precision_digits_count,
|
||||
input.e() + precision_digits_count);
|
||||
if (precision_bits >= half_way + error) {
|
||||
rounded_input.set_f(rounded_input.f() + 1);
|
||||
}
|
||||
// If the last_bits are too close to the half-way case than we are too
|
||||
// inaccurate and round down. In this case we return false so that we can
|
||||
// fall back to a more precise algorithm.
|
||||
|
||||
*result = Double(rounded_input).value();
|
||||
if (half_way - error < precision_bits && precision_bits < half_way + error) {
|
||||
// Too imprecise. The caller will have to fall back to a slower version.
|
||||
// However the returned number is guaranteed to be either the correct
|
||||
// double, or the next-lower double.
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns
|
||||
// - -1 if buffer*10^exponent < diy_fp.
|
||||
// - 0 if buffer*10^exponent == diy_fp.
|
||||
// - +1 if buffer*10^exponent > diy_fp.
|
||||
// Preconditions:
|
||||
// buffer.length() + exponent <= kMaxDecimalPower + 1
|
||||
// buffer.length() + exponent > kMinDecimalPower
|
||||
// buffer.length() <= kMaxDecimalSignificantDigits
|
||||
static int CompareBufferWithDiyFp(Vector<const char> buffer,
|
||||
int exponent,
|
||||
DiyFp diy_fp) {
|
||||
ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1);
|
||||
ASSERT(buffer.length() + exponent > kMinDecimalPower);
|
||||
ASSERT(buffer.length() <= kMaxSignificantDecimalDigits);
|
||||
// Make sure that the Bignum will be able to hold all our numbers.
|
||||
// Our Bignum implementation has a separate field for exponents. Shifts will
|
||||
// consume at most one bigit (< 64 bits).
|
||||
// ln(10) == 3.3219...
|
||||
ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits);
|
||||
Bignum buffer_bignum;
|
||||
Bignum diy_fp_bignum;
|
||||
buffer_bignum.AssignDecimalString(buffer);
|
||||
diy_fp_bignum.AssignUInt64(diy_fp.f());
|
||||
if (exponent >= 0) {
|
||||
buffer_bignum.MultiplyByPowerOfTen(exponent);
|
||||
} else {
|
||||
diy_fp_bignum.MultiplyByPowerOfTen(-exponent);
|
||||
}
|
||||
if (diy_fp.e() > 0) {
|
||||
diy_fp_bignum.ShiftLeft(diy_fp.e());
|
||||
} else {
|
||||
buffer_bignum.ShiftLeft(-diy_fp.e());
|
||||
}
|
||||
return Bignum::Compare(buffer_bignum, diy_fp_bignum);
|
||||
}
|
||||
|
||||
|
||||
// Returns true if the guess is the correct double.
|
||||
// Returns false, when guess is either correct or the next-lower double.
|
||||
static bool ComputeGuess(Vector<const char> trimmed, int exponent,
|
||||
double* guess) {
|
||||
if (trimmed.length() == 0) {
|
||||
*guess = 0.0;
|
||||
return true;
|
||||
}
|
||||
if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) {
|
||||
*guess = Double::Infinity();
|
||||
return true;
|
||||
}
|
||||
if (exponent + trimmed.length() <= kMinDecimalPower) {
|
||||
*guess = 0.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DoubleStrtod(trimmed, exponent, guess) ||
|
||||
DiyFpStrtod(trimmed, exponent, guess)) {
|
||||
return true;
|
||||
}
|
||||
if (*guess == Double::Infinity()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
double Strtod(Vector<const char> buffer, int exponent) {
|
||||
char copy_buffer[kMaxSignificantDecimalDigits];
|
||||
Vector<const char> trimmed;
|
||||
int updated_exponent;
|
||||
TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
|
||||
&trimmed, &updated_exponent);
|
||||
exponent = updated_exponent;
|
||||
|
||||
double guess;
|
||||
bool is_correct = ComputeGuess(trimmed, exponent, &guess);
|
||||
if (is_correct) return guess;
|
||||
|
||||
DiyFp upper_boundary = Double(guess).UpperBoundary();
|
||||
int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary);
|
||||
if (comparison < 0) {
|
||||
return guess;
|
||||
} else if (comparison > 0) {
|
||||
return Double(guess).NextDouble();
|
||||
} else if ((Double(guess).Significand() & 1) == 0) {
|
||||
// Round towards even.
|
||||
return guess;
|
||||
} else {
|
||||
return Double(guess).NextDouble();
|
||||
}
|
||||
}
|
||||
|
||||
float Strtof(Vector<const char> buffer, int exponent) {
|
||||
char copy_buffer[kMaxSignificantDecimalDigits];
|
||||
Vector<const char> trimmed;
|
||||
int updated_exponent;
|
||||
TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits,
|
||||
&trimmed, &updated_exponent);
|
||||
exponent = updated_exponent;
|
||||
|
||||
double double_guess;
|
||||
bool is_correct = ComputeGuess(trimmed, exponent, &double_guess);
|
||||
|
||||
float float_guess = static_cast<float>(double_guess);
|
||||
if (float_guess == double_guess) {
|
||||
// This shortcut triggers for integer values.
|
||||
return float_guess;
|
||||
}
|
||||
|
||||
// We must catch double-rounding. Say the double has been rounded up, and is
|
||||
// now a boundary of a float, and rounds up again. This is why we have to
|
||||
// look at previous too.
|
||||
// Example (in decimal numbers):
|
||||
// input: 12349
|
||||
// high-precision (4 digits): 1235
|
||||
// low-precision (3 digits):
|
||||
// when read from input: 123
|
||||
// when rounded from high precision: 124.
|
||||
// To do this we simply look at the neighbors of the correct result and see
|
||||
// if they would round to the same float. If the guess is not correct we have
|
||||
// to look at four values (since two different doubles could be the correct
|
||||
// double).
|
||||
|
||||
double double_next = Double(double_guess).NextDouble();
|
||||
double double_previous = Double(double_guess).PreviousDouble();
|
||||
|
||||
float f1 = static_cast<float>(double_previous);
|
||||
float f2 = float_guess;
|
||||
float f3 = static_cast<float>(double_next);
|
||||
float f4;
|
||||
if (is_correct) {
|
||||
f4 = f3;
|
||||
} else {
|
||||
double double_next2 = Double(double_next).NextDouble();
|
||||
f4 = static_cast<float>(double_next2);
|
||||
}
|
||||
(void) f2; // Mark variable as used.
|
||||
ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4);
|
||||
|
||||
// If the guess doesn't lie near a single-precision boundary we can simply
|
||||
// return its float-value.
|
||||
if (f1 == f4) {
|
||||
return float_guess;
|
||||
}
|
||||
|
||||
ASSERT((f1 != f2 && f2 == f3 && f3 == f4) ||
|
||||
(f1 == f2 && f2 != f3 && f3 == f4) ||
|
||||
(f1 == f2 && f2 == f3 && f3 != f4));
|
||||
|
||||
// guess and next are the two possible candidates (in the same way that
|
||||
// double_guess was the lower candidate for a double-precision guess).
|
||||
float guess = f1;
|
||||
float next = f4;
|
||||
DiyFp upper_boundary;
|
||||
if (guess == 0.0f) {
|
||||
float min_float = 1e-45f;
|
||||
upper_boundary = Double(static_cast<double>(min_float) / 2).AsDiyFp();
|
||||
} else {
|
||||
upper_boundary = Single(guess).UpperBoundary();
|
||||
}
|
||||
int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary);
|
||||
if (comparison < 0) {
|
||||
return guess;
|
||||
} else if (comparison > 0) {
|
||||
return next;
|
||||
} else if ((Single(guess).Significand() & 1) == 0) {
|
||||
// Round towards even.
|
||||
return guess;
|
||||
} else {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
@ -1,46 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_STRTOD_H_
|
||||
#define DOUBLE_CONVERSION_STRTOD_H_
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
namespace double_conversion
|
||||
{
|
||||
|
||||
// The buffer must only contain digits in the range [0-9]. It must not
|
||||
// contain a dot or a sign. It must not start with '0', and must not be empty.
|
||||
double Strtod(Vector<const char> buffer, int exponent);
|
||||
|
||||
// The buffer must only contain digits in the range [0-9]. It must not
|
||||
// contain a dot or a sign. It must not start with '0', and must not be empty.
|
||||
float Strtof(Vector<const char> buffer, int exponent);
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_STRTOD_H_
|
File diff suppressed because it is too large
Load Diff
@ -1,74 +0,0 @@
|
||||
/* header created automatically with -DGEN_TREES_H */
|
||||
|
||||
local const ct_data static_ltree[L_CODES + 2]
|
||||
= {{{12}, {8}}, {{140}, {8}}, {{76}, {8}}, {{204}, {8}}, {{44}, {8}}, {{172}, {8}}, {{108}, {8}}, {{236}, {8}}, {{28}, {8}},
|
||||
{{156}, {8}}, {{92}, {8}}, {{220}, {8}}, {{60}, {8}}, {{188}, {8}}, {{124}, {8}}, {{252}, {8}}, {{2}, {8}}, {{130}, {8}},
|
||||
{{66}, {8}}, {{194}, {8}}, {{34}, {8}}, {{162}, {8}}, {{98}, {8}}, {{226}, {8}}, {{18}, {8}}, {{146}, {8}}, {{82}, {8}},
|
||||
{{210}, {8}}, {{50}, {8}}, {{178}, {8}}, {{114}, {8}}, {{242}, {8}}, {{10}, {8}}, {{138}, {8}}, {{74}, {8}}, {{202}, {8}},
|
||||
{{42}, {8}}, {{170}, {8}}, {{106}, {8}}, {{234}, {8}}, {{26}, {8}}, {{154}, {8}}, {{90}, {8}}, {{218}, {8}}, {{58}, {8}},
|
||||
{{186}, {8}}, {{122}, {8}}, {{250}, {8}}, {{6}, {8}}, {{134}, {8}}, {{70}, {8}}, {{198}, {8}}, {{38}, {8}}, {{166}, {8}},
|
||||
{{102}, {8}}, {{230}, {8}}, {{22}, {8}}, {{150}, {8}}, {{86}, {8}}, {{214}, {8}}, {{54}, {8}}, {{182}, {8}}, {{118}, {8}},
|
||||
{{246}, {8}}, {{14}, {8}}, {{142}, {8}}, {{78}, {8}}, {{206}, {8}}, {{46}, {8}}, {{174}, {8}}, {{110}, {8}}, {{238}, {8}},
|
||||
{{30}, {8}}, {{158}, {8}}, {{94}, {8}}, {{222}, {8}}, {{62}, {8}}, {{190}, {8}}, {{126}, {8}}, {{254}, {8}}, {{1}, {8}},
|
||||
{{129}, {8}}, {{65}, {8}}, {{193}, {8}}, {{33}, {8}}, {{161}, {8}}, {{97}, {8}}, {{225}, {8}}, {{17}, {8}}, {{145}, {8}},
|
||||
{{81}, {8}}, {{209}, {8}}, {{49}, {8}}, {{177}, {8}}, {{113}, {8}}, {{241}, {8}}, {{9}, {8}}, {{137}, {8}}, {{73}, {8}},
|
||||
{{201}, {8}}, {{41}, {8}}, {{169}, {8}}, {{105}, {8}}, {{233}, {8}}, {{25}, {8}}, {{153}, {8}}, {{89}, {8}}, {{217}, {8}},
|
||||
{{57}, {8}}, {{185}, {8}}, {{121}, {8}}, {{249}, {8}}, {{5}, {8}}, {{133}, {8}}, {{69}, {8}}, {{197}, {8}}, {{37}, {8}},
|
||||
{{165}, {8}}, {{101}, {8}}, {{229}, {8}}, {{21}, {8}}, {{149}, {8}}, {{85}, {8}}, {{213}, {8}}, {{53}, {8}}, {{181}, {8}},
|
||||
{{117}, {8}}, {{245}, {8}}, {{13}, {8}}, {{141}, {8}}, {{77}, {8}}, {{205}, {8}}, {{45}, {8}}, {{173}, {8}}, {{109}, {8}},
|
||||
{{237}, {8}}, {{29}, {8}}, {{157}, {8}}, {{93}, {8}}, {{221}, {8}}, {{61}, {8}}, {{189}, {8}}, {{125}, {8}}, {{253}, {8}},
|
||||
{{19}, {9}}, {{275}, {9}}, {{147}, {9}}, {{403}, {9}}, {{83}, {9}}, {{339}, {9}}, {{211}, {9}}, {{467}, {9}}, {{51}, {9}},
|
||||
{{307}, {9}}, {{179}, {9}}, {{435}, {9}}, {{115}, {9}}, {{371}, {9}}, {{243}, {9}}, {{499}, {9}}, {{11}, {9}}, {{267}, {9}},
|
||||
{{139}, {9}}, {{395}, {9}}, {{75}, {9}}, {{331}, {9}}, {{203}, {9}}, {{459}, {9}}, {{43}, {9}}, {{299}, {9}}, {{171}, {9}},
|
||||
{{427}, {9}}, {{107}, {9}}, {{363}, {9}}, {{235}, {9}}, {{491}, {9}}, {{27}, {9}}, {{283}, {9}}, {{155}, {9}}, {{411}, {9}},
|
||||
{{91}, {9}}, {{347}, {9}}, {{219}, {9}}, {{475}, {9}}, {{59}, {9}}, {{315}, {9}}, {{187}, {9}}, {{443}, {9}}, {{123}, {9}},
|
||||
{{379}, {9}}, {{251}, {9}}, {{507}, {9}}, {{7}, {9}}, {{263}, {9}}, {{135}, {9}}, {{391}, {9}}, {{71}, {9}}, {{327}, {9}},
|
||||
{{199}, {9}}, {{455}, {9}}, {{39}, {9}}, {{295}, {9}}, {{167}, {9}}, {{423}, {9}}, {{103}, {9}}, {{359}, {9}}, {{231}, {9}},
|
||||
{{487}, {9}}, {{23}, {9}}, {{279}, {9}}, {{151}, {9}}, {{407}, {9}}, {{87}, {9}}, {{343}, {9}}, {{215}, {9}}, {{471}, {9}},
|
||||
{{55}, {9}}, {{311}, {9}}, {{183}, {9}}, {{439}, {9}}, {{119}, {9}}, {{375}, {9}}, {{247}, {9}}, {{503}, {9}}, {{15}, {9}},
|
||||
{{271}, {9}}, {{143}, {9}}, {{399}, {9}}, {{79}, {9}}, {{335}, {9}}, {{207}, {9}}, {{463}, {9}}, {{47}, {9}}, {{303}, {9}},
|
||||
{{175}, {9}}, {{431}, {9}}, {{111}, {9}}, {{367}, {9}}, {{239}, {9}}, {{495}, {9}}, {{31}, {9}}, {{287}, {9}}, {{159}, {9}},
|
||||
{{415}, {9}}, {{95}, {9}}, {{351}, {9}}, {{223}, {9}}, {{479}, {9}}, {{63}, {9}}, {{319}, {9}}, {{191}, {9}}, {{447}, {9}},
|
||||
{{127}, {9}}, {{383}, {9}}, {{255}, {9}}, {{511}, {9}}, {{0}, {7}}, {{64}, {7}}, {{32}, {7}}, {{96}, {7}}, {{16}, {7}},
|
||||
{{80}, {7}}, {{48}, {7}}, {{112}, {7}}, {{8}, {7}}, {{72}, {7}}, {{40}, {7}}, {{104}, {7}}, {{24}, {7}}, {{88}, {7}},
|
||||
{{56}, {7}}, {{120}, {7}}, {{4}, {7}}, {{68}, {7}}, {{36}, {7}}, {{100}, {7}}, {{20}, {7}}, {{84}, {7}}, {{52}, {7}},
|
||||
{{116}, {7}}, {{3}, {8}}, {{131}, {8}}, {{67}, {8}}, {{195}, {8}}, {{35}, {8}}, {{163}, {8}}, {{99}, {8}}, {{227}, {8}}};
|
||||
|
||||
local const ct_data static_dtree[D_CODES]
|
||||
= {{{0}, {5}}, {{16}, {5}}, {{8}, {5}}, {{24}, {5}}, {{4}, {5}}, {{20}, {5}}, {{12}, {5}}, {{28}, {5}}, {{2}, {5}}, {{18}, {5}},
|
||||
{{10}, {5}}, {{26}, {5}}, {{6}, {5}}, {{22}, {5}}, {{14}, {5}}, {{30}, {5}}, {{1}, {5}}, {{17}, {5}}, {{9}, {5}}, {{25}, {5}},
|
||||
{{5}, {5}}, {{21}, {5}}, {{13}, {5}}, {{29}, {5}}, {{3}, {5}}, {{19}, {5}}, {{11}, {5}}, {{27}, {5}}, {{7}, {5}}, {{23}, {5}}};
|
||||
|
||||
const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN]
|
||||
= {0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29};
|
||||
|
||||
const uch ZLIB_INTERNAL _length_code[MAX_MATCH - MIN_MATCH + 1]
|
||||
= {0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19,
|
||||
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28};
|
||||
|
||||
local const int base_length[LENGTH_CODES]
|
||||
= {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0};
|
||||
|
||||
local const int base_dist[D_CODES] = {0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128,
|
||||
192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576};
|
@ -1,311 +0,0 @@
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DOUBLE_CONVERSION_UTILS_H_
|
||||
#define DOUBLE_CONVERSION_UTILS_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <assert.h>
|
||||
#ifndef ASSERT
|
||||
# define ASSERT(condition) assert(condition);
|
||||
#endif
|
||||
#ifndef UNIMPLEMENTED
|
||||
# define UNIMPLEMENTED() (abort())
|
||||
#endif
|
||||
#ifndef UNREACHABLE
|
||||
# define UNREACHABLE() (abort())
|
||||
#endif
|
||||
|
||||
// Double operations detection based on target architecture.
|
||||
// Linux uses a 80bit wide floating point stack on x86. This induces double
|
||||
// rounding, which in turn leads to wrong results.
|
||||
// An easy way to test if the floating-point operations are correct is to
|
||||
// evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then
|
||||
// the result is equal to 89255e-22.
|
||||
// The best way to test this, is to create a division-function and to compare
|
||||
// the output of the division with the expected result. (Inlining must be
|
||||
// disabled.)
|
||||
// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
|
||||
#if defined(_M_X64) || defined(__x86_64__) || defined(__ARMEL__) || defined(_M_ARM) || defined(__arm__) || defined(__arm64__) \
|
||||
|| defined(__avr32__) || defined(__hppa__) || defined(__ia64__) || defined(__mips__) || defined(__powerpc__) || defined(__ppc__) \
|
||||
|| defined(__ppc64__) || defined(__sparc__) || defined(__sparc) || defined(__s390__) || defined(__SH4__) || defined(__alpha__) \
|
||||
|| defined(_MIPS_ARCH_MIPS32R2) || defined(__riscv) || defined(__AARCH64EL__) || defined(nios2) || defined(__nios2) \
|
||||
|| defined(__nios2__)
|
||||
# define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
|
||||
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
|
||||
# undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
|
||||
#else
|
||||
# error Target architecture was not detected as supported by Double-Conversion.
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define DOUBLE_CONVERSION_UNUSED
|
||||
#endif
|
||||
|
||||
|
||||
# include <stdint.h>
|
||||
|
||||
|
||||
// The following macro works on both 32 and 64-bit platforms.
|
||||
// Usage: instead of writing 0x1234567890123456
|
||||
// write UINT64_2PART_C(0x12345678,90123456);
|
||||
#define UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
|
||||
|
||||
|
||||
// The expression ARRAY_SIZE(a) is a compile-time constant of type
|
||||
// size_t which represents the number of elements of the given
|
||||
// array. You should only use ARRAY_SIZE on statically allocated
|
||||
// arrays.
|
||||
#ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(a) ((sizeof(a) / sizeof(*(a))) / static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
|
||||
#endif
|
||||
|
||||
// A macro to disallow the evil copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#ifndef DISALLOW_COPY_AND_ASSIGN
|
||||
# define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName &); \
|
||||
void operator=(const TypeName &)
|
||||
#endif
|
||||
|
||||
// A macro to disallow all the implicit constructors, namely the
|
||||
// default constructor, copy constructor and operator= functions.
|
||||
//
|
||||
// This should be used in the private: declarations for a class
|
||||
// that wants to prevent anyone from instantiating it. This is
|
||||
// especially useful for classes containing only static methods.
|
||||
#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
|
||||
# define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
|
||||
TypeName(); \
|
||||
DISALLOW_COPY_AND_ASSIGN(TypeName)
|
||||
#endif
|
||||
|
||||
namespace double_conversion
|
||||
{
|
||||
|
||||
static const int kCharSize = sizeof(char);
|
||||
|
||||
// Returns the maximum of the two parameters.
|
||||
template <typename T>
|
||||
static T Max(T a, T b)
|
||||
{
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
|
||||
// Returns the minimum of the two parameters.
|
||||
template <typename T>
|
||||
static T Min(T a, T b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
|
||||
inline int StrLength(const char * string)
|
||||
{
|
||||
size_t length = strlen(string);
|
||||
ASSERT(length == static_cast<size_t>(static_cast<int>(length)));
|
||||
return static_cast<int>(length);
|
||||
}
|
||||
|
||||
// This is a simplified version of V8's Vector class.
|
||||
template <typename T>
|
||||
class Vector
|
||||
{
|
||||
public:
|
||||
Vector() : start_(NULL), length_(0) { }
|
||||
Vector(T * data, int length) : start_(data), length_(length) { ASSERT(length == 0 || (length > 0 && data != NULL)); }
|
||||
|
||||
// Returns a vector using the same backing storage as this one,
|
||||
// spanning from and including 'from', to but not including 'to'.
|
||||
Vector<T> SubVector(int from, int to)
|
||||
{
|
||||
ASSERT(to <= length_);
|
||||
ASSERT(from < to);
|
||||
ASSERT(0 <= from);
|
||||
return Vector<T>(start() + from, to - from);
|
||||
}
|
||||
|
||||
// Returns the length of the vector.
|
||||
int length() const { return length_; }
|
||||
|
||||
// Returns whether or not the vector is empty.
|
||||
bool is_empty() const { return length_ == 0; }
|
||||
|
||||
// Returns the pointer to the start of the data in the vector.
|
||||
T * start() const { return start_; }
|
||||
|
||||
// Access individual vector elements - checks bounds in debug mode.
|
||||
T & operator[](int index) const
|
||||
{
|
||||
ASSERT(0 <= index && index < length_);
|
||||
return start_[index];
|
||||
}
|
||||
|
||||
T & first() { return start_[0]; }
|
||||
|
||||
T & last() { return start_[length_ - 1]; }
|
||||
|
||||
private:
|
||||
T * start_;
|
||||
int length_;
|
||||
};
|
||||
|
||||
|
||||
// Helper class for building result strings in a character buffer. The
|
||||
// purpose of the class is to use safe operations that checks the
|
||||
// buffer bounds on all operations in debug mode.
|
||||
class StringBuilder
|
||||
{
|
||||
public:
|
||||
StringBuilder(char * buffer, int size) : buffer_(buffer, size), position_(0) { }
|
||||
|
||||
~StringBuilder()
|
||||
{
|
||||
if (!is_finalized())
|
||||
Finalize();
|
||||
}
|
||||
|
||||
int size() const { return buffer_.length(); }
|
||||
|
||||
// Get the current position in the builder.
|
||||
int position() const
|
||||
{
|
||||
ASSERT(!is_finalized());
|
||||
return position_;
|
||||
}
|
||||
|
||||
// Reset the position.
|
||||
void Reset() { position_ = 0; }
|
||||
|
||||
// Add a single character to the builder. It is not allowed to add
|
||||
// 0-characters; use the Finalize() method to terminate the string
|
||||
// instead.
|
||||
void AddCharacter(char c)
|
||||
{
|
||||
ASSERT(c != '\0');
|
||||
ASSERT(!is_finalized() && position_ < buffer_.length());
|
||||
buffer_[position_++] = c;
|
||||
}
|
||||
|
||||
// Add an entire string to the builder. Uses strlen() internally to
|
||||
// compute the length of the input string.
|
||||
void AddString(const char * s) { AddSubstring(s, StrLength(s)); }
|
||||
|
||||
// Add the first 'n' characters of the given string 's' to the
|
||||
// builder. The input string must have enough characters.
|
||||
void AddSubstring(const char * s, int n)
|
||||
{
|
||||
ASSERT(!is_finalized() && position_ + n < buffer_.length());
|
||||
ASSERT(static_cast<size_t>(n) <= strlen(s));
|
||||
memmove(&buffer_[position_], s, n * kCharSize);
|
||||
position_ += n;
|
||||
}
|
||||
|
||||
|
||||
// Add character padding to the builder. If count is non-positive,
|
||||
// nothing is added to the builder.
|
||||
void AddPadding(char c, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
AddCharacter(c);
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize the string by 0-terminating it and returning the buffer.
|
||||
char * Finalize()
|
||||
{
|
||||
ASSERT(!is_finalized() && position_ < buffer_.length());
|
||||
buffer_[position_] = '\0';
|
||||
// Make sure nobody managed to add a 0-character to the
|
||||
// buffer while building the string.
|
||||
ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));
|
||||
position_ = -1;
|
||||
ASSERT(is_finalized());
|
||||
return buffer_.start();
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<char> buffer_;
|
||||
int position_;
|
||||
|
||||
bool is_finalized() const { return position_ < 0; }
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
|
||||
};
|
||||
|
||||
// The type-based aliasing rule allows the compiler to assume that pointers of
|
||||
// different types (for some definition of different) never alias each other.
|
||||
// Thus the following code does not work:
|
||||
//
|
||||
// float f = foo();
|
||||
// int fbits = *(int*)(&f);
|
||||
//
|
||||
// The compiler 'knows' that the int pointer can't refer to f since the types
|
||||
// don't match, so the compiler may cache f in a register, leaving random data
|
||||
// in fbits. Using C++ style casts makes no difference, however a pointer to
|
||||
// char data is assumed to alias any other pointer. This is the 'memcpy
|
||||
// exception'.
|
||||
//
|
||||
// Bit_cast uses the memcpy exception to move the bits from a variable of one
|
||||
// type of a variable of another type. Of course the end result is likely to
|
||||
// be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005)
|
||||
// will completely optimize BitCast away.
|
||||
//
|
||||
// There is an additional use for BitCast.
|
||||
// Recent gccs will warn when they see casts that may result in breakage due to
|
||||
// the type-based aliasing rule. If you have checked that there is no breakage
|
||||
// you can use BitCast to cast one pointer type to another. This confuses gcc
|
||||
// enough that it can no longer see that you have cast one pointer type to
|
||||
// another thus avoiding the warning.
|
||||
template <class Dest, class Source>
|
||||
inline Dest BitCast(const Source & source)
|
||||
{
|
||||
// Compile time assertion: sizeof(Dest) == sizeof(Source)
|
||||
// A compile error here means your Dest and Source have different sizes.
|
||||
DOUBLE_CONVERSION_UNUSED
|
||||
typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
|
||||
|
||||
Dest dest;
|
||||
memmove(&dest, &source, sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
|
||||
template <class Dest, class Source>
|
||||
inline Dest BitCast(Source * source)
|
||||
{
|
||||
return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));
|
||||
}
|
||||
|
||||
} // namespace double_conversion
|
||||
|
||||
#endif // DOUBLE_CONVERSION_UTILS_H_
|
@ -1,324 +0,0 @@
|
||||
/* zutil.c -- target dependent utility functions for the compression library
|
||||
* Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id: //poco/1.4/Foundation/src/zutil.c#3 $ */
|
||||
|
||||
#include "zutil.h"
|
||||
#ifndef Z_SOLO
|
||||
# include "gzguts.h"
|
||||
#endif
|
||||
|
||||
#ifndef NO_DUMMY_DECL
|
||||
struct internal_state {int dummy;}; /* for buggy compilers */
|
||||
#endif
|
||||
|
||||
z_const char * const z_errmsg[10] = {
|
||||
"need dictionary", /* Z_NEED_DICT 2 */
|
||||
"stream end", /* Z_STREAM_END 1 */
|
||||
"", /* Z_OK 0 */
|
||||
"file error", /* Z_ERRNO (-1) */
|
||||
"stream error", /* Z_STREAM_ERROR (-2) */
|
||||
"data error", /* Z_DATA_ERROR (-3) */
|
||||
"insufficient memory", /* Z_MEM_ERROR (-4) */
|
||||
"buffer error", /* Z_BUF_ERROR (-5) */
|
||||
"incompatible version",/* Z_VERSION_ERROR (-6) */
|
||||
""};
|
||||
|
||||
|
||||
const char * ZEXPORT zlibVersion()
|
||||
{
|
||||
return ZLIB_VERSION;
|
||||
}
|
||||
|
||||
uLong ZEXPORT zlibCompileFlags()
|
||||
{
|
||||
uLong flags;
|
||||
|
||||
flags = 0;
|
||||
switch ((int)(sizeof(uInt))) {
|
||||
case 2: break;
|
||||
case 4: flags += 1; break;
|
||||
case 8: flags += 2; break;
|
||||
default: flags += 3;
|
||||
}
|
||||
switch ((int)(sizeof(uLong))) {
|
||||
case 2: break;
|
||||
case 4: flags += 1 << 2; break;
|
||||
case 8: flags += 2 << 2; break;
|
||||
default: flags += 3 << 2;
|
||||
}
|
||||
switch ((int)(sizeof(voidpf))) {
|
||||
case 2: break;
|
||||
case 4: flags += 1 << 4; break;
|
||||
case 8: flags += 2 << 4; break;
|
||||
default: flags += 3 << 4;
|
||||
}
|
||||
switch ((int)(sizeof(z_off_t))) {
|
||||
case 2: break;
|
||||
case 4: flags += 1 << 6; break;
|
||||
case 8: flags += 2 << 6; break;
|
||||
default: flags += 3 << 6;
|
||||
}
|
||||
#ifdef ZLIB_DEBUG
|
||||
flags += 1 << 8;
|
||||
#endif
|
||||
#if defined(ASMV) || defined(ASMINF)
|
||||
flags += 1 << 9;
|
||||
#endif
|
||||
#ifdef ZLIB_WINAPI
|
||||
flags += 1 << 10;
|
||||
#endif
|
||||
#ifdef BUILDFIXED
|
||||
flags += 1 << 12;
|
||||
#endif
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
flags += 1 << 13;
|
||||
#endif
|
||||
#ifdef NO_GZCOMPRESS
|
||||
flags += 1L << 16;
|
||||
#endif
|
||||
#ifdef NO_GZIP
|
||||
flags += 1L << 17;
|
||||
#endif
|
||||
#ifdef PKZIP_BUG_WORKAROUND
|
||||
flags += 1L << 20;
|
||||
#endif
|
||||
#ifdef FASTEST
|
||||
flags += 1L << 21;
|
||||
#endif
|
||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
# ifdef NO_vsnprintf
|
||||
flags += 1L << 25;
|
||||
# ifdef HAS_vsprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_vsnprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
flags += 1L << 24;
|
||||
# ifdef NO_snprintf
|
||||
flags += 1L << 25;
|
||||
# ifdef HAS_sprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_snprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
return flags;
|
||||
}
|
||||
|
||||
#ifdef ZLIB_DEBUG
|
||||
|
||||
# ifndef verbose
|
||||
# define verbose 0
|
||||
# endif
|
||||
int ZLIB_INTERNAL z_verbose = verbose;
|
||||
|
||||
void ZLIB_INTERNAL z_error (m)
|
||||
char *m;
|
||||
{
|
||||
fprintf(stderr, "%s\n", m);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* exported to allow conversion of error code to string for compress() and
|
||||
* uncompress()
|
||||
*/
|
||||
const char * ZEXPORT zError(err)
|
||||
int err;
|
||||
{
|
||||
return ERR_MSG(err);
|
||||
}
|
||||
|
||||
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
|
||||
/* The Microsoft C Run-Time Library for Windows CE doesn't have
|
||||
* errno. We define it as a global variable to simplify porting.
|
||||
* Its value is always 0 and should not be used.
|
||||
*/
|
||||
int errno = 0;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MEMCPY
|
||||
|
||||
void ZLIB_INTERNAL zmemcpy(dest, source, len)
|
||||
Bytef* dest;
|
||||
const Bytef* source;
|
||||
uInt len;
|
||||
{
|
||||
if (len == 0) return;
|
||||
do {
|
||||
*dest++ = *source++; /* ??? to be unrolled */
|
||||
} while (--len != 0);
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL zmemcmp(s1, s2, len)
|
||||
const Bytef* s1;
|
||||
const Bytef* s2;
|
||||
uInt len;
|
||||
{
|
||||
uInt j;
|
||||
|
||||
for (j = 0; j < len; j++) {
|
||||
if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL zmemzero(dest, len)
|
||||
Bytef* dest;
|
||||
uInt len;
|
||||
{
|
||||
if (len == 0) return;
|
||||
do {
|
||||
*dest++ = 0; /* ??? to be unrolled */
|
||||
} while (--len != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef Z_SOLO
|
||||
|
||||
#ifdef SYS16BIT
|
||||
|
||||
#ifdef __TURBOC__
|
||||
/* Turbo C in 16-bit mode */
|
||||
|
||||
# define MY_ZCALLOC
|
||||
|
||||
/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
|
||||
* and farmalloc(64K) returns a pointer with an offset of 8, so we
|
||||
* must fix the pointer. Warning: the pointer must be put back to its
|
||||
* original form in order to free it, use zcfree().
|
||||
*/
|
||||
|
||||
#define MAX_PTR 10
|
||||
/* 10*64K = 640K */
|
||||
|
||||
local int next_ptr = 0;
|
||||
|
||||
typedef struct ptr_table_s {
|
||||
voidpf org_ptr;
|
||||
voidpf new_ptr;
|
||||
} ptr_table;
|
||||
|
||||
local ptr_table table[MAX_PTR];
|
||||
/* This table is used to remember the original form of pointers
|
||||
* to large buffers (64K). Such pointers are normalized with a zero offset.
|
||||
* Since MS-DOS is not a preemptive multitasking OS, this table is not
|
||||
* protected from concurrent access. This hack doesn't work anyway on
|
||||
* a protected system like OS/2. Use Microsoft C instead.
|
||||
*/
|
||||
|
||||
voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
|
||||
{
|
||||
voidpf buf = opaque; /* just to make some compilers happy */
|
||||
ulg bsize = (ulg)items*size;
|
||||
|
||||
/* If we allocate less than 65520 bytes, we assume that farmalloc
|
||||
* will return a usable pointer which doesn't have to be normalized.
|
||||
*/
|
||||
if (bsize < 65520L) {
|
||||
buf = farmalloc(bsize);
|
||||
if (*(ush*)&buf != 0) return buf;
|
||||
} else {
|
||||
buf = farmalloc(bsize + 16L);
|
||||
}
|
||||
if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
|
||||
table[next_ptr].org_ptr = buf;
|
||||
|
||||
/* Normalize the pointer to seg:0 */
|
||||
*((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
|
||||
*(ush*)&buf = 0;
|
||||
table[next_ptr++].new_ptr = buf;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
|
||||
{
|
||||
int n;
|
||||
if (*(ush*)&ptr != 0) { /* object < 64K */
|
||||
farfree(ptr);
|
||||
return;
|
||||
}
|
||||
/* Find the original pointer */
|
||||
for (n = 0; n < next_ptr; n++) {
|
||||
if (ptr != table[n].new_ptr) continue;
|
||||
|
||||
farfree(table[n].org_ptr);
|
||||
while (++n < next_ptr) {
|
||||
table[n-1] = table[n];
|
||||
}
|
||||
next_ptr--;
|
||||
return;
|
||||
}
|
||||
ptr = opaque; /* just to make some compilers happy */
|
||||
Assert(0, "zcfree: ptr not found");
|
||||
}
|
||||
|
||||
#endif /* __TURBOC__ */
|
||||
|
||||
|
||||
#ifdef M_I86
|
||||
/* Microsoft C in 16-bit mode */
|
||||
|
||||
# define MY_ZCALLOC
|
||||
|
||||
#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
|
||||
# define _halloc halloc
|
||||
# define _hfree hfree
|
||||
#endif
|
||||
|
||||
voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
|
||||
{
|
||||
if (opaque) opaque = 0; /* to make compiler happy */
|
||||
return _halloc((long)items, size);
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
|
||||
{
|
||||
if (opaque) opaque = 0; /* to make compiler happy */
|
||||
_hfree(ptr);
|
||||
}
|
||||
|
||||
#endif /* M_I86 */
|
||||
|
||||
#endif /* SYS16BIT */
|
||||
|
||||
|
||||
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
|
||||
|
||||
#ifndef STDC
|
||||
extern voidp malloc OF((uInt size));
|
||||
extern voidp calloc OF((uInt items, uInt size));
|
||||
extern void free OF((voidpf ptr));
|
||||
#endif
|
||||
|
||||
voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
|
||||
voidpf opaque;
|
||||
unsigned items;
|
||||
unsigned size;
|
||||
{
|
||||
if (opaque) items += size - size; /* make compiler happy */
|
||||
return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
|
||||
(voidpf)calloc(items, size);
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL zcfree (opaque, ptr)
|
||||
voidpf opaque;
|
||||
voidpf ptr;
|
||||
{
|
||||
free(ptr);
|
||||
if (opaque) return; /* make compiler happy */
|
||||
}
|
||||
|
||||
#endif /* MY_ZCALLOC */
|
||||
|
||||
#endif /* !Z_SOLO */
|
@ -1,237 +0,0 @@
|
||||
/* zutil.h -- internal interface and configuration of the compression library
|
||||
* Copyright (C) 1995-2013 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* @(#) $Id: //poco/1.4/Foundation/src/zutil.h#3 $ */
|
||||
|
||||
#ifndef ZUTIL_H
|
||||
#define ZUTIL_H
|
||||
|
||||
#ifdef HAVE_HIDDEN
|
||||
# define ZLIB_INTERNAL __attribute__((visibility("hidden")))
|
||||
#else
|
||||
# define ZLIB_INTERNAL
|
||||
#endif
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
#if defined(STDC) && !defined(Z_SOLO)
|
||||
# include <stddef.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef Z_SOLO
|
||||
typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
/* compile with -Dlocal if your debugger can't find static symbols */
|
||||
|
||||
typedef unsigned char uch;
|
||||
typedef uch FAR uchf;
|
||||
typedef unsigned short ush;
|
||||
typedef ush FAR ushf;
|
||||
typedef unsigned long ulg;
|
||||
|
||||
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||
/* (size given to avoid silly warnings with Visual C++) */
|
||||
|
||||
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT - (err)]
|
||||
|
||||
#define ERR_RETURN(strm, err) return (strm->msg = ERR_MSG(err), (err))
|
||||
/* To be used only when the state is known to be valid */
|
||||
|
||||
/* common constants */
|
||||
|
||||
#ifndef DEF_WBITS
|
||||
# define DEF_WBITS MAX_WBITS
|
||||
#endif
|
||||
/* default windowBits for decompression. MAX_WBITS is for compression only */
|
||||
|
||||
#if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
#else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
#endif
|
||||
/* default memLevel */
|
||||
|
||||
#define STORED_BLOCK 0
|
||||
#define STATIC_TREES 1
|
||||
#define DYN_TREES 2
|
||||
/* The three kinds of block type */
|
||||
|
||||
#define MIN_MATCH 3
|
||||
#define MAX_MATCH 258
|
||||
/* The minimum and maximum match lengths */
|
||||
|
||||
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
|
||||
|
||||
/* target dependencies */
|
||||
|
||||
#ifdef AMIGA
|
||||
# define OS_CODE 0x01
|
||||
#endif
|
||||
|
||||
#if defined(VAXC) || defined(VMS)
|
||||
# define OS_CODE 0x02
|
||||
# define F_OPEN(name, mode) fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
|
||||
#endif
|
||||
|
||||
#if defined(ATARI) || defined(atarist)
|
||||
# define OS_CODE 0x05
|
||||
#endif
|
||||
|
||||
#ifdef OS2
|
||||
# define OS_CODE 0x06
|
||||
# if defined(M_I86) && !defined(Z_SOLO)
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MACOS) || defined(TARGET_OS_MAC)
|
||||
# define OS_CODE 0x07
|
||||
# ifndef Z_SOLO
|
||||
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
|
||||
# include <unix.h> /* for fdopen */
|
||||
# else
|
||||
# ifndef fdopen
|
||||
# define fdopen(fd, mode) NULL /* No fdopen() */
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef TOPS20
|
||||
# define OS_CODE 0x0a
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# define OS_CODE 0x0b
|
||||
#endif
|
||||
|
||||
#ifdef __50SERIES /* Prime/PRIMOS */
|
||||
# define OS_CODE 0x0f
|
||||
#endif
|
||||
|
||||
#if defined(_BEOS_) || defined(RISCOS)
|
||||
# define fdopen(fd, mode) NULL /* No fdopen() */
|
||||
#endif
|
||||
|
||||
|
||||
/* provide prototypes for these when building zlib without LFS */
|
||||
#if !defined(_WIN32) && (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE - 0 == 0)
|
||||
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
|
||||
#endif
|
||||
|
||||
/* common defaults */
|
||||
|
||||
#ifndef OS_CODE
|
||||
# define OS_CODE 0x03 /* assume Unix */
|
||||
#endif
|
||||
|
||||
#ifndef F_OPEN
|
||||
# define F_OPEN(name, mode) fopen((name), (mode))
|
||||
#endif
|
||||
|
||||
/* functions */
|
||||
|
||||
#if defined(pyr) || defined(Z_SOLO)
|
||||
# define NO_MEMCPY
|
||||
#endif
|
||||
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
|
||||
/* Use our own functions for small and medium model with MSC <= 5.0.
|
||||
* You may have to use the same strategy for Borland C (untested).
|
||||
* The __SC__ check is for Symantec.
|
||||
*/
|
||||
# define NO_MEMCPY
|
||||
#endif
|
||||
#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
|
||||
# define HAVE_MEMCPY
|
||||
#endif
|
||||
#ifdef HAVE_MEMCPY
|
||||
# ifdef SMALL_MEDIUM /* MS-DOS small or medium model */
|
||||
# define zmemcpy _fmemcpy
|
||||
# define zmemcmp _fmemcmp
|
||||
# define zmemzero(dest, len) _fmemset(dest, 0, len)
|
||||
# else
|
||||
# define zmemcpy memcpy
|
||||
# define zmemcmp memcmp
|
||||
# define zmemzero(dest, len) memset(dest, 0, len)
|
||||
# endif
|
||||
#else
|
||||
void ZLIB_INTERNAL zmemcpy OF((Bytef * dest, const Bytef * source, uInt len));
|
||||
int ZLIB_INTERNAL zmemcmp OF((const Bytef * s1, const Bytef * s2, uInt len));
|
||||
void ZLIB_INTERNAL zmemzero OF((Bytef * dest, uInt len));
|
||||
#endif
|
||||
|
||||
/* Diagnostic functions */
|
||||
#ifdef ZLIB_DEBUG
|
||||
# include <stdio.h>
|
||||
extern int ZLIB_INTERNAL z_verbose;
|
||||
extern void ZLIB_INTERNAL z_error OF((char * m));
|
||||
# define Assert(cond, msg) \
|
||||
{ \
|
||||
if (!(cond)) \
|
||||
z_error(msg); \
|
||||
}
|
||||
# define Trace(x) \
|
||||
{ \
|
||||
if (z_verbose >= 0) \
|
||||
fprintf x; \
|
||||
}
|
||||
# define Tracev(x) \
|
||||
{ \
|
||||
if (z_verbose > 0) \
|
||||
fprintf x; \
|
||||
}
|
||||
# define Tracevv(x) \
|
||||
{ \
|
||||
if (z_verbose > 1) \
|
||||
fprintf x; \
|
||||
}
|
||||
# define Tracec(c, x) \
|
||||
{ \
|
||||
if (z_verbose > 0 && (c)) \
|
||||
fprintf x; \
|
||||
}
|
||||
# define Tracecv(c, x) \
|
||||
{ \
|
||||
if (z_verbose > 1 && (c)) \
|
||||
fprintf x; \
|
||||
}
|
||||
#else
|
||||
# define Assert(cond, msg)
|
||||
# define Trace(x)
|
||||
# define Tracev(x)
|
||||
# define Tracevv(x)
|
||||
# define Tracec(c, x)
|
||||
# define Tracecv(c, x)
|
||||
#endif
|
||||
|
||||
#ifndef Z_SOLO
|
||||
voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, unsigned size));
|
||||
void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
|
||||
#endif
|
||||
|
||||
#define ZALLOC(strm, items, size) (*((strm)->zalloc))((strm)->opaque, (items), (size))
|
||||
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
|
||||
#define TRY_FREE(s, p) \
|
||||
{ \
|
||||
if (p) \
|
||||
ZFREE(s, p); \
|
||||
}
|
||||
|
||||
/* Reverse the bytes in a 32-bit value */
|
||||
#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + (((q)&0xff00) << 8) + (((q)&0xff) << 24))
|
||||
|
||||
#endif /* ZUTIL_H */
|
2
contrib/llvm-project
vendored
2
contrib/llvm-project
vendored
@ -1 +1 @@
|
||||
Subproject commit e0accd517933ebb44aff84bc8db448ffd8ef1929
|
||||
Subproject commit 2aedf7598a4040b23881dbe05b6afaca25a337ef
|
2
contrib/zstd
vendored
2
contrib/zstd
vendored
@ -1 +1 @@
|
||||
Subproject commit 945f27758c0fd67b636103a38dbf050266c6b90a
|
||||
Subproject commit 63779c798237346c2b245c546c40b72a5a5913fe
|
@ -151,5 +151,9 @@
|
||||
"name": "clickhouse/docs-builder",
|
||||
"dependent": [
|
||||
]
|
||||
},
|
||||
"docker/test/sqllogic": {
|
||||
"name": "clickhouse/sqllogic-test",
|
||||
"dependent": []
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +194,12 @@ function build
|
||||
{
|
||||
(
|
||||
cd "$FASTTEST_BUILD"
|
||||
time ninja clickhouse-bundle 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee "$FASTTEST_OUTPUT/build_log.txt"
|
||||
TIMEFORMAT=$'\nreal\t%3R\nuser\t%3U\nsys\t%3S'
|
||||
( time ninja clickhouse-bundle) |& ts '%Y-%m-%d %H:%M:%S' | tee "$FASTTEST_OUTPUT/build_log.txt"
|
||||
BUILD_SECONDS_ELAPSED=$(awk '/^....-..-.. ..:..:.. real\t[0-9]/ {print $4}' < "$FASTTEST_OUTPUT/build_log.txt")
|
||||
echo "build_clickhouse_fasttest_binary: [ OK ] $BUILD_SECONDS_ELAPSED sec." \
|
||||
| ts '%Y-%m-%d %H:%M:%S' \
|
||||
| tee "$FASTTEST_OUTPUT/test_result.txt"
|
||||
if [ "$COPY_CLICKHOUSE_BINARY_TO_OUTPUT" -eq "1" ]; then
|
||||
cp programs/clickhouse "$FASTTEST_OUTPUT/clickhouse"
|
||||
|
||||
@ -251,7 +256,7 @@ function run_tests
|
||||
)
|
||||
time clickhouse-test "${test_opts[@]}" -- "$FASTTEST_FOCUS" 2>&1 \
|
||||
| ts '%Y-%m-%d %H:%M:%S' \
|
||||
| tee "$FASTTEST_OUTPUT/test_result.txt"
|
||||
| tee -a "$FASTTEST_OUTPUT/test_result.txt"
|
||||
set -e
|
||||
|
||||
clickhouse stop --pid-path "$FASTTEST_DATA"
|
||||
|
@ -47,10 +47,9 @@ ENV TZ=Etc/UTC
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
ENV DOCKER_CHANNEL stable
|
||||
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
|
||||
RUN add-apt-repository "deb https://download.docker.com/linux/ubuntu $(lsb_release -c -s) ${DOCKER_CHANNEL}"
|
||||
|
||||
RUN apt-get update \
|
||||
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - \
|
||||
&& add-apt-repository "deb https://download.docker.com/linux/ubuntu $(lsb_release -c -s) ${DOCKER_CHANNEL}" \
|
||||
&& apt-get update \
|
||||
&& env DEBIAN_FRONTEND=noninteractive apt-get install --yes \
|
||||
docker-ce \
|
||||
&& rm -rf \
|
||||
@ -61,7 +60,7 @@ RUN apt-get update \
|
||||
|
||||
RUN dockerd --version; docker --version
|
||||
|
||||
RUN python3 -m pip install \
|
||||
RUN python3 -m pip install --no-cache-dir \
|
||||
PyMySQL \
|
||||
aerospike==4.0.0 \
|
||||
avro==1.10.2 \
|
||||
@ -104,8 +103,9 @@ COPY dockerd-entrypoint.sh /usr/local/bin/
|
||||
COPY compose/ /compose/
|
||||
COPY misc/ /misc/
|
||||
|
||||
RUN wget https://dlcdn.apache.org/spark/spark-3.3.2/spark-3.3.2-bin-hadoop3.tgz \
|
||||
&& tar xzvf spark-3.3.2-bin-hadoop3.tgz -C /
|
||||
RUN curl -fsSL -O https://dlcdn.apache.org/spark/spark-3.3.2/spark-3.3.2-bin-hadoop3.tgz \
|
||||
&& tar xzvf spark-3.3.2-bin-hadoop3.tgz -C / \
|
||||
&& rm spark-3.3.2-bin-hadoop3.tgz
|
||||
|
||||
# download spark and packages
|
||||
# if you change packages, don't forget to update them in tests/integration/helpers/cluster.py
|
||||
|
@ -16,7 +16,9 @@ echo '{
|
||||
# and on hung you can simply press Ctrl-C and it will spawn a python pdb,
|
||||
# but on SIGINT dockerd will exit, so ignore it to preserve the daemon.
|
||||
trap '' INT
|
||||
dockerd --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2375 --default-address-pool base=172.17.0.0/12,size=24 &>/ClickHouse/tests/integration/dockerd.log &
|
||||
# Binding to an IP address without --tlsverify is deprecated. Startup is intentionally being slowed
|
||||
# unless --tls=false or --tlsverify=false is set
|
||||
dockerd --host=unix:///var/run/docker.sock --tls=false --host=tcp://0.0.0.0:2375 --default-address-pool base=172.17.0.0/12,size=24 &>/ClickHouse/tests/integration/dockerd.log &
|
||||
|
||||
set +e
|
||||
reties=0
|
||||
|
45
docker/test/sqllogic/Dockerfile
Normal file
45
docker/test/sqllogic/Dockerfile
Normal file
@ -0,0 +1,45 @@
|
||||
# docker build -t clickhouse/sqllogic-test .
|
||||
ARG FROM_TAG=latest
|
||||
FROM clickhouse/test-base:$FROM_TAG
|
||||
|
||||
RUN apt-get update --yes \
|
||||
&& env DEBIAN_FRONTEND=noninteractive \
|
||||
apt-get install --yes --no-install-recommends \
|
||||
wget \
|
||||
git \
|
||||
python3 \
|
||||
python3-dev \
|
||||
python3-pip \
|
||||
sqlite3 \
|
||||
unixodbc \
|
||||
unixodbc-dev \
|
||||
sudo \
|
||||
&& apt-get clean
|
||||
|
||||
RUN pip3 install \
|
||||
numpy \
|
||||
pyodbc \
|
||||
deepdiff
|
||||
|
||||
ARG odbc_repo="https://github.com/ClickHouse/clickhouse-odbc.git"
|
||||
|
||||
RUN git clone --recursive ${odbc_repo} \
|
||||
&& mkdir -p /clickhouse-odbc/build \
|
||||
&& cmake -S /clickhouse-odbc -B /clickhouse-odbc/build \
|
||||
&& ls /clickhouse-odbc/build/driver \
|
||||
&& make -j 10 -C /clickhouse-odbc/build \
|
||||
&& ls /clickhouse-odbc/build/driver \
|
||||
&& mkdir -p /usr/local/lib64/ && cp /clickhouse-odbc/build/driver/lib*.so /usr/local/lib64/ \
|
||||
&& odbcinst -i -d -f /clickhouse-odbc/packaging/odbcinst.ini.sample \
|
||||
&& odbcinst -i -s -l -f /clickhouse-odbc/packaging/odbc.ini.sample
|
||||
|
||||
ENV TZ=Europe/Amsterdam
|
||||
ENV MAX_RUN_TIME=900
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
ARG sqllogic_test_repo="https://github.com/gregrahn/sqllogictest.git"
|
||||
|
||||
RUN git clone --recursive ${sqllogic_test_repo}
|
||||
|
||||
COPY run.sh /
|
||||
CMD ["/bin/bash", "/run.sh"]
|
100
docker/test/sqllogic/run.sh
Executable file
100
docker/test/sqllogic/run.sh
Executable file
@ -0,0 +1,100 @@
|
||||
#!/bin/bash
|
||||
set -exu
|
||||
trap "exit" INT TERM
|
||||
|
||||
echo "ENV"
|
||||
env
|
||||
|
||||
# fail on errors, verbose and export all env variables
|
||||
set -e -x -a
|
||||
|
||||
echo "Current directory"
|
||||
pwd
|
||||
echo "Files in current directory"
|
||||
ls -la ./
|
||||
echo "Files in root directory"
|
||||
ls -la /
|
||||
echo "Files in /clickhouse-tests directory"
|
||||
ls -la /clickhouse-tests
|
||||
echo "Files in /clickhouse-tests/sqllogic directory"
|
||||
ls -la /clickhouse-tests/sqllogic
|
||||
echo "Files in /package_folder directory"
|
||||
ls -la /package_folder
|
||||
echo "Files in /test_output"
|
||||
ls -la /test_output
|
||||
echo "File in /sqllogictest"
|
||||
ls -la /sqllogictest
|
||||
|
||||
dpkg -i package_folder/clickhouse-common-static_*.deb
|
||||
dpkg -i package_folder/clickhouse-common-static-dbg_*.deb
|
||||
dpkg -i package_folder/clickhouse-server_*.deb
|
||||
dpkg -i package_folder/clickhouse-client_*.deb
|
||||
|
||||
# install test configs
|
||||
# /clickhouse-tests/config/install.sh
|
||||
|
||||
sudo clickhouse start
|
||||
|
||||
sleep 5
|
||||
for _ in $(seq 1 60); do if [[ $(wget --timeout=1 -q 'localhost:8123' -O-) == 'Ok.' ]]; then break ; else sleep 1; fi ; done
|
||||
|
||||
function run_tests()
|
||||
{
|
||||
set -x
|
||||
|
||||
cd /test_output
|
||||
|
||||
/clickhouse-tests/sqllogic/runner.py --help 2>&1 \
|
||||
| ts '%Y-%m-%d %H:%M:%S'
|
||||
|
||||
mkdir -p /test_output/self-test
|
||||
/clickhouse-tests/sqllogic/runner.py --log-file /test_output/runner-self-test.log \
|
||||
self-test \
|
||||
--self-test-dir /clickhouse-tests/sqllogic/self-test \
|
||||
--out-dir /test_output/self-test \
|
||||
2>&1 \
|
||||
| ts '%Y-%m-%d %H:%M:%S'
|
||||
|
||||
cat /test_output/self-test/check_status.tsv >> /test_output/check_status.tsv
|
||||
cat /test_output/self-test/test_results.tsv >> /test_output/test_results.tsv ||:
|
||||
tar -zcvf self-test.tar.gz self-test 1>/dev/null
|
||||
|
||||
if [ -d /sqllogictest ]
|
||||
then
|
||||
mkdir -p /test_output/statements-test
|
||||
/clickhouse-tests/sqllogic/runner.py \
|
||||
--log-file /test_output/runner-statements-test.log \
|
||||
--log-level info \
|
||||
statements-test \
|
||||
--input-dir /sqllogictest \
|
||||
--out-dir /test_output/statements-test \
|
||||
2>&1 \
|
||||
| ts '%Y-%m-%d %H:%M:%S'
|
||||
|
||||
cat /test_output/statements-test/check_status.tsv >> /test_output/check_status.tsv
|
||||
cat /test_output/statements-test/test_results.tsv >> /test_output/test_results.tsv
|
||||
tar -zcvf statements-check.tar.gz statements-test 1>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
export -f run_tests
|
||||
|
||||
timeout "${MAX_RUN_TIME:-9000}" bash -c run_tests || echo "timeout reached" >&2
|
||||
|
||||
#/process_functional_tests_result.py || echo -e "failure\tCannot parse results" > /test_output/check_status.tsv
|
||||
|
||||
clickhouse-client -q "system flush logs" ||:
|
||||
|
||||
# Stop server so we can safely read data with clickhouse-local.
|
||||
# Why do we read data with clickhouse-local?
|
||||
# Because it's the simplest way to read it when server has crashed.
|
||||
sudo clickhouse stop ||:
|
||||
|
||||
for _ in $(seq 1 60); do if [[ $(wget --timeout=1 -q 'localhost:8123' -O-) == 'Ok.' ]]; then sleep 1 ; else break; fi ; done
|
||||
|
||||
grep -Fa "Fatal" /var/log/clickhouse-server/clickhouse-server.log ||:
|
||||
pigz < /var/log/clickhouse-server/clickhouse-server.log > /test_output/clickhouse-server.log.gz &
|
||||
|
||||
# Compressed (FIXME: remove once only github actions will be left)
|
||||
rm /var/log/clickhouse-server/clickhouse-server.log
|
||||
mv /var/log/clickhouse-server/stderr.log /test_output/ ||:
|
@ -79,8 +79,8 @@ In most cases, the read method is only responsible for reading the specified col
|
||||
|
||||
But there are notable exceptions:
|
||||
|
||||
- The AST query is passed to the `read` method, and the table engine can use it to derive index usage and to read fewer data from a table.
|
||||
- Sometimes the table engine can process data itself to a specific stage. For example, `StorageDistributed` can send a query to remote servers, ask them to process data to a stage where data from different remote servers can be merged, and return that preprocessed data. The query interpreter then finishes processing the data.
|
||||
- The AST query is passed to the `read` method, and the table engine can use it to derive index usage and to read fewer data from a table.
|
||||
- Sometimes the table engine can process data itself to a specific stage. For example, `StorageDistributed` can send a query to remote servers, ask them to process data to a stage where data from different remote servers can be merged, and return that preprocessed data. The query interpreter then finishes processing the data.
|
||||
|
||||
The table’s `read` method can return multiple `IBlockInputStream` objects to allow parallel data processing. These multiple block input streams can read from a table in parallel. Then you can wrap these streams with various transformations (such as expression evaluation or filtering) that can be calculated independently and create a `UnionBlockInputStream` on top of them, to read from multiple streams in parallel.
|
||||
|
||||
@ -132,9 +132,9 @@ Aggregation states can be serialized and deserialized to pass over the network d
|
||||
|
||||
The server implements several different interfaces:
|
||||
|
||||
- An HTTP interface for any foreign clients.
|
||||
- A TCP interface for the native ClickHouse client and for cross-server communication during distributed query execution.
|
||||
- An interface for transferring data for replication.
|
||||
- An HTTP interface for any foreign clients.
|
||||
- A TCP interface for the native ClickHouse client and for cross-server communication during distributed query execution.
|
||||
- An interface for transferring data for replication.
|
||||
|
||||
Internally, it is just a primitive multithread server without coroutines or fibers. Since the server is not designed to process a high rate of simple queries but to process a relatively low rate of complex queries, each of them can process a vast amount of data for analytics.
|
||||
|
||||
|
@ -9,9 +9,9 @@ description: How to build ClickHouse on Linux
|
||||
|
||||
Supported platforms:
|
||||
|
||||
- x86_64
|
||||
- AArch64
|
||||
- Power9 (experimental)
|
||||
- x86_64
|
||||
- AArch64
|
||||
- Power9 (experimental)
|
||||
|
||||
## Normal Build for Development on Ubuntu
|
||||
|
||||
@ -82,13 +82,13 @@ This will create the `programs/clickhouse` executable, which can be used with `c
|
||||
|
||||
The build requires the following components:
|
||||
|
||||
- Git (is used only to checkout the sources, it’s not needed for the build)
|
||||
- CMake 3.15 or newer
|
||||
- Ninja
|
||||
- C++ compiler: clang-15 or newer
|
||||
- Linker: lld
|
||||
- Yasm
|
||||
- Gawk
|
||||
- Git (is used only to checkout the sources, it’s not needed for the build)
|
||||
- CMake 3.15 or newer
|
||||
- Ninja
|
||||
- C++ compiler: clang-15 or newer
|
||||
- Linker: lld
|
||||
- Yasm
|
||||
- Gawk
|
||||
|
||||
If all the components are installed, you may build in the same way as the steps above.
|
||||
|
||||
|
@ -370,8 +370,8 @@ If the file contains a single function, name the file the same way as the functi
|
||||
|
||||
**11.** If the name contains an abbreviation, then:
|
||||
|
||||
- For variable names, the abbreviation should use lowercase letters `mysql_connection` (not `mySQL_connection`).
|
||||
- For names of classes and functions, keep the uppercase letters in the abbreviation`MySQLConnection` (not `MySqlConnection`).
|
||||
- For variable names, the abbreviation should use lowercase letters `mysql_connection` (not `mySQL_connection`).
|
||||
- For names of classes and functions, keep the uppercase letters in the abbreviation`MySQLConnection` (not `MySqlConnection`).
|
||||
|
||||
**12.** Constructor arguments that are used just to initialize the class members should be named the same way as the class members, but with an underscore at the end.
|
||||
|
||||
@ -434,9 +434,9 @@ In application code, memory must be freed by the object that owns it.
|
||||
|
||||
Examples:
|
||||
|
||||
- The easiest way is to place an object on the stack, or make it a member of another class.
|
||||
- For a large number of small objects, use containers.
|
||||
- For automatic deallocation of a small number of objects that reside in the heap, use `shared_ptr/unique_ptr`.
|
||||
- The easiest way is to place an object on the stack, or make it a member of another class.
|
||||
- For a large number of small objects, use containers.
|
||||
- For automatic deallocation of a small number of objects that reside in the heap, use `shared_ptr/unique_ptr`.
|
||||
|
||||
**2.** Resource management.
|
||||
|
||||
@ -504,10 +504,10 @@ This is not recommended, but it is allowed.
|
||||
|
||||
Use the following options:
|
||||
|
||||
- Create a function (`done()` or `finalize()`) that will do all the work in advance that might lead to an exception. If that function was called, there should be no exceptions in the destructor later.
|
||||
- Tasks that are too complex (such as sending messages over the network) can be put in separate method that the class user will have to call before destruction.
|
||||
- If there is an exception in the destructor, it’s better to log it than to hide it (if the logger is available).
|
||||
- In simple applications, it is acceptable to rely on `std::terminate` (for cases of `noexcept` by default in C++11) to handle exceptions.
|
||||
- Create a function (`done()` or `finalize()`) that will do all the work in advance that might lead to an exception. If that function was called, there should be no exceptions in the destructor later.
|
||||
- Tasks that are too complex (such as sending messages over the network) can be put in separate method that the class user will have to call before destruction.
|
||||
- If there is an exception in the destructor, it’s better to log it than to hide it (if the logger is available).
|
||||
- In simple applications, it is acceptable to rely on `std::terminate` (for cases of `noexcept` by default in C++11) to handle exceptions.
|
||||
|
||||
**6.** Anonymous code blocks.
|
||||
|
||||
@ -529,11 +529,11 @@ ready_any.set();
|
||||
|
||||
In offline data processing programs:
|
||||
|
||||
- Try to get the best possible performance on a single CPU core. You can then parallelize your code if necessary.
|
||||
- Try to get the best possible performance on a single CPU core. You can then parallelize your code if necessary.
|
||||
|
||||
In server applications:
|
||||
|
||||
- Use the thread pool to process requests. At this point, we haven’t had any tasks that required userspace context switching.
|
||||
- Use the thread pool to process requests. At this point, we haven’t had any tasks that required userspace context switching.
|
||||
|
||||
Fork is not used for parallelization.
|
||||
|
||||
|
@ -194,11 +194,11 @@ If the system clickhouse-server is already running and you do not want to stop i
|
||||
Build tests allow to check that build is not broken on various alternative configurations and on some foreign systems. These tests are automated as well.
|
||||
|
||||
Examples:
|
||||
- cross-compile for Darwin x86_64 (macOS)
|
||||
- cross-compile for FreeBSD x86_64
|
||||
- cross-compile for Linux AArch64
|
||||
- build on Ubuntu with libraries from system packages (discouraged)
|
||||
- build with shared linking of libraries (discouraged)
|
||||
- cross-compile for Darwin x86_64 (macOS)
|
||||
- cross-compile for FreeBSD x86_64
|
||||
- cross-compile for Linux AArch64
|
||||
- build on Ubuntu with libraries from system packages (discouraged)
|
||||
- build with shared linking of libraries (discouraged)
|
||||
|
||||
For example, build with system packages is bad practice, because we cannot guarantee what exact version of packages a system will have. But this is really needed by Debian maintainers. For this reason we at least have to support this variant of build. Another example: shared linking is a common source of trouble, but it is needed for some enthusiasts.
|
||||
|
||||
|
@ -59,4 +59,4 @@ For [ReplicatedMergeTree](../table-engines/mergetree-family/replication.md#table
|
||||
|
||||
## See Also
|
||||
|
||||
- [system.databases](../../operations/system-tables/databases.md) system table
|
||||
- [system.databases](../../operations/system-tables/databases.md) system table
|
||||
|
@ -11,18 +11,18 @@ Database engines allow you to work with tables. By default, ClickHouse uses the
|
||||
|
||||
Here is a complete list of available database engines. Follow the links for more details:
|
||||
|
||||
- [Atomic](../../engines/database-engines/atomic.md)
|
||||
- [Atomic](../../engines/database-engines/atomic.md)
|
||||
|
||||
- [MySQL](../../engines/database-engines/mysql.md)
|
||||
- [MySQL](../../engines/database-engines/mysql.md)
|
||||
|
||||
- [MaterializedMySQL](../../engines/database-engines/materialized-mysql.md)
|
||||
- [MaterializedMySQL](../../engines/database-engines/materialized-mysql.md)
|
||||
|
||||
- [Lazy](../../engines/database-engines/lazy.md)
|
||||
- [Lazy](../../engines/database-engines/lazy.md)
|
||||
|
||||
- [PostgreSQL](../../engines/database-engines/postgresql.md)
|
||||
- [PostgreSQL](../../engines/database-engines/postgresql.md)
|
||||
|
||||
- [MaterializedPostgreSQL](../../engines/database-engines/materialized-postgresql.md)
|
||||
- [MaterializedPostgreSQL](../../engines/database-engines/materialized-postgresql.md)
|
||||
|
||||
- [Replicated](../../engines/database-engines/replicated.md)
|
||||
- [Replicated](../../engines/database-engines/replicated.md)
|
||||
|
||||
- [SQLite](../../engines/database-engines/sqlite.md)
|
||||
- [SQLite](../../engines/database-engines/sqlite.md)
|
||||
|
@ -22,10 +22,10 @@ ENGINE = MaterializedMySQL('host:port', ['database' | database], 'user', 'passwo
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `host:port` — MySQL server endpoint.
|
||||
- `database` — MySQL database name.
|
||||
- `user` — MySQL user.
|
||||
- `password` — User password.
|
||||
- `host:port` — MySQL server endpoint.
|
||||
- `database` — MySQL database name.
|
||||
- `user` — MySQL user.
|
||||
- `password` — User password.
|
||||
|
||||
## Engine Settings
|
||||
|
||||
|
@ -26,10 +26,10 @@ ENGINE = MaterializedPostgreSQL('host:port', 'database', 'user', 'password') [SE
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `host:port` — PostgreSQL server endpoint.
|
||||
- `database` — PostgreSQL database name.
|
||||
- `user` — PostgreSQL user.
|
||||
- `password` — User password.
|
||||
- `host:port` — PostgreSQL server endpoint.
|
||||
- `database` — PostgreSQL database name.
|
||||
- `user` — PostgreSQL user.
|
||||
- `password` — User password.
|
||||
|
||||
## Example of Use {#example-of-use}
|
||||
|
||||
@ -120,9 +120,9 @@ Warning: for this case dots in table name are not allowed.
|
||||
|
||||
2. Each replicated table must have one of the following [replica identity](https://www.postgresql.org/docs/10/sql-altertable.html#SQL-CREATETABLE-REPLICA-IDENTITY):
|
||||
|
||||
- primary key (by default)
|
||||
- primary key (by default)
|
||||
|
||||
- index
|
||||
- index
|
||||
|
||||
``` bash
|
||||
postgres# CREATE TABLE postgres_table (a Integer NOT NULL, b Integer, c Integer NOT NULL, d Integer, e Integer NOT NULL);
|
||||
@ -171,7 +171,7 @@ Replication of [**TOAST**](https://www.postgresql.org/docs/9.5/storage-toast.htm
|
||||
|
||||
Possible values:
|
||||
|
||||
- Positive integer.
|
||||
- Positive integer.
|
||||
|
||||
Default value: `65536`.
|
||||
|
||||
|
@ -12,9 +12,9 @@ The `MySQL` database engine translate queries to the MySQL server so you can per
|
||||
|
||||
You cannot perform the following queries:
|
||||
|
||||
- `RENAME`
|
||||
- `CREATE TABLE`
|
||||
- `ALTER`
|
||||
- `RENAME`
|
||||
- `CREATE TABLE`
|
||||
- `ALTER`
|
||||
|
||||
## Creating a Database {#creating-a-database}
|
||||
|
||||
@ -25,10 +25,10 @@ ENGINE = MySQL('host:port', ['database' | database], 'user', 'password')
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `host:port` — MySQL server address.
|
||||
- `database` — Remote database name.
|
||||
- `user` — MySQL user.
|
||||
- `password` — User password.
|
||||
- `host:port` — MySQL server address.
|
||||
- `database` — Remote database name.
|
||||
- `user` — MySQL user.
|
||||
- `password` — User password.
|
||||
|
||||
## Data Types Support {#data_types-support}
|
||||
|
||||
|
@ -21,12 +21,12 @@ ENGINE = PostgreSQL('host:port', 'database', 'user', 'password'[, `schema`, `use
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `host:port` — PostgreSQL server address.
|
||||
- `database` — Remote database name.
|
||||
- `user` — PostgreSQL user.
|
||||
- `password` — User password.
|
||||
- `schema` — PostgreSQL schema.
|
||||
- `use_table_cache` — Defines if the database table structure is cached or not. Optional. Default value: `0`.
|
||||
- `host:port` — PostgreSQL server address.
|
||||
- `database` — Remote database name.
|
||||
- `user` — PostgreSQL user.
|
||||
- `password` — User password.
|
||||
- `schema` — PostgreSQL schema.
|
||||
- `use_table_cache` — Defines if the database table structure is cached or not. Optional. Default value: `0`.
|
||||
|
||||
## Data Types Support {#data_types-support}
|
||||
|
||||
|
@ -17,9 +17,9 @@ CREATE DATABASE testdb ENGINE = Replicated('zoo_path', 'shard_name', 'replica_na
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `zoo_path` — ZooKeeper path. The same ZooKeeper path corresponds to the same database.
|
||||
- `shard_name` — Shard name. Database replicas are grouped into shards by `shard_name`.
|
||||
- `replica_name` — Replica name. Replica names must be different for all replicas of the same shard.
|
||||
- `zoo_path` — ZooKeeper path. The same ZooKeeper path corresponds to the same database.
|
||||
- `shard_name` — Shard name. Database replicas are grouped into shards by `shard_name`.
|
||||
- `replica_name` — Replica name. Replica names must be different for all replicas of the same shard.
|
||||
|
||||
For [ReplicatedMergeTree](../table-engines/mergetree-family/replication.md#table_engines-replication) tables if no arguments provided, then default arguments are used: `/clickhouse/tables/{uuid}/{shard}` and `{replica}`. These can be changed in the server settings [default_replica_path](../../operations/server-configuration-parameters/settings.md#default_replica_path) and [default_replica_name](../../operations/server-configuration-parameters/settings.md#default_replica_name). Macro `{uuid}` is unfolded to table's uuid, `{shard}` and `{replica}` are unfolded to values from server config, not from database engine arguments. But in the future, it will be possible to use `shard_name` and `replica_name` of Replicated database.
|
||||
|
||||
|
@ -17,7 +17,7 @@ Allows to connect to [SQLite](https://www.sqlite.org/index.html) database and pe
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `db_path` — Path to a file with SQLite database.
|
||||
- `db_path` — Path to a file with SQLite database.
|
||||
|
||||
## Data Types Support {#data_types-support}
|
||||
|
||||
|
@ -9,12 +9,12 @@ toc_title: Introduction
|
||||
|
||||
The table engine (type of table) determines:
|
||||
|
||||
- How and where data is stored, where to write it to, and where to read it from.
|
||||
- Which queries are supported, and how.
|
||||
- Concurrent data access.
|
||||
- Use of indexes, if present.
|
||||
- Whether multithread request execution is possible.
|
||||
- Data replication parameters.
|
||||
- How and where data is stored, where to write it to, and where to read it from.
|
||||
- Which queries are supported, and how.
|
||||
- Concurrent data access.
|
||||
- Use of indexes, if present.
|
||||
- Whether multithread request execution is possible.
|
||||
- Data replication parameters.
|
||||
|
||||
## Engine Families {#engine-families}
|
||||
|
||||
@ -24,13 +24,13 @@ The most universal and functional table engines for high-load tasks. The propert
|
||||
|
||||
Engines in the family:
|
||||
|
||||
- [MergeTree](../../engines/table-engines/mergetree-family/mergetree.md#mergetree)
|
||||
- [ReplacingMergeTree](../../engines/table-engines/mergetree-family/replacingmergetree.md#replacingmergetree)
|
||||
- [SummingMergeTree](../../engines/table-engines/mergetree-family/summingmergetree.md#summingmergetree)
|
||||
- [AggregatingMergeTree](../../engines/table-engines/mergetree-family/aggregatingmergetree.md#aggregatingmergetree)
|
||||
- [CollapsingMergeTree](../../engines/table-engines/mergetree-family/collapsingmergetree.md#table_engine-collapsingmergetree)
|
||||
- [VersionedCollapsingMergeTree](../../engines/table-engines/mergetree-family/versionedcollapsingmergetree.md#versionedcollapsingmergetree)
|
||||
- [GraphiteMergeTree](../../engines/table-engines/mergetree-family/graphitemergetree.md#graphitemergetree)
|
||||
- [MergeTree](../../engines/table-engines/mergetree-family/mergetree.md#mergetree)
|
||||
- [ReplacingMergeTree](../../engines/table-engines/mergetree-family/replacingmergetree.md#replacingmergetree)
|
||||
- [SummingMergeTree](../../engines/table-engines/mergetree-family/summingmergetree.md#summingmergetree)
|
||||
- [AggregatingMergeTree](../../engines/table-engines/mergetree-family/aggregatingmergetree.md#aggregatingmergetree)
|
||||
- [CollapsingMergeTree](../../engines/table-engines/mergetree-family/collapsingmergetree.md#table_engine-collapsingmergetree)
|
||||
- [VersionedCollapsingMergeTree](../../engines/table-engines/mergetree-family/versionedcollapsingmergetree.md#versionedcollapsingmergetree)
|
||||
- [GraphiteMergeTree](../../engines/table-engines/mergetree-family/graphitemergetree.md#graphitemergetree)
|
||||
|
||||
### Log {#log}
|
||||
|
||||
@ -38,9 +38,9 @@ Lightweight [engines](../../engines/table-engines/log-family/index.md) with mini
|
||||
|
||||
Engines in the family:
|
||||
|
||||
- [TinyLog](../../engines/table-engines/log-family/tinylog.md#tinylog)
|
||||
- [StripeLog](../../engines/table-engines/log-family/stripelog.md#stripelog)
|
||||
- [Log](../../engines/table-engines/log-family/log.md#log)
|
||||
- [TinyLog](../../engines/table-engines/log-family/tinylog.md#tinylog)
|
||||
- [StripeLog](../../engines/table-engines/log-family/stripelog.md#stripelog)
|
||||
- [Log](../../engines/table-engines/log-family/log.md#log)
|
||||
|
||||
### Integration Engines {#integration-engines}
|
||||
|
||||
@ -49,34 +49,34 @@ Engines for communicating with other data storage and processing systems.
|
||||
Engines in the family:
|
||||
|
||||
|
||||
- [ODBC](../../engines/table-engines/integrations/odbc.md)
|
||||
- [JDBC](../../engines/table-engines/integrations/jdbc.md)
|
||||
- [MySQL](../../engines/table-engines/integrations/mysql.md)
|
||||
- [MongoDB](../../engines/table-engines/integrations/mongodb.md)
|
||||
- [HDFS](../../engines/table-engines/integrations/hdfs.md)
|
||||
- [S3](../../engines/table-engines/integrations/s3.md)
|
||||
- [Kafka](../../engines/table-engines/integrations/kafka.md)
|
||||
- [EmbeddedRocksDB](../../engines/table-engines/integrations/embedded-rocksdb.md)
|
||||
- [RabbitMQ](../../engines/table-engines/integrations/rabbitmq.md)
|
||||
- [PostgreSQL](../../engines/table-engines/integrations/postgresql.md)
|
||||
- [ODBC](../../engines/table-engines/integrations/odbc.md)
|
||||
- [JDBC](../../engines/table-engines/integrations/jdbc.md)
|
||||
- [MySQL](../../engines/table-engines/integrations/mysql.md)
|
||||
- [MongoDB](../../engines/table-engines/integrations/mongodb.md)
|
||||
- [HDFS](../../engines/table-engines/integrations/hdfs.md)
|
||||
- [S3](../../engines/table-engines/integrations/s3.md)
|
||||
- [Kafka](../../engines/table-engines/integrations/kafka.md)
|
||||
- [EmbeddedRocksDB](../../engines/table-engines/integrations/embedded-rocksdb.md)
|
||||
- [RabbitMQ](../../engines/table-engines/integrations/rabbitmq.md)
|
||||
- [PostgreSQL](../../engines/table-engines/integrations/postgresql.md)
|
||||
|
||||
### Special Engines {#special-engines}
|
||||
|
||||
Engines in the family:
|
||||
|
||||
- [Distributed](../../engines/table-engines/special/distributed.md#distributed)
|
||||
- [MaterializedView](../../engines/table-engines/special/materializedview.md#materializedview)
|
||||
- [Dictionary](../../engines/table-engines/special/dictionary.md#dictionary)
|
||||
- [Merge](../../engines/table-engines/special/merge.md#merge)
|
||||
- [File](../../engines/table-engines/special/file.md#file)
|
||||
- [Null](../../engines/table-engines/special/null.md#null)
|
||||
- [Set](../../engines/table-engines/special/set.md#set)
|
||||
- [Join](../../engines/table-engines/special/join.md#join)
|
||||
- [URL](../../engines/table-engines/special/url.md#table_engines-url)
|
||||
- [View](../../engines/table-engines/special/view.md#table_engines-view)
|
||||
- [Memory](../../engines/table-engines/special/memory.md#memory)
|
||||
- [Buffer](../../engines/table-engines/special/buffer.md#buffer)
|
||||
- [KeeperMap](../../engines/table-engines/special/keepermap.md)
|
||||
- [Distributed](../../engines/table-engines/special/distributed.md#distributed)
|
||||
- [MaterializedView](../../engines/table-engines/special/materializedview.md#materializedview)
|
||||
- [Dictionary](../../engines/table-engines/special/dictionary.md#dictionary)
|
||||
- [Merge](../../engines/table-engines/special/merge.md#merge)
|
||||
- [File](../../engines/table-engines/special/file.md#file)
|
||||
- [Null](../../engines/table-engines/special/null.md#null)
|
||||
- [Set](../../engines/table-engines/special/set.md#set)
|
||||
- [Join](../../engines/table-engines/special/join.md#join)
|
||||
- [URL](../../engines/table-engines/special/url.md#table_engines-url)
|
||||
- [View](../../engines/table-engines/special/view.md#table_engines-view)
|
||||
- [Memory](../../engines/table-engines/special/memory.md#memory)
|
||||
- [Buffer](../../engines/table-engines/special/buffer.md#buffer)
|
||||
- [KeeperMap](../../engines/table-engines/special/keepermap.md)
|
||||
|
||||
## Virtual Columns {#table_engines-virtual_columns}
|
||||
|
||||
|
@ -22,17 +22,17 @@ See a detailed description of the [CREATE TABLE](../../../sql-reference/statemen
|
||||
|
||||
The table structure can differ from the original table structure:
|
||||
|
||||
- Column names should be the same as in the original table, but you can use just some of these columns and in any order.
|
||||
- Column types may differ from those in the original table. ClickHouse tries to [cast](../../../sql-reference/functions/type-conversion-functions.md#type_conversion_function-cast) values to the ClickHouse data types.
|
||||
- Column names should be the same as in the original table, but you can use just some of these columns and in any order.
|
||||
- Column types may differ from those in the original table. ClickHouse tries to [cast](../../../sql-reference/functions/type-conversion-functions.md#type_conversion_function-cast) values to the ClickHouse data types.
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `engine` — The table engine `MySQL` or `PostgreSQL`.
|
||||
- `host:port` — MySQL or PostgreSQL server address.
|
||||
- `database` — Remote database name.
|
||||
- `table` — Remote table name.
|
||||
- `user` — User name.
|
||||
- `password` — User password.
|
||||
- `engine` — The table engine `MySQL` or `PostgreSQL`.
|
||||
- `host:port` — MySQL or PostgreSQL server address.
|
||||
- `database` — Remote database name.
|
||||
- `table` — Remote table name.
|
||||
- `user` — User name.
|
||||
- `password` — User password.
|
||||
|
||||
## Implementation Details {#implementation-details}
|
||||
|
||||
@ -48,6 +48,6 @@ You can specify any number of shards and any number of replicas for each shard.
|
||||
|
||||
**See Also**
|
||||
|
||||
- [MySQL table engine](../../../engines/table-engines/integrations/mysql.md)
|
||||
- [PostgreSQL table engine](../../../engines/table-engines/integrations/postgresql.md)
|
||||
- [Distributed table engine](../../../engines/table-engines/special/distributed.md)
|
||||
- [MySQL table engine](../../../engines/table-engines/integrations/mysql.md)
|
||||
- [PostgreSQL table engine](../../../engines/table-engines/integrations/postgresql.md)
|
||||
- [Distributed table engine](../../../engines/table-engines/special/distributed.md)
|
||||
|
@ -18,8 +18,8 @@ CREATE TABLE deltalake
|
||||
|
||||
**Engine parameters**
|
||||
|
||||
- `url` — Bucket url with path to the existing Delta Lake table.
|
||||
- `aws_access_key_id`, `aws_secret_access_key` - Long-term credentials for the [AWS](https://aws.amazon.com/) account user. You can use these to authenticate your requests. Parameter is optional. If credentials are not specified, they are used from the configuration file.
|
||||
- `url` — Bucket url with path to the existing Delta Lake table.
|
||||
- `aws_access_key_id`, `aws_secret_access_key` - Long-term credentials for the [AWS](https://aws.amazon.com/) account user. You can use these to authenticate your requests. Parameter is optional. If credentials are not specified, they are used from the configuration file.
|
||||
|
||||
Engine parameters can be specified using [Named Collections](../../../operations/named-collections.md)
|
||||
|
||||
@ -49,4 +49,4 @@ CREATE TABLE deltalake ENGINE=DeltaLake(deltalake_conf, filename = 'test_table')
|
||||
|
||||
## See also
|
||||
|
||||
- [deltaLake table function](../../../sql-reference/table-functions/deltalake.md)
|
||||
- [deltaLake table function](../../../sql-reference/table-functions/deltalake.md)
|
||||
|
@ -17,7 +17,7 @@ ENGINE = HDFS(URI, format)
|
||||
**Engine Parameters**
|
||||
|
||||
- `URI` - whole file URI in HDFS. The path part of `URI` may contain globs. In this case the table would be readonly.
|
||||
- `format` - specifies one of the available file formats. To perform
|
||||
- `format` - specifies one of the available file formats. To perform
|
||||
`SELECT` queries, the format must be supported for input, and to perform
|
||||
`INSERT` queries – for output. The available formats are listed in the
|
||||
[Formats](../../../interfaces/formats.md#formats) section.
|
||||
@ -58,11 +58,11 @@ SELECT * FROM hdfs_engine_table LIMIT 2
|
||||
|
||||
## Implementation Details {#implementation-details}
|
||||
|
||||
- Reads and writes can be parallel.
|
||||
- Not supported:
|
||||
- `ALTER` and `SELECT...SAMPLE` operations.
|
||||
- Indexes.
|
||||
- [Zero-copy](../../../operations/storing-data.md#zero-copy) replication is possible, but not recommended.
|
||||
- Reads and writes can be parallel.
|
||||
- Not supported:
|
||||
- `ALTER` and `SELECT...SAMPLE` operations.
|
||||
- Indexes.
|
||||
- [Zero-copy](../../../operations/storing-data.md#zero-copy) replication is possible, but not recommended.
|
||||
|
||||
:::note Zero-copy replication is not ready for production
|
||||
Zero-copy replication is disabled by default in ClickHouse version 22.8 and higher. This feature is not recommended for production use.
|
||||
@ -72,10 +72,10 @@ SELECT * FROM hdfs_engine_table LIMIT 2
|
||||
|
||||
Multiple path components can have globs. For being processed file should exists and matches to the whole path pattern. Listing of files determines during `SELECT` (not at `CREATE` moment).
|
||||
|
||||
- `*` — Substitutes any number of any characters except `/` including empty string.
|
||||
- `?` — Substitutes any single character.
|
||||
- `{some_string,another_string,yet_another_one}` — Substitutes any of strings `'some_string', 'another_string', 'yet_another_one'`.
|
||||
- `{N..M}` — Substitutes any number in range from N to M including both borders.
|
||||
- `*` — Substitutes any number of any characters except `/` including empty string.
|
||||
- `?` — Substitutes any single character.
|
||||
- `{some_string,another_string,yet_another_one}` — Substitutes any of strings `'some_string', 'another_string', 'yet_another_one'`.
|
||||
- `{N..M}` — Substitutes any number in range from N to M including both borders.
|
||||
|
||||
Constructions with `{}` are similar to the [remote](../../../sql-reference/table-functions/remote.md) table function.
|
||||
|
||||
@ -83,12 +83,12 @@ Constructions with `{}` are similar to the [remote](../../../sql-reference/table
|
||||
|
||||
1. Suppose we have several files in TSV format with the following URIs on HDFS:
|
||||
|
||||
- 'hdfs://hdfs1:9000/some_dir/some_file_1'
|
||||
- 'hdfs://hdfs1:9000/some_dir/some_file_2'
|
||||
- 'hdfs://hdfs1:9000/some_dir/some_file_3'
|
||||
- 'hdfs://hdfs1:9000/another_dir/some_file_1'
|
||||
- 'hdfs://hdfs1:9000/another_dir/some_file_2'
|
||||
- 'hdfs://hdfs1:9000/another_dir/some_file_3'
|
||||
- 'hdfs://hdfs1:9000/some_dir/some_file_1'
|
||||
- 'hdfs://hdfs1:9000/some_dir/some_file_2'
|
||||
- 'hdfs://hdfs1:9000/some_dir/some_file_3'
|
||||
- 'hdfs://hdfs1:9000/another_dir/some_file_1'
|
||||
- 'hdfs://hdfs1:9000/another_dir/some_file_2'
|
||||
- 'hdfs://hdfs1:9000/another_dir/some_file_3'
|
||||
|
||||
1. There are several ways to make a table consisting of all six files:
|
||||
|
||||
@ -145,7 +145,7 @@ Similar to GraphiteMergeTree, the HDFS engine supports extended configuration us
|
||||
|
||||
|
||||
| **parameter** | **default value** |
|
||||
| - | - |
|
||||
| - | - |
|
||||
| rpc\_client\_connect\_tcpnodelay | true |
|
||||
| dfs\_client\_read\_shortcircuit | true |
|
||||
| output\_replace-datanode-on-failure | true |
|
||||
@ -195,7 +195,7 @@ Similar to GraphiteMergeTree, the HDFS engine supports extended configuration us
|
||||
#### ClickHouse extras {#clickhouse-extras}
|
||||
|
||||
| **parameter** | **default value** |
|
||||
| - | - |
|
||||
| - | - |
|
||||
|hadoop\_kerberos\_keytab | "" |
|
||||
|hadoop\_kerberos\_principal | "" |
|
||||
|libhdfs3\_conf | "" |
|
||||
@ -230,9 +230,9 @@ libhdfs3 support HDFS namenode HA.
|
||||
|
||||
## Virtual Columns {#virtual-columns}
|
||||
|
||||
- `_path` — Path to the file.
|
||||
- `_file` — Name of the file.
|
||||
- `_path` — Path to the file.
|
||||
- `_file` — Name of the file.
|
||||
|
||||
**See Also**
|
||||
|
||||
- [Virtual columns](../../../engines/table-engines/index.md#table_engines-virtual_columns)
|
||||
- [Virtual columns](../../../engines/table-engines/index.md#table_engines-virtual_columns)
|
||||
|
@ -28,17 +28,17 @@ PARTITION BY expr
|
||||
See a detailed description of the [CREATE TABLE](../../../sql-reference/statements/create/table.md#create-table-query) query.
|
||||
|
||||
The table structure can differ from the original Hive table structure:
|
||||
- Column names should be the same as in the original Hive table, but you can use just some of these columns and in any order, also you can use some alias columns calculated from other columns.
|
||||
- Column types should be the same from those in the original Hive table.
|
||||
- Partition by expression should be consistent with the original Hive table, and columns in partition by expression should be in the table structure.
|
||||
- Column names should be the same as in the original Hive table, but you can use just some of these columns and in any order, also you can use some alias columns calculated from other columns.
|
||||
- Column types should be the same from those in the original Hive table.
|
||||
- Partition by expression should be consistent with the original Hive table, and columns in partition by expression should be in the table structure.
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `thrift://host:port` — Hive Metastore address
|
||||
- `thrift://host:port` — Hive Metastore address
|
||||
|
||||
- `database` — Remote database name.
|
||||
- `database` — Remote database name.
|
||||
|
||||
- `table` — Remote table name.
|
||||
- `table` — Remote table name.
|
||||
|
||||
## Usage Example {#usage-example}
|
||||
|
||||
|
@ -18,8 +18,8 @@ CREATE TABLE hudi_table
|
||||
|
||||
**Engine parameters**
|
||||
|
||||
- `url` — Bucket url with the path to an existing Hudi table.
|
||||
- `aws_access_key_id`, `aws_secret_access_key` - Long-term credentials for the [AWS](https://aws.amazon.com/) account user. You can use these to authenticate your requests. Parameter is optional. If credentials are not specified, they are used from the configuration file.
|
||||
- `url` — Bucket url with the path to an existing Hudi table.
|
||||
- `aws_access_key_id`, `aws_secret_access_key` - Long-term credentials for the [AWS](https://aws.amazon.com/) account user. You can use these to authenticate your requests. Parameter is optional. If credentials are not specified, they are used from the configuration file.
|
||||
|
||||
Engine parameters can be specified using [Named Collections](../../../operations/named-collections.md)
|
||||
|
||||
@ -49,4 +49,4 @@ CREATE TABLE hudi_table ENGINE=Hudi(hudi_conf, filename = 'test_table')
|
||||
|
||||
## See also
|
||||
|
||||
- [hudi table function](/docs/en/sql-reference/table-functions/hudi.md)
|
||||
- [hudi table function](/docs/en/sql-reference/table-functions/hudi.md)
|
||||
|
@ -18,8 +18,8 @@ CREATE TABLE iceberg_table
|
||||
|
||||
**Engine parameters**
|
||||
|
||||
- `url` — url with the path to an existing Iceberg table.
|
||||
- `aws_access_key_id`, `aws_secret_access_key` - Long-term credentials for the [AWS](https://aws.amazon.com/) account user. You can use these to authenticate your requests. Parameter is optional. If credentials are not specified, they are used from the configuration file.
|
||||
- `url` — url with the path to an existing Iceberg table.
|
||||
- `aws_access_key_id`, `aws_secret_access_key` - Long-term credentials for the [AWS](https://aws.amazon.com/) account user. You can use these to authenticate your requests. Parameter is optional. If credentials are not specified, they are used from the configuration file.
|
||||
|
||||
Engine parameters can be specified using [Named Collections](../../../operations/named-collections.md)
|
||||
|
||||
@ -49,4 +49,4 @@ CREATE TABLE iceberg_table ENGINE=Iceberg(iceberg_conf, filename = 'test_table')
|
||||
|
||||
## See also
|
||||
|
||||
- [iceberg table function](/docs/en/sql-reference/table-functions/iceberg.md)
|
||||
- [iceberg table function](/docs/en/sql-reference/table-functions/iceberg.md)
|
||||
|
@ -10,20 +10,20 @@ ClickHouse provides various means for integrating with external systems, includi
|
||||
|
||||
List of supported integrations:
|
||||
|
||||
- [ODBC](../../../engines/table-engines/integrations/odbc.md)
|
||||
- [JDBC](../../../engines/table-engines/integrations/jdbc.md)
|
||||
- [MySQL](../../../engines/table-engines/integrations/mysql.md)
|
||||
- [MongoDB](../../../engines/table-engines/integrations/mongodb.md)
|
||||
- [HDFS](../../../engines/table-engines/integrations/hdfs.md)
|
||||
- [S3](../../../engines/table-engines/integrations/s3.md)
|
||||
- [Kafka](../../../engines/table-engines/integrations/kafka.md)
|
||||
- [EmbeddedRocksDB](../../../engines/table-engines/integrations/embedded-rocksdb.md)
|
||||
- [RabbitMQ](../../../engines/table-engines/integrations/rabbitmq.md)
|
||||
- [PostgreSQL](../../../engines/table-engines/integrations/postgresql.md)
|
||||
- [SQLite](../../../engines/table-engines/integrations/sqlite.md)
|
||||
- [Hive](../../../engines/table-engines/integrations/hive.md)
|
||||
- [ExternalDistributed](../../../engines/table-engines/integrations/ExternalDistributed.md)
|
||||
- [MaterializedPostgreSQL](../../../engines/table-engines/integrations/materialized-postgresql.md)
|
||||
- [NATS](../../../engines/table-engines/integrations/nats.md)
|
||||
- [DeltaLake](../../../engines/table-engines/integrations/deltalake.md)
|
||||
- [Hudi](../../../engines/table-engines/integrations/hudi.md)
|
||||
- [ODBC](../../../engines/table-engines/integrations/odbc.md)
|
||||
- [JDBC](../../../engines/table-engines/integrations/jdbc.md)
|
||||
- [MySQL](../../../engines/table-engines/integrations/mysql.md)
|
||||
- [MongoDB](../../../engines/table-engines/integrations/mongodb.md)
|
||||
- [HDFS](../../../engines/table-engines/integrations/hdfs.md)
|
||||
- [S3](../../../engines/table-engines/integrations/s3.md)
|
||||
- [Kafka](../../../engines/table-engines/integrations/kafka.md)
|
||||
- [EmbeddedRocksDB](../../../engines/table-engines/integrations/embedded-rocksdb.md)
|
||||
- [RabbitMQ](../../../engines/table-engines/integrations/rabbitmq.md)
|
||||
- [PostgreSQL](../../../engines/table-engines/integrations/postgresql.md)
|
||||
- [SQLite](../../../engines/table-engines/integrations/sqlite.md)
|
||||
- [Hive](../../../engines/table-engines/integrations/hive.md)
|
||||
- [ExternalDistributed](../../../engines/table-engines/integrations/ExternalDistributed.md)
|
||||
- [MaterializedPostgreSQL](../../../engines/table-engines/integrations/materialized-postgresql.md)
|
||||
- [NATS](../../../engines/table-engines/integrations/nats.md)
|
||||
- [DeltaLake](../../../engines/table-engines/integrations/deltalake.md)
|
||||
- [Hudi](../../../engines/table-engines/integrations/hudi.md)
|
||||
|
@ -25,14 +25,14 @@ ENGINE = JDBC(datasource_uri, external_database, external_table)
|
||||
**Engine Parameters**
|
||||
|
||||
|
||||
- `datasource_uri` — URI or name of an external DBMS.
|
||||
- `datasource_uri` — URI or name of an external DBMS.
|
||||
|
||||
URI Format: `jdbc:<driver_name>://<host_name>:<port>/?user=<username>&password=<password>`.
|
||||
Example for MySQL: `jdbc:mysql://localhost:3306/?user=root&password=root`.
|
||||
|
||||
- `external_database` — Database in an external DBMS.
|
||||
- `external_database` — Database in an external DBMS.
|
||||
|
||||
- `external_table` — Name of the table in `external_database` or a select query like `select * from table1 where column1=1`.
|
||||
- `external_table` — Name of the table in `external_database` or a select query like `select * from table1 where column1=1`.
|
||||
|
||||
## Usage Example {#usage-example}
|
||||
|
||||
@ -91,4 +91,4 @@ FROM system.numbers
|
||||
|
||||
## See Also {#see-also}
|
||||
|
||||
- [JDBC table function](../../../sql-reference/table-functions/jdbc.md).
|
||||
- [JDBC table function](../../../sql-reference/table-functions/jdbc.md).
|
||||
|
@ -10,9 +10,9 @@ This engine works with [Apache Kafka](http://kafka.apache.org/).
|
||||
|
||||
Kafka lets you:
|
||||
|
||||
- Publish or subscribe to data flows.
|
||||
- Organize fault-tolerant storage.
|
||||
- Process streams as they become available.
|
||||
- Publish or subscribe to data flows.
|
||||
- Organize fault-tolerant storage.
|
||||
- Process streams as they become available.
|
||||
|
||||
## Creating a Table {#table_engine-kafka-creating-a-table}
|
||||
|
||||
@ -46,27 +46,27 @@ SETTINGS
|
||||
|
||||
Required parameters:
|
||||
|
||||
- `kafka_broker_list` — A comma-separated list of brokers (for example, `localhost:9092`).
|
||||
- `kafka_topic_list` — A list of Kafka topics.
|
||||
- `kafka_group_name` — A group of Kafka consumers. Reading margins are tracked for each group separately. If you do not want messages to be duplicated in the cluster, use the same group name everywhere.
|
||||
- `kafka_format` — Message format. Uses the same notation as the SQL `FORMAT` function, such as `JSONEachRow`. For more information, see the [Formats](../../../interfaces/formats.md) section.
|
||||
- `kafka_broker_list` — A comma-separated list of brokers (for example, `localhost:9092`).
|
||||
- `kafka_topic_list` — A list of Kafka topics.
|
||||
- `kafka_group_name` — A group of Kafka consumers. Reading margins are tracked for each group separately. If you do not want messages to be duplicated in the cluster, use the same group name everywhere.
|
||||
- `kafka_format` — Message format. Uses the same notation as the SQL `FORMAT` function, such as `JSONEachRow`. For more information, see the [Formats](../../../interfaces/formats.md) section.
|
||||
|
||||
Optional parameters:
|
||||
|
||||
- `kafka_row_delimiter` — Delimiter character, which ends the message. **This setting is deprecated and is no longer used, not left for compatibility reasons.**
|
||||
- `kafka_schema` — Parameter that must be used if the format requires a schema definition. For example, [Cap’n Proto](https://capnproto.org/) requires the path to the schema file and the name of the root `schema.capnp:Message` object.
|
||||
- `kafka_num_consumers` — The number of consumers per table. Specify more consumers if the throughput of one consumer is insufficient. The total number of consumers should not exceed the number of partitions in the topic, since only one consumer can be assigned per partition, and must not be greater than the number of physical cores on the server where ClickHouse is deployed. Default: `1`.
|
||||
- `kafka_max_block_size` — The maximum batch size (in messages) for poll. Default: [max_insert_block_size](../../../operations/settings/settings.md#setting-max_insert_block_size).
|
||||
- `kafka_skip_broken_messages` — Kafka message parser tolerance to schema-incompatible messages per block. If `kafka_skip_broken_messages = N` then the engine skips *N* Kafka messages that cannot be parsed (a message equals a row of data). Default: `0`.
|
||||
- `kafka_commit_every_batch` — Commit every consumed and handled batch instead of a single commit after writing a whole block. Default: `0`.
|
||||
- `kafka_client_id` — Client identifier. Empty by default.
|
||||
- `kafka_poll_timeout_ms` — Timeout for single poll from Kafka. Default: [stream_poll_timeout_ms](../../../operations/settings/settings.md#stream_poll_timeout_ms).
|
||||
- `kafka_poll_max_batch_size` — Maximum amount of messages to be polled in a single Kafka poll. Default: [max_block_size](../../../operations/settings/settings.md#setting-max_block_size).
|
||||
- `kafka_flush_interval_ms` — Timeout for flushing data from Kafka. Default: [stream_flush_interval_ms](../../../operations/settings/settings.md#stream-flush-interval-ms).
|
||||
- `kafka_thread_per_consumer` — Provide independent thread for each consumer. When enabled, every consumer flush the data independently, in parallel (otherwise — rows from several consumers squashed to form one block). Default: `0`.
|
||||
- `kafka_handle_error_mode` — How to handle errors for Kafka engine. Possible values: default, stream.
|
||||
- `kafka_commit_on_select` — Commit messages when select query is made. Default: `false`.
|
||||
- `kafka_max_rows_per_message` — The maximum number of rows written in one kafka message for row-based formats. Default : `1`.
|
||||
- `kafka_row_delimiter` — Delimiter character, which ends the message. **This setting is deprecated and is no longer used, not left for compatibility reasons.**
|
||||
- `kafka_schema` — Parameter that must be used if the format requires a schema definition. For example, [Cap’n Proto](https://capnproto.org/) requires the path to the schema file and the name of the root `schema.capnp:Message` object.
|
||||
- `kafka_num_consumers` — The number of consumers per table. Specify more consumers if the throughput of one consumer is insufficient. The total number of consumers should not exceed the number of partitions in the topic, since only one consumer can be assigned per partition, and must not be greater than the number of physical cores on the server where ClickHouse is deployed. Default: `1`.
|
||||
- `kafka_max_block_size` — The maximum batch size (in messages) for poll. Default: [max_insert_block_size](../../../operations/settings/settings.md#setting-max_insert_block_size).
|
||||
- `kafka_skip_broken_messages` — Kafka message parser tolerance to schema-incompatible messages per block. If `kafka_skip_broken_messages = N` then the engine skips *N* Kafka messages that cannot be parsed (a message equals a row of data). Default: `0`.
|
||||
- `kafka_commit_every_batch` — Commit every consumed and handled batch instead of a single commit after writing a whole block. Default: `0`.
|
||||
- `kafka_client_id` — Client identifier. Empty by default.
|
||||
- `kafka_poll_timeout_ms` — Timeout for single poll from Kafka. Default: [stream_poll_timeout_ms](../../../operations/settings/settings.md#stream_poll_timeout_ms).
|
||||
- `kafka_poll_max_batch_size` — Maximum amount of messages to be polled in a single Kafka poll. Default: [max_block_size](../../../operations/settings/settings.md#setting-max_block_size).
|
||||
- `kafka_flush_interval_ms` — Timeout for flushing data from Kafka. Default: [stream_flush_interval_ms](../../../operations/settings/settings.md#stream-flush-interval-ms).
|
||||
- `kafka_thread_per_consumer` — Provide independent thread for each consumer. When enabled, every consumer flush the data independently, in parallel (otherwise — rows from several consumers squashed to form one block). Default: `0`.
|
||||
- `kafka_handle_error_mode` — How to handle errors for Kafka engine. Possible values: default, stream.
|
||||
- `kafka_commit_on_select` — Commit messages when select query is made. Default: `false`.
|
||||
- `kafka_max_rows_per_message` — The maximum number of rows written in one kafka message for row-based formats. Default : `1`.
|
||||
|
||||
Examples:
|
||||
|
||||
@ -239,14 +239,14 @@ Example:
|
||||
|
||||
## Virtual Columns {#virtual-columns}
|
||||
|
||||
- `_topic` — Kafka topic.
|
||||
- `_key` — Key of the message.
|
||||
- `_offset` — Offset of the message.
|
||||
- `_timestamp` — Timestamp of the message.
|
||||
- `_timestamp_ms` — Timestamp in milliseconds of the message.
|
||||
- `_partition` — Partition of Kafka topic.
|
||||
- `_headers.name` — Array of message's headers keys.
|
||||
- `_headers.value` — Array of message's headers values.
|
||||
- `_topic` — Kafka topic.
|
||||
- `_key` — Key of the message.
|
||||
- `_offset` — Offset of the message.
|
||||
- `_timestamp` — Timestamp of the message.
|
||||
- `_timestamp_ms` — Timestamp in milliseconds of the message.
|
||||
- `_partition` — Partition of Kafka topic.
|
||||
- `_headers.name` — Array of message's headers keys.
|
||||
- `_headers.value` — Array of message's headers values.
|
||||
|
||||
## Data formats support {#data-formats-support}
|
||||
|
||||
@ -258,5 +258,5 @@ The number of rows in one Kafka message depends on whether the format is row-bas
|
||||
|
||||
**See Also**
|
||||
|
||||
- [Virtual columns](../../../engines/table-engines/index.md#table_engines-virtual_columns)
|
||||
- [background_message_broker_schedule_pool_size](../../../operations/server-configuration-parameters/settings.md#background_message_broker_schedule_pool_size)
|
||||
- [Virtual columns](../../../engines/table-engines/index.md#table_engines-virtual_columns)
|
||||
- [background_message_broker_schedule_pool_size](../../../operations/server-configuration-parameters/settings.md#background_message_broker_schedule_pool_size)
|
||||
|
@ -19,11 +19,11 @@ PRIMARY KEY key;
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `host:port` — PostgreSQL server address.
|
||||
- `database` — Remote database name.
|
||||
- `table` — Remote table name.
|
||||
- `user` — PostgreSQL user.
|
||||
- `password` — User password.
|
||||
- `host:port` — PostgreSQL server address.
|
||||
- `database` — Remote database name.
|
||||
- `table` — Remote table name.
|
||||
- `user` — PostgreSQL user.
|
||||
- `password` — User password.
|
||||
|
||||
## Requirements {#requirements}
|
||||
|
||||
@ -33,11 +33,13 @@ PRIMARY KEY key;
|
||||
|
||||
3. Only database [Atomic](https://en.wikipedia.org/wiki/Atomicity_(database_systems)) is allowed.
|
||||
|
||||
4. The `MaterializedPostgreSQL` table engine only works for PostgreSQL versions >= 11 as the implementation requires the [pg_replication_slot_advance](https://pgpedia.info/p/pg_replication_slot_advance.html) PostgreSQL function.
|
||||
|
||||
## Virtual columns {#virtual-columns}
|
||||
|
||||
- `_version` — Transaction counter. Type: [UInt64](../../../sql-reference/data-types/int-uint.md).
|
||||
- `_version` — Transaction counter. Type: [UInt64](../../../sql-reference/data-types/int-uint.md).
|
||||
|
||||
- `_sign` — Deletion mark. Type: [Int8](../../../sql-reference/data-types/int-uint.md). Possible values:
|
||||
- `_sign` — Deletion mark. Type: [Int8](../../../sql-reference/data-types/int-uint.md). Possible values:
|
||||
- `1` — Row is not deleted,
|
||||
- `-1` — Row is deleted.
|
||||
|
||||
|
@ -21,17 +21,17 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `host:port` — MongoDB server address.
|
||||
- `host:port` — MongoDB server address.
|
||||
|
||||
- `database` — Remote database name.
|
||||
- `database` — Remote database name.
|
||||
|
||||
- `collection` — Remote collection name.
|
||||
- `collection` — Remote collection name.
|
||||
|
||||
- `user` — MongoDB user.
|
||||
- `user` — MongoDB user.
|
||||
|
||||
- `password` — User password.
|
||||
- `password` — User password.
|
||||
|
||||
- `options` — MongoDB connection string options (optional parameter).
|
||||
- `options` — MongoDB connection string options (optional parameter).
|
||||
|
||||
## Usage Example {#usage-example}
|
||||
|
||||
|
@ -31,25 +31,25 @@ See a detailed description of the [CREATE TABLE](../../../sql-reference/statemen
|
||||
|
||||
The table structure can differ from the original MySQL table structure:
|
||||
|
||||
- Column names should be the same as in the original MySQL table, but you can use just some of these columns and in any order.
|
||||
- Column types may differ from those in the original MySQL table. ClickHouse tries to [cast](../../../engines/database-engines/mysql.md#data_types-support) values to the ClickHouse data types.
|
||||
- The [external_table_functions_use_nulls](../../../operations/settings/settings.md#external-table-functions-use-nulls) setting defines how to handle Nullable columns. Default value: 1. If 0, the table function does not make Nullable columns and inserts default values instead of nulls. This is also applicable for NULL values inside arrays.
|
||||
- Column names should be the same as in the original MySQL table, but you can use just some of these columns and in any order.
|
||||
- Column types may differ from those in the original MySQL table. ClickHouse tries to [cast](../../../engines/database-engines/mysql.md#data_types-support) values to the ClickHouse data types.
|
||||
- The [external_table_functions_use_nulls](../../../operations/settings/settings.md#external-table-functions-use-nulls) setting defines how to handle Nullable columns. Default value: 1. If 0, the table function does not make Nullable columns and inserts default values instead of nulls. This is also applicable for NULL values inside arrays.
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `host:port` — MySQL server address.
|
||||
- `host:port` — MySQL server address.
|
||||
|
||||
- `database` — Remote database name.
|
||||
- `database` — Remote database name.
|
||||
|
||||
- `table` — Remote table name.
|
||||
- `table` — Remote table name.
|
||||
|
||||
- `user` — MySQL user.
|
||||
- `user` — MySQL user.
|
||||
|
||||
- `password` — User password.
|
||||
- `password` — User password.
|
||||
|
||||
- `replace_query` — Flag that converts `INSERT INTO` queries to `REPLACE INTO`. If `replace_query=1`, the query is substituted.
|
||||
- `replace_query` — Flag that converts `INSERT INTO` queries to `REPLACE INTO`. If `replace_query=1`, the query is substituted.
|
||||
|
||||
- `on_duplicate_clause` — The `ON DUPLICATE KEY on_duplicate_clause` expression that is added to the `INSERT` query.
|
||||
- `on_duplicate_clause` — The `ON DUPLICATE KEY on_duplicate_clause` expression that is added to the `INSERT` query.
|
||||
|
||||
Example: `INSERT INTO t (c1,c2) VALUES ('a', 2) ON DUPLICATE KEY UPDATE c2 = c2 + 1`, where `on_duplicate_clause` is `UPDATE c2 = c2 + 1`. See the [MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html) to find which `on_duplicate_clause` you can use with the `ON DUPLICATE KEY` clause.
|
||||
|
||||
@ -121,8 +121,8 @@ Allows to automatically close the connection after query execution, i.e. disable
|
||||
|
||||
Possible values:
|
||||
|
||||
- 1 — Auto-close connection is allowed, so the connection reuse is disabled
|
||||
- 0 — Auto-close connection is not allowed, so the connection reuse is enabled
|
||||
- 1 — Auto-close connection is allowed, so the connection reuse is disabled
|
||||
- 0 — Auto-close connection is not allowed, so the connection reuse is enabled
|
||||
|
||||
Default value: `1`.
|
||||
|
||||
@ -132,8 +132,8 @@ Sets the number of retries for pool with failover.
|
||||
|
||||
Possible values:
|
||||
|
||||
- Positive integer.
|
||||
- 0 — There are no retries for pool with failover.
|
||||
- Positive integer.
|
||||
- 0 — There are no retries for pool with failover.
|
||||
|
||||
Default value: `3`.
|
||||
|
||||
@ -143,7 +143,7 @@ Size of connection pool (if all connections are in use, the query will wait unti
|
||||
|
||||
Possible values:
|
||||
|
||||
- Positive integer.
|
||||
- Positive integer.
|
||||
|
||||
Default value: `16`.
|
||||
|
||||
@ -153,7 +153,7 @@ Timeout (in seconds) for waiting for free connection (in case of there is alread
|
||||
|
||||
Possible values:
|
||||
|
||||
- Positive integer.
|
||||
- Positive integer.
|
||||
|
||||
Default value: `5`.
|
||||
|
||||
@ -163,7 +163,7 @@ Connect timeout (in seconds).
|
||||
|
||||
Possible values:
|
||||
|
||||
- Positive integer.
|
||||
- Positive integer.
|
||||
|
||||
Default value: `10`.
|
||||
|
||||
@ -173,11 +173,11 @@ Read/write timeout (in seconds).
|
||||
|
||||
Possible values:
|
||||
|
||||
- Positive integer.
|
||||
- Positive integer.
|
||||
|
||||
Default value: `300`.
|
||||
|
||||
## See Also {#see-also}
|
||||
|
||||
- [The mysql table function](../../../sql-reference/table-functions/mysql.md)
|
||||
- [Using MySQL as a dictionary source](../../../sql-reference/dictionaries/index.md#dictionary-sources#dicts-external_dicts_dict_sources-mysql)
|
||||
- [The mysql table function](../../../sql-reference/table-functions/mysql.md)
|
||||
- [Using MySQL as a dictionary source](../../../sql-reference/dictionaries/index.md#dictionary-sources#dicts-external_dicts_dict_sources-mysql)
|
||||
|
@ -45,9 +45,9 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
|
||||
|
||||
Required parameters:
|
||||
|
||||
- `nats_url` – host:port (for example, `localhost:5672`)..
|
||||
- `nats_subjects` – List of subject for NATS table to subscribe/publsh to. Supports wildcard subjects like `foo.*.bar` or `baz.>`
|
||||
- `nats_format` – Message format. Uses the same notation as the SQL `FORMAT` function, such as `JSONEachRow`. For more information, see the [Formats](../../../interfaces/formats.md) section.
|
||||
- `nats_url` – host:port (for example, `localhost:5672`)..
|
||||
- `nats_subjects` – List of subject for NATS table to subscribe/publsh to. Supports wildcard subjects like `foo.*.bar` or `baz.>`
|
||||
- `nats_format` – Message format. Uses the same notation as the SQL `FORMAT` function, such as `JSONEachRow`. For more information, see the [Formats](../../../interfaces/formats.md) section.
|
||||
|
||||
Optional parameters:
|
||||
|
||||
|
@ -28,15 +28,15 @@ See a detailed description of the [CREATE TABLE](../../../sql-reference/statemen
|
||||
|
||||
The table structure can differ from the source table structure:
|
||||
|
||||
- Column names should be the same as in the source table, but you can use just some of these columns and in any order.
|
||||
- Column types may differ from those in the source table. ClickHouse tries to [cast](../../../sql-reference/functions/type-conversion-functions.md#type_conversion_function-cast) values to the ClickHouse data types.
|
||||
- The [external_table_functions_use_nulls](../../../operations/settings/settings.md#external-table-functions-use-nulls) setting defines how to handle Nullable columns. Default value: 1. If 0, the table function does not make Nullable columns and inserts default values instead of nulls. This is also applicable for NULL values inside arrays.
|
||||
- Column names should be the same as in the source table, but you can use just some of these columns and in any order.
|
||||
- Column types may differ from those in the source table. ClickHouse tries to [cast](../../../sql-reference/functions/type-conversion-functions.md#type_conversion_function-cast) values to the ClickHouse data types.
|
||||
- The [external_table_functions_use_nulls](../../../operations/settings/settings.md#external-table-functions-use-nulls) setting defines how to handle Nullable columns. Default value: 1. If 0, the table function does not make Nullable columns and inserts default values instead of nulls. This is also applicable for NULL values inside arrays.
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `connection_settings` — Name of the section with connection settings in the `odbc.ini` file.
|
||||
- `external_database` — Name of a database in an external DBMS.
|
||||
- `external_table` — Name of a table in the `external_database`.
|
||||
- `connection_settings` — Name of the section with connection settings in the `odbc.ini` file.
|
||||
- `external_database` — Name of a database in an external DBMS.
|
||||
- `external_table` — Name of a table in the `external_database`.
|
||||
|
||||
## Usage Example {#usage-example}
|
||||
|
||||
@ -126,5 +126,5 @@ SELECT * FROM odbc_t
|
||||
|
||||
## See Also {#see-also}
|
||||
|
||||
- [ODBC dictionaries](../../../sql-reference/dictionaries/index.md#dictionary-sources#dicts-external_dicts_dict_sources-odbc)
|
||||
- [ODBC table function](../../../sql-reference/table-functions/odbc.md)
|
||||
- [ODBC dictionaries](../../../sql-reference/dictionaries/index.md#dictionary-sources#dicts-external_dicts_dict_sources-odbc)
|
||||
- [ODBC table function](../../../sql-reference/table-functions/odbc.md)
|
||||
|
@ -23,19 +23,19 @@ See a detailed description of the [CREATE TABLE](../../../sql-reference/statemen
|
||||
|
||||
The table structure can differ from the original PostgreSQL table structure:
|
||||
|
||||
- Column names should be the same as in the original PostgreSQL table, but you can use just some of these columns and in any order.
|
||||
- Column types may differ from those in the original PostgreSQL table. ClickHouse tries to [cast](../../../engines/database-engines/postgresql.md#data_types-support) values to the ClickHouse data types.
|
||||
- The [external_table_functions_use_nulls](../../../operations/settings/settings.md#external-table-functions-use-nulls) setting defines how to handle Nullable columns. Default value: 1. If 0, the table function does not make Nullable columns and inserts default values instead of nulls. This is also applicable for NULL values inside arrays.
|
||||
- Column names should be the same as in the original PostgreSQL table, but you can use just some of these columns and in any order.
|
||||
- Column types may differ from those in the original PostgreSQL table. ClickHouse tries to [cast](../../../engines/database-engines/postgresql.md#data_types-support) values to the ClickHouse data types.
|
||||
- The [external_table_functions_use_nulls](../../../operations/settings/settings.md#external-table-functions-use-nulls) setting defines how to handle Nullable columns. Default value: 1. If 0, the table function does not make Nullable columns and inserts default values instead of nulls. This is also applicable for NULL values inside arrays.
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `host:port` — PostgreSQL server address.
|
||||
- `database` — Remote database name.
|
||||
- `table` — Remote table name.
|
||||
- `user` — PostgreSQL user.
|
||||
- `password` — User password.
|
||||
- `schema` — Non-default table schema. Optional.
|
||||
- `on conflict ...` — example: `ON CONFLICT DO NOTHING`. Optional. Note: adding this option will make insertion less efficient.
|
||||
- `host:port` — PostgreSQL server address.
|
||||
- `database` — Remote database name.
|
||||
- `table` — Remote table name.
|
||||
- `user` — PostgreSQL user.
|
||||
- `password` — User password.
|
||||
- `schema` — Non-default table schema. Optional.
|
||||
- `on conflict ...` — example: `ON CONFLICT DO NOTHING`. Optional. Note: adding this option will make insertion less efficient.
|
||||
|
||||
or via config (since version 21.11):
|
||||
|
||||
@ -111,7 +111,7 @@ In the example below replica `example01-1` has the highest priority:
|
||||
|
||||
## Usage Example {#usage-example}
|
||||
|
||||
Table in PostgreSQL:
|
||||
### Table in PostgreSQL
|
||||
|
||||
``` text
|
||||
postgres=# CREATE TABLE "public"."test" (
|
||||
@ -134,7 +134,9 @@ postgresql> SELECT * FROM test;
|
||||
(1 row)
|
||||
```
|
||||
|
||||
Table in ClickHouse, retrieving data from the PostgreSQL table created above:
|
||||
### Creating Table in ClickHouse, and connecting to PostgreSQL table created above
|
||||
|
||||
This example uses the [PostgreSQL table engine](/docs/en/engines/table-engines/integrations/postgresql.md) to connect the ClickHouse table to the PostgreSQL table:
|
||||
|
||||
``` sql
|
||||
CREATE TABLE default.postgresql_table
|
||||
@ -146,6 +148,35 @@ CREATE TABLE default.postgresql_table
|
||||
ENGINE = PostgreSQL('localhost:5432', 'public', 'test', 'postges_user', 'postgres_password');
|
||||
```
|
||||
|
||||
### Inserting initial data from PostgreSQL table into ClickHouse table, using a SELECT query
|
||||
|
||||
The [postgresql table function](/docs/en/sql-reference/table-functions/postgresql.md) copies the data from PostgreSQL to ClickHouse, which is often used for improving the query performance of the data by querying or performing analytics in ClickHouse rather than in PostgreSQL, or can also be used for migrating data from PostgreSQL to ClickHouse:
|
||||
|
||||
``` sql
|
||||
INSERT INTO default.postgresql_table
|
||||
SELECT * FROM postgresql('localhost:5432', 'public', 'test', 'postges_user', 'postgres_password');
|
||||
```
|
||||
|
||||
### Inserting incremental data from PostgreSQL table into ClickHouse table
|
||||
|
||||
If then performing ongoing synchronization between the PostgreSQL table and ClickHouse table after the initial insert, you can use a WHERE clause in ClickHouse to insert only data added to PostgreSQL based on a timestamp or unique sequence ID.
|
||||
|
||||
This would require keeping track of the max ID or timestamp previously added, such as the following:
|
||||
|
||||
``` sql
|
||||
SELECT max(`int_id`) AS maxIntID FROM default.postgresql_table;
|
||||
```
|
||||
|
||||
Then inserting values from PostgreSQL table greater than the max
|
||||
|
||||
``` sql
|
||||
INSERT INTO default.postgresql_table
|
||||
SELECT * FROM postgresql('localhost:5432', 'public', 'test', 'postges_user', 'postgres_password');
|
||||
WHERE int_id > maxIntID;
|
||||
```
|
||||
|
||||
### Selecting data from the resulting ClickHouse table
|
||||
|
||||
``` sql
|
||||
SELECT * FROM postgresql_table WHERE str IN ('test');
|
||||
```
|
||||
@ -156,7 +187,7 @@ SELECT * FROM postgresql_table WHERE str IN ('test');
|
||||
└────────────────┴──────┴────────┘
|
||||
```
|
||||
|
||||
Using Non-default Schema:
|
||||
### Using Non-default Schema
|
||||
|
||||
```text
|
||||
postgres=# CREATE SCHEMA "nice.schema";
|
||||
@ -173,8 +204,8 @@ CREATE TABLE pg_table_schema_with_dots (a UInt32)
|
||||
|
||||
**See Also**
|
||||
|
||||
- [The `postgresql` table function](../../../sql-reference/table-functions/postgresql.md)
|
||||
- [Using PostgreSQL as a dictionary source](../../../sql-reference/dictionaries/index.md#dictionary-sources#dicts-external_dicts_dict_sources-postgresql)
|
||||
- [The `postgresql` table function](../../../sql-reference/table-functions/postgresql.md)
|
||||
- [Using PostgreSQL as a dictionary source](../../../sql-reference/dictionaries/index.md#dictionary-sources#dicts-external_dicts_dict_sources-postgresql)
|
||||
|
||||
## Related content
|
||||
|
||||
|
@ -10,8 +10,8 @@ This engine allows integrating ClickHouse with [RabbitMQ](https://www.rabbitmq.c
|
||||
|
||||
`RabbitMQ` lets you:
|
||||
|
||||
- Publish or subscribe to data flows.
|
||||
- Process streams as they become available.
|
||||
- Publish or subscribe to data flows.
|
||||
- Process streams as they become available.
|
||||
|
||||
## Creating a Table {#table_engine-rabbitmq-creating-a-table}
|
||||
|
||||
@ -51,9 +51,9 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
|
||||
|
||||
Required parameters:
|
||||
|
||||
- `rabbitmq_host_port` – host:port (for example, `localhost:5672`).
|
||||
- `rabbitmq_exchange_name` – RabbitMQ exchange name.
|
||||
- `rabbitmq_format` – Message format. Uses the same notation as the SQL `FORMAT` function, such as `JSONEachRow`. For more information, see the [Formats](../../../interfaces/formats.md) section.
|
||||
- `rabbitmq_host_port` – host:port (for example, `localhost:5672`).
|
||||
- `rabbitmq_exchange_name` – RabbitMQ exchange name.
|
||||
- `rabbitmq_format` – Message format. Uses the same notation as the SQL `FORMAT` function, such as `JSONEachRow`. For more information, see the [Formats](../../../interfaces/formats.md) section.
|
||||
|
||||
Optional parameters:
|
||||
|
||||
@ -138,24 +138,24 @@ There can be no more than one exchange per table. One exchange can be shared bet
|
||||
|
||||
Exchange type options:
|
||||
|
||||
- `direct` - Routing is based on the exact matching of keys. Example table key list: `key1,key2,key3,key4,key5`, message key can equal any of them.
|
||||
- `fanout` - Routing to all tables (where exchange name is the same) regardless of the keys.
|
||||
- `topic` - Routing is based on patterns with dot-separated keys. Examples: `*.logs`, `records.*.*.2020`, `*.2018,*.2019,*.2020`.
|
||||
- `headers` - Routing is based on `key=value` matches with a setting `x-match=all` or `x-match=any`. Example table key list: `x-match=all,format=logs,type=report,year=2020`.
|
||||
- `consistent_hash` - Data is evenly distributed between all bound tables (where the exchange name is the same). Note that this exchange type must be enabled with RabbitMQ plugin: `rabbitmq-plugins enable rabbitmq_consistent_hash_exchange`.
|
||||
- `direct` - Routing is based on the exact matching of keys. Example table key list: `key1,key2,key3,key4,key5`, message key can equal any of them.
|
||||
- `fanout` - Routing to all tables (where exchange name is the same) regardless of the keys.
|
||||
- `topic` - Routing is based on patterns with dot-separated keys. Examples: `*.logs`, `records.*.*.2020`, `*.2018,*.2019,*.2020`.
|
||||
- `headers` - Routing is based on `key=value` matches with a setting `x-match=all` or `x-match=any`. Example table key list: `x-match=all,format=logs,type=report,year=2020`.
|
||||
- `consistent_hash` - Data is evenly distributed between all bound tables (where the exchange name is the same). Note that this exchange type must be enabled with RabbitMQ plugin: `rabbitmq-plugins enable rabbitmq_consistent_hash_exchange`.
|
||||
|
||||
Setting `rabbitmq_queue_base` may be used for the following cases:
|
||||
|
||||
- to let different tables share queues, so that multiple consumers could be registered for the same queues, which makes a better performance. If using `rabbitmq_num_consumers` and/or `rabbitmq_num_queues` settings, the exact match of queues is achieved in case these parameters are the same.
|
||||
- to be able to restore reading from certain durable queues when not all messages were successfully consumed. To resume consumption from one specific queue - set its name in `rabbitmq_queue_base` setting and do not specify `rabbitmq_num_consumers` and `rabbitmq_num_queues` (defaults to 1). To resume consumption from all queues, which were declared for a specific table - just specify the same settings: `rabbitmq_queue_base`, `rabbitmq_num_consumers`, `rabbitmq_num_queues`. By default, queue names will be unique to tables.
|
||||
- to reuse queues as they are declared durable and not auto-deleted. (Can be deleted via any of RabbitMQ CLI tools.)
|
||||
- to let different tables share queues, so that multiple consumers could be registered for the same queues, which makes a better performance. If using `rabbitmq_num_consumers` and/or `rabbitmq_num_queues` settings, the exact match of queues is achieved in case these parameters are the same.
|
||||
- to be able to restore reading from certain durable queues when not all messages were successfully consumed. To resume consumption from one specific queue - set its name in `rabbitmq_queue_base` setting and do not specify `rabbitmq_num_consumers` and `rabbitmq_num_queues` (defaults to 1). To resume consumption from all queues, which were declared for a specific table - just specify the same settings: `rabbitmq_queue_base`, `rabbitmq_num_consumers`, `rabbitmq_num_queues`. By default, queue names will be unique to tables.
|
||||
- to reuse queues as they are declared durable and not auto-deleted. (Can be deleted via any of RabbitMQ CLI tools.)
|
||||
|
||||
To improve performance, received messages are grouped into blocks the size of [max_insert_block_size](../../../operations/server-configuration-parameters/settings.md#settings-max_insert_block_size). If the block wasn’t formed within [stream_flush_interval_ms](../../../operations/server-configuration-parameters/settings.md) milliseconds, the data will be flushed to the table regardless of the completeness of the block.
|
||||
|
||||
If `rabbitmq_num_consumers` and/or `rabbitmq_num_queues` settings are specified along with `rabbitmq_exchange_type`, then:
|
||||
|
||||
- `rabbitmq-consistent-hash-exchange` plugin must be enabled.
|
||||
- `message_id` property of the published messages must be specified (unique for each message/batch).
|
||||
- `rabbitmq-consistent-hash-exchange` plugin must be enabled.
|
||||
- `message_id` property of the published messages must be specified (unique for each message/batch).
|
||||
|
||||
For insert query there is message metadata, which is added for each published message: `messageID` and `republished` flag (true, if published more than once) - can be accessed via message headers.
|
||||
|
||||
|
@ -19,11 +19,11 @@ CREATE TABLE s3_engine_table (name String, value UInt32)
|
||||
|
||||
**Engine parameters**
|
||||
|
||||
- `path` — Bucket url with path to file. Supports following wildcards in readonly mode: `*`, `?`, `{abc,def}` and `{N..M}` where `N`, `M` — numbers, `'abc'`, `'def'` — strings. For more information see [below](#wildcards-in-path).
|
||||
- `NOSIGN` - If this keyword is provided in place of credentials, all the requests will not be signed.
|
||||
- `format` — The [format](../../../interfaces/formats.md#formats) of the file.
|
||||
- `aws_access_key_id`, `aws_secret_access_key` - Long-term credentials for the [AWS](https://aws.amazon.com/) account user. You can use these to authenticate your requests. Parameter is optional. If credentials are not specified, they are used from the configuration file. For more information see [Using S3 for Data Storage](../mergetree-family/mergetree.md#table_engine-mergetree-s3).
|
||||
- `compression` — Compression type. Supported values: `none`, `gzip/gz`, `brotli/br`, `xz/LZMA`, `zstd/zst`. Parameter is optional. By default, it will autodetect compression by file extension.
|
||||
- `path` — Bucket url with path to file. Supports following wildcards in readonly mode: `*`, `?`, `{abc,def}` and `{N..M}` where `N`, `M` — numbers, `'abc'`, `'def'` — strings. For more information see [below](#wildcards-in-path).
|
||||
- `NOSIGN` - If this keyword is provided in place of credentials, all the requests will not be signed.
|
||||
- `format` — The [format](../../../interfaces/formats.md#formats) of the file.
|
||||
- `aws_access_key_id`, `aws_secret_access_key` - Long-term credentials for the [AWS](https://aws.amazon.com/) account user. You can use these to authenticate your requests. Parameter is optional. If credentials are not specified, they are used from the configuration file. For more information see [Using S3 for Data Storage](../mergetree-family/mergetree.md#table_engine-mergetree-s3).
|
||||
- `compression` — Compression type. Supported values: `none`, `gzip/gz`, `brotli/br`, `xz/LZMA`, `zstd/zst`. Parameter is optional. By default, it will autodetect compression by file extension.
|
||||
|
||||
### PARTITION BY
|
||||
|
||||
@ -51,18 +51,18 @@ SELECT * FROM s3_engine_table LIMIT 2;
|
||||
```
|
||||
## Virtual columns {#virtual-columns}
|
||||
|
||||
- `_path` — Path to the file.
|
||||
- `_file` — Name of the file.
|
||||
- `_path` — Path to the file.
|
||||
- `_file` — Name of the file.
|
||||
|
||||
For more information about virtual columns see [here](../../../engines/table-engines/index.md#table_engines-virtual_columns).
|
||||
|
||||
## Implementation Details {#implementation-details}
|
||||
|
||||
- Reads and writes can be parallel
|
||||
- Not supported:
|
||||
- `ALTER` and `SELECT...SAMPLE` operations.
|
||||
- Indexes.
|
||||
- [Zero-copy](../../../operations/storing-data.md#zero-copy) replication is possible, but not supported.
|
||||
- Reads and writes can be parallel
|
||||
- Not supported:
|
||||
- `ALTER` and `SELECT...SAMPLE` operations.
|
||||
- Indexes.
|
||||
- [Zero-copy](../../../operations/storing-data.md#zero-copy) replication is possible, but not supported.
|
||||
|
||||
:::note Zero-copy replication is not ready for production
|
||||
Zero-copy replication is disabled by default in ClickHouse version 22.8 and higher. This feature is not recommended for production use.
|
||||
@ -72,10 +72,10 @@ For more information about virtual columns see [here](../../../engines/table-eng
|
||||
|
||||
`path` argument can specify multiple files using bash-like wildcards. For being processed file should exist and match to the whole path pattern. Listing of files is determined during `SELECT` (not at `CREATE` moment).
|
||||
|
||||
- `*` — Substitutes any number of any characters except `/` including empty string.
|
||||
- `?` — Substitutes any single character.
|
||||
- `{some_string,another_string,yet_another_one}` — Substitutes any of strings `'some_string', 'another_string', 'yet_another_one'`.
|
||||
- `{N..M}` — Substitutes any number in range from N to M including both borders. N and M can have leading zeroes e.g. `000..078`.
|
||||
- `*` — Substitutes any number of any characters except `/` including empty string.
|
||||
- `?` — Substitutes any single character.
|
||||
- `{some_string,another_string,yet_another_one}` — Substitutes any of strings `'some_string', 'another_string', 'yet_another_one'`.
|
||||
- `{N..M}` — Substitutes any number in range from N to M including both borders. N and M can have leading zeroes e.g. `000..078`.
|
||||
|
||||
Constructions with `{}` are similar to the [remote](../../../sql-reference/table-functions/remote.md) table function.
|
||||
|
||||
@ -96,12 +96,12 @@ CREATE TABLE big_table (name String, value UInt32)
|
||||
|
||||
Suppose we have several files in CSV format with the following URIs on S3:
|
||||
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/some_folder/some_file_1.csv'
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/some_folder/some_file_2.csv'
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/some_folder/some_file_3.csv'
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/another_folder/some_file_1.csv'
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/another_folder/some_file_2.csv'
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/another_folder/some_file_3.csv'
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/some_folder/some_file_1.csv'
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/some_folder/some_file_2.csv'
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/some_folder/some_file_3.csv'
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/another_folder/some_file_1.csv'
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/another_folder/some_file_2.csv'
|
||||
- 'https://clickhouse-public-datasets.s3.amazonaws.com/my-bucket/another_folder/some_file_3.csv'
|
||||
|
||||
|
||||
There are several ways to make a table consisting of all six files:
|
||||
@ -131,14 +131,14 @@ CREATE TABLE table_with_asterisk (name String, value UInt32)
|
||||
|
||||
The following settings can be set before query execution or placed into configuration file.
|
||||
|
||||
- `s3_max_single_part_upload_size` — The maximum size of object to upload using singlepart upload to S3. Default value is `64Mb`.
|
||||
- `s3_min_upload_part_size` — The minimum size of part to upload during multipart upload to [S3 Multipart upload](https://docs.aws.amazon.com/AmazonS3/latest/dev/uploadobjusingmpu.html). Default value is `512Mb`.
|
||||
- `s3_max_redirects` — Max number of S3 redirects hops allowed. Default value is `10`.
|
||||
- `s3_single_read_retries` — The maximum number of attempts during single read. Default value is `4`.
|
||||
- `s3_max_put_rps` — Maximum PUT requests per second rate before throttling. Default value is `0` (unlimited).
|
||||
- `s3_max_put_burst` — Max number of requests that can be issued simultaneously before hitting request per second limit. By default (`0` value) equals to `s3_max_put_rps`.
|
||||
- `s3_max_get_rps` — Maximum GET requests per second rate before throttling. Default value is `0` (unlimited).
|
||||
- `s3_max_get_burst` — Max number of requests that can be issued simultaneously before hitting request per second limit. By default (`0` value) equals to `s3_max_get_rps`.
|
||||
- `s3_max_single_part_upload_size` — The maximum size of object to upload using singlepart upload to S3. Default value is `64Mb`.
|
||||
- `s3_min_upload_part_size` — The minimum size of part to upload during multipart upload to [S3 Multipart upload](https://docs.aws.amazon.com/AmazonS3/latest/dev/uploadobjusingmpu.html). Default value is `512Mb`.
|
||||
- `s3_max_redirects` — Max number of S3 redirects hops allowed. Default value is `10`.
|
||||
- `s3_single_read_retries` — The maximum number of attempts during single read. Default value is `4`.
|
||||
- `s3_max_put_rps` — Maximum PUT requests per second rate before throttling. Default value is `0` (unlimited).
|
||||
- `s3_max_put_burst` — Max number of requests that can be issued simultaneously before hitting request per second limit. By default (`0` value) equals to `s3_max_put_rps`.
|
||||
- `s3_max_get_rps` — Maximum GET requests per second rate before throttling. Default value is `0` (unlimited).
|
||||
- `s3_max_get_burst` — Max number of requests that can be issued simultaneously before hitting request per second limit. By default (`0` value) equals to `s3_max_get_rps`.
|
||||
|
||||
Security consideration: if malicious user can specify arbitrary S3 URLs, `s3_max_redirects` must be set to zero to avoid [SSRF](https://en.wikipedia.org/wiki/Server-side_request_forgery) attacks; or alternatively, `remote_host_filter` must be specified in server configuration.
|
||||
|
||||
@ -146,17 +146,17 @@ Security consideration: if malicious user can specify arbitrary S3 URLs, `s3_max
|
||||
|
||||
The following settings can be specified in configuration file for given endpoint (which will be matched by exact prefix of a URL):
|
||||
|
||||
- `endpoint` — Specifies prefix of an endpoint. Mandatory.
|
||||
- `access_key_id` and `secret_access_key` — Specifies credentials to use with given endpoint. Optional.
|
||||
- `use_environment_credentials` — If set to `true`, S3 client will try to obtain credentials from environment variables and [Amazon EC2](https://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud) metadata for given endpoint. Optional, default value is `false`.
|
||||
- `region` — Specifies S3 region name. Optional.
|
||||
- `use_insecure_imds_request` — If set to `true`, S3 client will use insecure IMDS request while obtaining credentials from Amazon EC2 metadata. Optional, default value is `false`.
|
||||
- `expiration_window_seconds` — Grace period for checking if expiration-based credentials have expired. Optional, default value is `120`.
|
||||
- `no_sign_request` - Ignore all the credentials so requests are not signed. Useful for accessing public buckets.
|
||||
- `header` — Adds specified HTTP header to a request to given endpoint. Optional, can be specified multiple times.
|
||||
- `server_side_encryption_customer_key_base64` — If specified, required headers for accessing S3 objects with SSE-C encryption will be set. Optional.
|
||||
- `max_single_read_retries` — The maximum number of attempts during single read. Default value is `4`. Optional.
|
||||
- `max_put_rps`, `max_put_burst`, `max_get_rps` and `max_get_burst` - Throttling settings (see description above) to use for specific endpoint instead of per query. Optional.
|
||||
- `endpoint` — Specifies prefix of an endpoint. Mandatory.
|
||||
- `access_key_id` and `secret_access_key` — Specifies credentials to use with given endpoint. Optional.
|
||||
- `use_environment_credentials` — If set to `true`, S3 client will try to obtain credentials from environment variables and [Amazon EC2](https://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud) metadata for given endpoint. Optional, default value is `false`.
|
||||
- `region` — Specifies S3 region name. Optional.
|
||||
- `use_insecure_imds_request` — If set to `true`, S3 client will use insecure IMDS request while obtaining credentials from Amazon EC2 metadata. Optional, default value is `false`.
|
||||
- `expiration_window_seconds` — Grace period for checking if expiration-based credentials have expired. Optional, default value is `120`.
|
||||
- `no_sign_request` - Ignore all the credentials so requests are not signed. Useful for accessing public buckets.
|
||||
- `header` — Adds specified HTTP header to a request to given endpoint. Optional, can be specified multiple times.
|
||||
- `server_side_encryption_customer_key_base64` — If specified, required headers for accessing S3 objects with SSE-C encryption will be set. Optional.
|
||||
- `max_single_read_retries` — The maximum number of attempts during single read. Default value is `4`. Optional.
|
||||
- `max_put_rps`, `max_put_burst`, `max_get_rps` and `max_get_burst` - Throttling settings (see description above) to use for specific endpoint instead of per query. Optional.
|
||||
|
||||
**Example:**
|
||||
|
||||
@ -191,4 +191,4 @@ CREATE TABLE big_table (name String, value UInt32)
|
||||
|
||||
## See also
|
||||
|
||||
- [s3 table function](../../../sql-reference/table-functions/s3.md)
|
||||
- [s3 table function](../../../sql-reference/table-functions/s3.md)
|
||||
|
@ -20,8 +20,8 @@ The engine allows to import and export data to SQLite and supports queries to SQ
|
||||
|
||||
**Engine Parameters**
|
||||
|
||||
- `db_path` — Path to SQLite file with a database.
|
||||
- `table` — Name of a table in the SQLite database.
|
||||
- `db_path` — Path to SQLite file with a database.
|
||||
- `table` — Name of a table in the SQLite database.
|
||||
|
||||
## Usage Example {#usage-example}
|
||||
|
||||
@ -56,5 +56,5 @@ SELECT * FROM sqlite_db.table2 ORDER BY col1;
|
||||
|
||||
**See Also**
|
||||
|
||||
- [SQLite](../../../engines/database-engines/sqlite.md) engine
|
||||
- [sqlite](../../../sql-reference/table-functions/sqlite.md) table function
|
||||
- [SQLite](../../../engines/database-engines/sqlite.md) engine
|
||||
- [sqlite](../../../sql-reference/table-functions/sqlite.md) table function
|
||||
|
@ -10,9 +10,9 @@ These engines were developed for scenarios when you need to quickly write many s
|
||||
|
||||
Engines of the family:
|
||||
|
||||
- [StripeLog](/docs/en/engines/table-engines/log-family/stripelog.md)
|
||||
- [Log](/docs/en/engines/table-engines/log-family/log.md)
|
||||
- [TinyLog](/docs/en/engines/table-engines/log-family/tinylog.md)
|
||||
- [StripeLog](/docs/en/engines/table-engines/log-family/stripelog.md)
|
||||
- [Log](/docs/en/engines/table-engines/log-family/log.md)
|
||||
- [TinyLog](/docs/en/engines/table-engines/log-family/tinylog.md)
|
||||
|
||||
`Log` family table engines can store data to [HDFS](/docs/en/engines/table-engines/mergetree-family/mergetree.md/#table_engine-mergetree-hdfs) or [S3](/docs/en/engines/table-engines/mergetree-family/mergetree.md/#table_engine-mergetree-s3) distributed file systems.
|
||||
|
||||
@ -20,21 +20,21 @@ Engines of the family:
|
||||
|
||||
Engines:
|
||||
|
||||
- Store data on a disk.
|
||||
- Store data on a disk.
|
||||
|
||||
- Append data to the end of file when writing.
|
||||
- Append data to the end of file when writing.
|
||||
|
||||
- Support locks for concurrent data access.
|
||||
- Support locks for concurrent data access.
|
||||
|
||||
During `INSERT` queries, the table is locked, and other queries for reading and writing data both wait for the table to unlock. If there are no data writing queries, any number of data reading queries can be performed concurrently.
|
||||
|
||||
- Do not support [mutations](/docs/en/sql-reference/statements/alter/index.md#alter-mutations).
|
||||
- Do not support [mutations](/docs/en/sql-reference/statements/alter/index.md#alter-mutations).
|
||||
|
||||
- Do not support indexes.
|
||||
- Do not support indexes.
|
||||
|
||||
This means that `SELECT` queries for ranges of data are not efficient.
|
||||
|
||||
- Do not write data atomically.
|
||||
- Do not write data atomically.
|
||||
|
||||
You can get a table with corrupted data if something breaks the write operation, for example, abnormal server shutdown.
|
||||
|
||||
|
@ -29,8 +29,8 @@ The `StripeLog` engine stores all the columns in one file. For each `INSERT` que
|
||||
|
||||
For each table ClickHouse writes the files:
|
||||
|
||||
- `data.bin` — Data file.
|
||||
- `index.mrk` — File with marks. Marks contain offsets for each column of each data block inserted.
|
||||
- `data.bin` — Data file.
|
||||
- `index.mrk` — File with marks. Marks contain offsets for each column of each data block inserted.
|
||||
|
||||
The `StripeLog` engine does not support the `ALTER UPDATE` and `ALTER DELETE` operations.
|
||||
|
||||
|
@ -60,7 +60,7 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
|
||||
|
||||
All of the parameters excepting `sign` have the same meaning as in `MergeTree`.
|
||||
|
||||
- `sign` — Name of the column with the type of row: `1` — “state” row, `-1` — “cancel” row.
|
||||
- `sign` — Name of the column with the type of row: `1` — “state” row, `-1` — “cancel” row.
|
||||
|
||||
Column Data Type — `Int8`.
|
||||
|
||||
|
@ -77,11 +77,11 @@ The `name` column contains the names of the partition data parts. You can use th
|
||||
|
||||
Let’s break down the name of the part: `201901_1_9_2_11`:
|
||||
|
||||
- `201901` is the partition name.
|
||||
- `1` is the minimum number of the data block.
|
||||
- `9` is the maximum number of the data block.
|
||||
- `2` is the chunk level (the depth of the merge tree it is formed from).
|
||||
- `11` is the mutation version (if a part mutated)
|
||||
- `201901` is the partition name.
|
||||
- `1` is the minimum number of the data block.
|
||||
- `9` is the maximum number of the data block.
|
||||
- `2` is the chunk level (the depth of the merge tree it is formed from).
|
||||
- `11` is the mutation version (if a part mutated)
|
||||
|
||||
:::info
|
||||
The parts of old-type tables have the name: `20190117_20190123_2_2_0` (minimum date - maximum date - minimum block number - maximum block number - level).
|
||||
@ -165,9 +165,9 @@ Performance of such a query heavily depends on the table layout. Because of that
|
||||
|
||||
The key factors for a good performance:
|
||||
|
||||
- number of partitions involved in the query should be sufficiently large (more than `max_threads / 2`), otherwise query will underutilize the machine
|
||||
- partitions shouldn't be too small, so batch processing won't degenerate into row-by-row processing
|
||||
- partitions should be comparable in size, so all threads will do roughly the same amount of work
|
||||
- number of partitions involved in the query should be sufficiently large (more than `max_threads / 2`), otherwise query will underutilize the machine
|
||||
- partitions shouldn't be too small, so batch processing won't degenerate into row-by-row processing
|
||||
- partitions should be comparable in size, so all threads will do roughly the same amount of work
|
||||
|
||||
:::info
|
||||
It's recommended to apply some hash function to columns in `partition by` clause in order to distribute data evenly between partitions.
|
||||
@ -175,6 +175,6 @@ It's recommended to apply some hash function to columns in `partition by` clause
|
||||
|
||||
Relevant settings are:
|
||||
|
||||
- `allow_aggregate_partitions_independently` - controls if the use of optimisation is enabled
|
||||
- `force_aggregate_partitions_independently` - forces its use when it's applicable from the correctness standpoint, but getting disabled by internal logic that estimates its expediency
|
||||
- `max_number_of_partitions_for_independent_aggregation` - hard limit on the maximal number of partitions table could have
|
||||
- `allow_aggregate_partitions_independently` - controls if the use of optimisation is enabled
|
||||
- `force_aggregate_partitions_independently` - forces its use when it's applicable from the correctness standpoint, but getting disabled by internal logic that estimates its expediency
|
||||
- `max_number_of_partitions_for_independent_aggregation` - hard limit on the maximal number of partitions table could have
|
||||
|
@ -33,19 +33,19 @@ See a detailed description of the [CREATE TABLE](../../../sql-reference/statemen
|
||||
|
||||
A table for the Graphite data should have the following columns for the following data:
|
||||
|
||||
- Metric name (Graphite sensor). Data type: `String`.
|
||||
- Metric name (Graphite sensor). Data type: `String`.
|
||||
|
||||
- Time of measuring the metric. Data type: `DateTime`.
|
||||
- Time of measuring the metric. Data type: `DateTime`.
|
||||
|
||||
- Value of the metric. Data type: `Float64`.
|
||||
- Value of the metric. Data type: `Float64`.
|
||||
|
||||
- Version of the metric. Data type: any numeric (ClickHouse saves the rows with the highest version or the last written if versions are the same. Other rows are deleted during the merge of data parts).
|
||||
- Version of the metric. Data type: any numeric (ClickHouse saves the rows with the highest version or the last written if versions are the same. Other rows are deleted during the merge of data parts).
|
||||
|
||||
The names of these columns should be set in the rollup configuration.
|
||||
|
||||
**GraphiteMergeTree parameters**
|
||||
|
||||
- `config_section` — Name of the section in the configuration file, where are the rules of rollup set.
|
||||
- `config_section` — Name of the section in the configuration file, where are the rules of rollup set.
|
||||
|
||||
**Query clauses**
|
||||
|
||||
@ -73,7 +73,7 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
|
||||
|
||||
All of the parameters excepting `config_section` have the same meaning as in `MergeTree`.
|
||||
|
||||
- `config_section` — Name of the section in the configuration file, where are the rules of rollup set.
|
||||
- `config_section` — Name of the section in the configuration file, where are the rules of rollup set.
|
||||
|
||||
</details>
|
||||
|
||||
@ -141,18 +141,18 @@ When processing a row, ClickHouse checks the rules in the `pattern` sections. Ea
|
||||
|
||||
Fields for `pattern` and `default` sections:
|
||||
|
||||
- `rule_type` - a rule's type. It's applied only to a particular metrics. The engine use it to separate plain and tagged metrics. Optional parameter. Default value: `all`.
|
||||
- `rule_type` - a rule's type. It's applied only to a particular metrics. The engine use it to separate plain and tagged metrics. Optional parameter. Default value: `all`.
|
||||
It's unnecessary when performance is not critical, or only one metrics type is used, e.g. plain metrics. By default only one type of rules set is created. Otherwise, if any of special types is defined, two different sets are created. One for plain metrics (root.branch.leaf) and one for tagged metrics (root.branch.leaf;tag1=value1).
|
||||
The default rules are ended up in both sets.
|
||||
Valid values:
|
||||
- `all` (default) - a universal rule, used when `rule_type` is omitted.
|
||||
- `plain` - a rule for plain metrics. The field `regexp` is processed as regular expression.
|
||||
- `tagged` - a rule for tagged metrics (metrics are stored in DB in the format of `someName?tag1=value1&tag2=value2&tag3=value3`). Regular expression must be sorted by tags' names, first tag must be `__name__` if exists. The field `regexp` is processed as regular expression.
|
||||
- `tag_list` - a rule for tagged matrics, a simple DSL for easier metric description in graphite format `someName;tag1=value1;tag2=value2`, `someName`, or `tag1=value1;tag2=value2`. The field `regexp` is translated into a `tagged` rule. The sorting by tags' names is unnecessary, ti will be done automatically. A tag's value (but not a name) can be set as a regular expression, e.g. `env=(dev|staging)`.
|
||||
- `regexp` – A pattern for the metric name (a regular or DSL).
|
||||
- `age` – The minimum age of the data in seconds.
|
||||
- `precision`– How precisely to define the age of the data in seconds. Should be a divisor for 86400 (seconds in a day).
|
||||
- `function` – The name of the aggregating function to apply to data whose age falls within the range `[age, age + precision]`. Accepted functions: min / max / any / avg. The average is calculated imprecisely, like the average of the averages.
|
||||
- `all` (default) - a universal rule, used when `rule_type` is omitted.
|
||||
- `plain` - a rule for plain metrics. The field `regexp` is processed as regular expression.
|
||||
- `tagged` - a rule for tagged metrics (metrics are stored in DB in the format of `someName?tag1=value1&tag2=value2&tag3=value3`). Regular expression must be sorted by tags' names, first tag must be `__name__` if exists. The field `regexp` is processed as regular expression.
|
||||
- `tag_list` - a rule for tagged matrics, a simple DSL for easier metric description in graphite format `someName;tag1=value1;tag2=value2`, `someName`, or `tag1=value1;tag2=value2`. The field `regexp` is translated into a `tagged` rule. The sorting by tags' names is unnecessary, ti will be done automatically. A tag's value (but not a name) can be set as a regular expression, e.g. `env=(dev|staging)`.
|
||||
- `regexp` – A pattern for the metric name (a regular or DSL).
|
||||
- `age` – The minimum age of the data in seconds.
|
||||
- `precision`– How precisely to define the age of the data in seconds. Should be a divisor for 86400 (seconds in a day).
|
||||
- `function` – The name of the aggregating function to apply to data whose age falls within the range `[age, age + precision]`. Accepted functions: min / max / any / avg. The average is calculated imprecisely, like the average of the averages.
|
||||
|
||||
### Configuration Example without rules types {#configuration-example}
|
||||
|
||||
|
@ -12,19 +12,19 @@ Engines in the `MergeTree` family are designed for inserting a very large amount
|
||||
|
||||
Main features:
|
||||
|
||||
- Stores data sorted by primary key.
|
||||
- Stores data sorted by primary key.
|
||||
|
||||
This allows you to create a small sparse index that helps find data faster.
|
||||
|
||||
- Partitions can be used if the [partitioning key](/docs/en/engines/table-engines/mergetree-family/custom-partitioning-key.md) is specified.
|
||||
- Partitions can be used if the [partitioning key](/docs/en/engines/table-engines/mergetree-family/custom-partitioning-key.md) is specified.
|
||||
|
||||
ClickHouse supports certain operations with partitions that are more efficient than general operations on the same data with the same result. ClickHouse also automatically cuts off the partition data where the partitioning key is specified in the query.
|
||||
|
||||
- Data replication support.
|
||||
- Data replication support.
|
||||
|
||||
The family of `ReplicatedMergeTree` tables provides data replication. For more information, see [Data replication](/docs/en/engines/table-engines/mergetree-family/replication.md).
|
||||
|
||||
- Data sampling support.
|
||||
- Data sampling support.
|
||||
|
||||
If necessary, you can set the data sampling method in the table.
|
||||
|
||||
@ -207,10 +207,10 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
|
||||
|
||||
**MergeTree() Parameters**
|
||||
|
||||
- `date-column` — The name of a column of the [Date](/docs/en/sql-reference/data-types/date.md) type. ClickHouse automatically creates partitions by month based on this column. The partition names are in the `"YYYYMM"` format.
|
||||
- `sampling_expression` — An expression for sampling.
|
||||
- `(primary, key)` — Primary key. Type: [Tuple()](/docs/en/sql-reference/data-types/tuple.md)
|
||||
- `index_granularity` — The granularity of an index. The number of data rows between the “marks” of an index. The value 8192 is appropriate for most tasks.
|
||||
- `date-column` — The name of a column of the [Date](/docs/en/sql-reference/data-types/date.md) type. ClickHouse automatically creates partitions by month based on this column. The partition names are in the `"YYYYMM"` format.
|
||||
- `sampling_expression` — An expression for sampling.
|
||||
- `(primary, key)` — Primary key. Type: [Tuple()](/docs/en/sql-reference/data-types/tuple.md)
|
||||
- `index_granularity` — The granularity of an index. The number of data rows between the “marks” of an index. The value 8192 is appropriate for most tasks.
|
||||
|
||||
**Example**
|
||||
|
||||
@ -250,9 +250,9 @@ Take the `(CounterID, Date)` primary key as an example. In this case, the sortin
|
||||
|
||||
If the data query specifies:
|
||||
|
||||
- `CounterID in ('a', 'h')`, the server reads the data in the ranges of marks `[0, 3)` and `[6, 8)`.
|
||||
- `CounterID IN ('a', 'h') AND Date = 3`, the server reads the data in the ranges of marks `[1, 3)` and `[7, 8)`.
|
||||
- `Date = 3`, the server reads the data in the range of marks `[1, 10]`.
|
||||
- `CounterID in ('a', 'h')`, the server reads the data in the ranges of marks `[0, 3)` and `[6, 8)`.
|
||||
- `CounterID IN ('a', 'h') AND Date = 3`, the server reads the data in the ranges of marks `[1, 3)` and `[7, 8)`.
|
||||
- `Date = 3`, the server reads the data in the range of marks `[1, 10]`.
|
||||
|
||||
The examples above show that it is always more effective to use an index than a full scan.
|
||||
|
||||
@ -268,18 +268,18 @@ You can use `Nullable`-typed expressions in the `PRIMARY KEY` and `ORDER BY` cla
|
||||
|
||||
The number of columns in the primary key is not explicitly limited. Depending on the data structure, you can include more or fewer columns in the primary key. This may:
|
||||
|
||||
- Improve the performance of an index.
|
||||
- Improve the performance of an index.
|
||||
|
||||
If the primary key is `(a, b)`, then adding another column `c` will improve the performance if the following conditions are met:
|
||||
|
||||
- There are queries with a condition on column `c`.
|
||||
- Long data ranges (several times longer than the `index_granularity`) with identical values for `(a, b)` are common. In other words, when adding another column allows you to skip quite long data ranges.
|
||||
- There are queries with a condition on column `c`.
|
||||
- Long data ranges (several times longer than the `index_granularity`) with identical values for `(a, b)` are common. In other words, when adding another column allows you to skip quite long data ranges.
|
||||
|
||||
- Improve data compression.
|
||||
- Improve data compression.
|
||||
|
||||
ClickHouse sorts data by primary key, so the higher the consistency, the better the compression.
|
||||
|
||||
- Provide additional logic when merging data parts in the [CollapsingMergeTree](/docs/en/engines/table-engines/mergetree-family/collapsingmergetree.md/#table_engine-collapsingmergetree) and [SummingMergeTree](/docs/en/engines/table-engines/mergetree-family/summingmergetree.md) engines.
|
||||
- Provide additional logic when merging data parts in the [CollapsingMergeTree](/docs/en/engines/table-engines/mergetree-family/collapsingmergetree.md/#table_engine-collapsingmergetree) and [SummingMergeTree](/docs/en/engines/table-engines/mergetree-family/summingmergetree.md) engines.
|
||||
|
||||
In this case it makes sense to specify the *sorting key* that is different from the primary key.
|
||||
|
||||
@ -483,25 +483,25 @@ Indexes of type `set` can be utilized by all functions. The other index types ar
|
||||
|
||||
Functions with a constant argument that is less than ngram size can’t be used by `ngrambf_v1` for query optimization.
|
||||
|
||||
(*) For `hasTokenCaseInsensitve` and `hasTokenCaseInsensitive` to be effective, the `tokenbf_v1` index must be created on lowercased data, for example `INDEX idx (lower(str_col)) TYPE tokenbf_v1(512, 3, 0)`.
|
||||
(*) For `hasTokenCaseInsensitive` and `hasTokenCaseInsensitiveOrNull` to be effective, the `tokenbf_v1` index must be created on lowercased data, for example `INDEX idx (lower(str_col)) TYPE tokenbf_v1(512, 3, 0)`.
|
||||
|
||||
:::note
|
||||
Bloom filters can have false positive matches, so the `ngrambf_v1`, `tokenbf_v1`, and `bloom_filter` indexes can not be used for optimizing queries where the result of a function is expected to be false.
|
||||
|
||||
For example:
|
||||
|
||||
- Can be optimized:
|
||||
- `s LIKE '%test%'`
|
||||
- `NOT s NOT LIKE '%test%'`
|
||||
- `s = 1`
|
||||
- `NOT s != 1`
|
||||
- `startsWith(s, 'test')`
|
||||
- Can not be optimized:
|
||||
- `NOT s LIKE '%test%'`
|
||||
- `s NOT LIKE '%test%'`
|
||||
- `NOT s = 1`
|
||||
- `s != 1`
|
||||
- `NOT startsWith(s, 'test')`
|
||||
- Can be optimized:
|
||||
- `s LIKE '%test%'`
|
||||
- `NOT s NOT LIKE '%test%'`
|
||||
- `s = 1`
|
||||
- `NOT s != 1`
|
||||
- `startsWith(s, 'test')`
|
||||
- Can not be optimized:
|
||||
- `NOT s LIKE '%test%'`
|
||||
- `s NOT LIKE '%test%'`
|
||||
- `NOT s = 1`
|
||||
- `s != 1`
|
||||
- `NOT startsWith(s, 'test')`
|
||||
:::
|
||||
|
||||
|
||||
@ -614,11 +614,11 @@ TTL expr
|
||||
|
||||
Type of TTL rule may follow each TTL expression. It affects an action which is to be done once the expression is satisfied (reaches current time):
|
||||
|
||||
- `DELETE` - delete expired rows (default action);
|
||||
- `RECOMPRESS codec_name` - recompress data part with the `codec_name`;
|
||||
- `TO DISK 'aaa'` - move part to the disk `aaa`;
|
||||
- `TO VOLUME 'bbb'` - move part to the disk `bbb`;
|
||||
- `GROUP BY` - aggregate expired rows.
|
||||
- `DELETE` - delete expired rows (default action);
|
||||
- `RECOMPRESS codec_name` - recompress data part with the `codec_name`;
|
||||
- `TO DISK 'aaa'` - move part to the disk `aaa`;
|
||||
- `TO VOLUME 'bbb'` - move part to the disk `bbb`;
|
||||
- `GROUP BY` - aggregate expired rows.
|
||||
|
||||
`DELETE` action can be used together with `WHERE` clause to delete only some of the expired rows based on a filtering condition:
|
||||
``` sql
|
||||
@ -722,10 +722,10 @@ Data part is the minimum movable unit for `MergeTree`-engine tables. The data be
|
||||
|
||||
### Terms {#terms}
|
||||
|
||||
- Disk — Block device mounted to the filesystem.
|
||||
- Default disk — Disk that stores the path specified in the [path](/docs/en/operations/server-configuration-parameters/settings.md/#server_configuration_parameters-path) server setting.
|
||||
- Volume — Ordered set of equal disks (similar to [JBOD](https://en.wikipedia.org/wiki/Non-RAID_drive_architectures)).
|
||||
- Storage policy — Set of volumes and the rules for moving data between them.
|
||||
- Disk — Block device mounted to the filesystem.
|
||||
- Default disk — Disk that stores the path specified in the [path](/docs/en/operations/server-configuration-parameters/settings.md/#server_configuration_parameters-path) server setting.
|
||||
- Volume — Ordered set of equal disks (similar to [JBOD](https://en.wikipedia.org/wiki/Non-RAID_drive_architectures)).
|
||||
- Storage policy — Set of volumes and the rules for moving data between them.
|
||||
|
||||
The names given to the described entities can be found in the system tables, [system.storage_policies](/docs/en/operations/system-tables/storage_policies.md/#system_tables-storage_policies) and [system.disks](/docs/en/operations/system-tables/disks.md/#system_tables-disks). To apply one of the configured storage policies for a table, use the `storage_policy` setting of `MergeTree`-engine family tables.
|
||||
|
||||
@ -759,9 +759,9 @@ Configuration structure:
|
||||
|
||||
Tags:
|
||||
|
||||
- `<disk_name_N>` — Disk name. Names must be different for all disks.
|
||||
- `path` — path under which a server will store data (`data` and `shadow` folders), should be terminated with ‘/’.
|
||||
- `keep_free_space_bytes` — the amount of free disk space to be reserved.
|
||||
- `<disk_name_N>` — Disk name. Names must be different for all disks.
|
||||
- `path` — path under which a server will store data (`data` and `shadow` folders), should be terminated with ‘/’.
|
||||
- `keep_free_space_bytes` — the amount of free disk space to be reserved.
|
||||
|
||||
The order of the disk definition is not important.
|
||||
|
||||
@ -797,14 +797,14 @@ Storage policies configuration markup:
|
||||
|
||||
Tags:
|
||||
|
||||
- `policy_name_N` — Policy name. Policy names must be unique.
|
||||
- `volume_name_N` — Volume name. Volume names must be unique.
|
||||
- `disk` — a disk within a volume.
|
||||
- `max_data_part_size_bytes` — the maximum size of a part that can be stored on any of the volume’s disks. If the a size of a merged part estimated to be bigger than `max_data_part_size_bytes` then this part will be written to a next volume. Basically this feature allows to keep new/small parts on a hot (SSD) volume and move them to a cold (HDD) volume when they reach large size. Do not use this setting if your policy has only one volume.
|
||||
- `move_factor` — when the amount of available space gets lower than this factor, data automatically starts to move on the next volume if any (by default, 0.1). ClickHouse sorts existing parts by size from largest to smallest (in descending order) and selects parts with the total size that is sufficient to meet the `move_factor` condition. If the total size of all parts is insufficient, all parts will be moved.
|
||||
- `prefer_not_to_merge` — Disables merging of data parts on this volume. When this setting is enabled, merging data on this volume is not allowed. This allows controlling how ClickHouse works with slow disks.
|
||||
- `perform_ttl_move_on_insert` — Disables TTL move on data part INSERT. By default if we insert a data part that already expired by the TTL move rule it immediately goes to a volume/disk declared in move rule. This can significantly slowdown insert in case if destination volume/disk is slow (e.g. S3).
|
||||
- `load_balancing` - Policy for disk balancing, `round_robin` or `least_used`.
|
||||
- `policy_name_N` — Policy name. Policy names must be unique.
|
||||
- `volume_name_N` — Volume name. Volume names must be unique.
|
||||
- `disk` — a disk within a volume.
|
||||
- `max_data_part_size_bytes` — the maximum size of a part that can be stored on any of the volume’s disks. If the a size of a merged part estimated to be bigger than `max_data_part_size_bytes` then this part will be written to a next volume. Basically this feature allows to keep new/small parts on a hot (SSD) volume and move them to a cold (HDD) volume when they reach large size. Do not use this setting if your policy has only one volume.
|
||||
- `move_factor` — when the amount of available space gets lower than this factor, data automatically starts to move on the next volume if any (by default, 0.1). ClickHouse sorts existing parts by size from largest to smallest (in descending order) and selects parts with the total size that is sufficient to meet the `move_factor` condition. If the total size of all parts is insufficient, all parts will be moved.
|
||||
- `prefer_not_to_merge` — Disables merging of data parts on this volume. When this setting is enabled, merging data on this volume is not allowed. This allows controlling how ClickHouse works with slow disks.
|
||||
- `perform_ttl_move_on_insert` — Disables TTL move on data part INSERT. By default if we insert a data part that already expired by the TTL move rule it immediately goes to a volume/disk declared in move rule. This can significantly slowdown insert in case if destination volume/disk is slow (e.g. S3).
|
||||
- `load_balancing` - Policy for disk balancing, `round_robin` or `least_used`.
|
||||
|
||||
Cofiguration examples:
|
||||
|
||||
@ -880,10 +880,10 @@ The number of threads performing background moves of data parts can be changed b
|
||||
|
||||
In the case of `MergeTree` tables, data is getting to disk in different ways:
|
||||
|
||||
- As a result of an insert (`INSERT` query).
|
||||
- During background merges and [mutations](/docs/en/sql-reference/statements/alter/index.md#alter-mutations).
|
||||
- When downloading from another replica.
|
||||
- As a result of partition freezing [ALTER TABLE … FREEZE PARTITION](/docs/en/sql-reference/statements/alter/partition.md/#alter_freeze-partition).
|
||||
- As a result of an insert (`INSERT` query).
|
||||
- During background merges and [mutations](/docs/en/sql-reference/statements/alter/index.md#alter-mutations).
|
||||
- When downloading from another replica.
|
||||
- As a result of partition freezing [ALTER TABLE … FREEZE PARTITION](/docs/en/sql-reference/statements/alter/partition.md/#alter_freeze-partition).
|
||||
|
||||
In all these cases except for mutations and partition freezing, a part is stored on a volume and a disk according to the given storage policy:
|
||||
|
||||
@ -956,30 +956,30 @@ ClickHouse versions 22.3 through 22.7 use a different cache configuration, see [
|
||||
|
||||
Required parameters:
|
||||
|
||||
- `endpoint` — S3 endpoint URL in `path` or `virtual hosted` [styles](https://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html). Endpoint URL should contain a bucket and root path to store data.
|
||||
- `access_key_id` — S3 access key id.
|
||||
- `secret_access_key` — S3 secret access key.
|
||||
- `endpoint` — S3 endpoint URL in `path` or `virtual hosted` [styles](https://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html). Endpoint URL should contain a bucket and root path to store data.
|
||||
- `access_key_id` — S3 access key id.
|
||||
- `secret_access_key` — S3 secret access key.
|
||||
|
||||
Optional parameters:
|
||||
|
||||
- `region` — S3 region name.
|
||||
- `support_batch_delete` — This controls the check to see if batch deletes are supported. Set this to `false` when using Google Cloud Storage (GCS) as GCS does not support batch deletes and preventing the checks will prevent error messages in the logs.
|
||||
- `use_environment_credentials` — Reads AWS credentials from the Environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN if they exist. Default value is `false`.
|
||||
- `use_insecure_imds_request` — If set to `true`, S3 client will use insecure IMDS request while obtaining credentials from Amazon EC2 metadata. Default value is `false`.
|
||||
- `expiration_window_seconds` — Grace period for checking if expiration-based credentials have expired. Optional, default value is `120`.
|
||||
- `proxy` — Proxy configuration for S3 endpoint. Each `uri` element inside `proxy` block should contain a proxy URL.
|
||||
- `connect_timeout_ms` — Socket connect timeout in milliseconds. Default value is `10 seconds`.
|
||||
- `request_timeout_ms` — Request timeout in milliseconds. Default value is `5 seconds`.
|
||||
- `retry_attempts` — Number of retry attempts in case of failed request. Default value is `10`.
|
||||
- `single_read_retries` — Number of retry attempts in case of connection drop during read. Default value is `4`.
|
||||
- `min_bytes_for_seek` — Minimal number of bytes to use seek operation instead of sequential read. Default value is `1 Mb`.
|
||||
- `metadata_path` — Path on local FS to store metadata files for S3. Default value is `/var/lib/clickhouse/disks/<disk_name>/`.
|
||||
- `skip_access_check` — If true, disk access checks will not be performed on disk start-up. Default value is `false`.
|
||||
- `server_side_encryption_customer_key_base64` — If specified, required headers for accessing S3 objects with SSE-C encryption will be set.
|
||||
- `s3_max_put_rps` — Maximum PUT requests per second rate before throttling. Default value is `0` (unlimited).
|
||||
- `s3_max_put_burst` — Max number of requests that can be issued simultaneously before hitting request per second limit. By default (`0` value) equals to `s3_max_put_rps`.
|
||||
- `s3_max_get_rps` — Maximum GET requests per second rate before throttling. Default value is `0` (unlimited).
|
||||
- `s3_max_get_burst` — Max number of requests that can be issued simultaneously before hitting request per second limit. By default (`0` value) equals to `s3_max_get_rps`.
|
||||
- `region` — S3 region name.
|
||||
- `support_batch_delete` — This controls the check to see if batch deletes are supported. Set this to `false` when using Google Cloud Storage (GCS) as GCS does not support batch deletes and preventing the checks will prevent error messages in the logs.
|
||||
- `use_environment_credentials` — Reads AWS credentials from the Environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN if they exist. Default value is `false`.
|
||||
- `use_insecure_imds_request` — If set to `true`, S3 client will use insecure IMDS request while obtaining credentials from Amazon EC2 metadata. Default value is `false`.
|
||||
- `expiration_window_seconds` — Grace period for checking if expiration-based credentials have expired. Optional, default value is `120`.
|
||||
- `proxy` — Proxy configuration for S3 endpoint. Each `uri` element inside `proxy` block should contain a proxy URL.
|
||||
- `connect_timeout_ms` — Socket connect timeout in milliseconds. Default value is `10 seconds`.
|
||||
- `request_timeout_ms` — Request timeout in milliseconds. Default value is `5 seconds`.
|
||||
- `retry_attempts` — Number of retry attempts in case of failed request. Default value is `10`.
|
||||
- `single_read_retries` — Number of retry attempts in case of connection drop during read. Default value is `4`.
|
||||
- `min_bytes_for_seek` — Minimal number of bytes to use seek operation instead of sequential read. Default value is `1 Mb`.
|
||||
- `metadata_path` — Path on local FS to store metadata files for S3. Default value is `/var/lib/clickhouse/disks/<disk_name>/`.
|
||||
- `skip_access_check` — If true, disk access checks will not be performed on disk start-up. Default value is `false`.
|
||||
- `server_side_encryption_customer_key_base64` — If specified, required headers for accessing S3 objects with SSE-C encryption will be set.
|
||||
- `s3_max_put_rps` — Maximum PUT requests per second rate before throttling. Default value is `0` (unlimited).
|
||||
- `s3_max_put_burst` — Max number of requests that can be issued simultaneously before hitting request per second limit. By default (`0` value) equals to `s3_max_put_rps`.
|
||||
- `s3_max_get_rps` — Maximum GET requests per second rate before throttling. Default value is `0` (unlimited).
|
||||
- `s3_max_get_burst` — Max number of requests that can be issued simultaneously before hitting request per second limit. By default (`0` value) equals to `s3_max_get_rps`.
|
||||
|
||||
### Configuring the cache
|
||||
|
||||
@ -994,12 +994,12 @@ This is the cache configuration from above:
|
||||
```
|
||||
|
||||
These parameters define the cache layer:
|
||||
- `type` — If a disk is of type `cache` it caches mark and index files in memory.
|
||||
- `disk` — The name of the disk that will be cached.
|
||||
- `type` — If a disk is of type `cache` it caches mark and index files in memory.
|
||||
- `disk` — The name of the disk that will be cached.
|
||||
|
||||
Cache parameters:
|
||||
- `path` — The path where metadata for the cache is stored.
|
||||
- `max_size` — The size (amount of memory) that the cache can grow to.
|
||||
- `path` — The path where metadata for the cache is stored.
|
||||
- `max_size` — The size (amount of memory) that the cache can grow to.
|
||||
|
||||
:::tip
|
||||
There are several other cache parameters that you can use to tune your storage, see [using local cache](/docs/en/operations/storing-data.md/#using-local-cache) for the details.
|
||||
@ -1100,9 +1100,9 @@ Examples of working configurations can be found in integration tests directory (
|
||||
|
||||
## Virtual Columns {#virtual-columns}
|
||||
|
||||
- `_part` — Name of a part.
|
||||
- `_part_index` — Sequential index of the part in the query result.
|
||||
- `_partition_id` — Name of a partition.
|
||||
- `_part_uuid` — Unique part identifier (if enabled MergeTree setting `assign_part_uuids`).
|
||||
- `_partition_value` — Values (a tuple) of a `partition by` expression.
|
||||
- `_sample_factor` — Sample factor (from the query).
|
||||
- `_part` — Name of a part.
|
||||
- `_part_index` — Sequential index of the part in the query result.
|
||||
- `_partition_id` — Name of a partition.
|
||||
- `_part_uuid` — Unique part identifier (if enabled MergeTree setting `assign_part_uuids`).
|
||||
- `_partition_value` — Values (a tuple) of a `partition by` expression.
|
||||
- `_sample_factor` — Sample factor (from the query).
|
||||
|
@ -20,12 +20,12 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
|
||||
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
|
||||
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
|
||||
...
|
||||
) ENGINE = ReplacingMergeTree([ver])
|
||||
) ENGINE = ReplacingMergeTree([ver [, is_deleted]])
|
||||
[PARTITION BY expr]
|
||||
[ORDER BY expr]
|
||||
[PRIMARY KEY expr]
|
||||
[SAMPLE BY expr]
|
||||
[SETTINGS name=value, ...]
|
||||
[SETTINGS name=value, clean_deleted_rows=value, ...]
|
||||
```
|
||||
|
||||
For a description of request parameters, see [statement description](../../../sql-reference/statements/create/table.md).
|
||||
@ -88,6 +88,18 @@ SELECT * FROM mySecondReplacingMT FINAL;
|
||||
└─────┴─────────┴─────────────────────┘
|
||||
```
|
||||
|
||||
### is_deleted
|
||||
|
||||
`is_deleted` — Name of the column with the type of row: `1` is a “deleted“ row, `0` is a “state“ row.
|
||||
|
||||
Column data type — `Int8`.
|
||||
|
||||
Can only be enabled when `ver` is used.
|
||||
The row is deleted when use the `OPTIMIZE ... FINAL CLEANUP`, or `OPTIMIZE ... FINAL` if the engine settings `clean_deleted_rows` has been set to `Always`.
|
||||
No matter the operation on the data, the version must be increased. If two inserted rows have the same version number, the last inserted one is the one kept.
|
||||
|
||||
|
||||
|
||||
## Query clauses
|
||||
|
||||
When creating a `ReplacingMergeTree` table the same [clauses](../../../engines/table-engines/mergetree-family/mergetree.md) are required, as when creating a `MergeTree` table.
|
||||
@ -111,6 +123,6 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
|
||||
|
||||
All of the parameters excepting `ver` have the same meaning as in `MergeTree`.
|
||||
|
||||
- `ver` - column with the version. Optional parameter. For a description, see the text above.
|
||||
- `ver` - column with the version. Optional parameter. For a description, see the text above.
|
||||
|
||||
</details>
|
||||
|
@ -26,13 +26,13 @@ ENGINE = ReplicatedReplacingMergeTree
|
||||
|
||||
Replication is only supported for tables in the MergeTree family:
|
||||
|
||||
- ReplicatedMergeTree
|
||||
- ReplicatedSummingMergeTree
|
||||
- ReplicatedReplacingMergeTree
|
||||
- ReplicatedAggregatingMergeTree
|
||||
- ReplicatedCollapsingMergeTree
|
||||
- ReplicatedVersionedCollapsingMergeTree
|
||||
- ReplicatedGraphiteMergeTree
|
||||
- ReplicatedMergeTree
|
||||
- ReplicatedSummingMergeTree
|
||||
- ReplicatedReplacingMergeTree
|
||||
- ReplicatedAggregatingMergeTree
|
||||
- ReplicatedCollapsingMergeTree
|
||||
- ReplicatedVersionedCollapsingMergeTree
|
||||
- ReplicatedGraphiteMergeTree
|
||||
|
||||
Replication works at the level of an individual table, not the entire server. A server can store both replicated and non-replicated tables at the same time.
|
||||
|
||||
@ -42,9 +42,9 @@ Compressed data for `INSERT` and `ALTER` queries is replicated (for more informa
|
||||
|
||||
`CREATE`, `DROP`, `ATTACH`, `DETACH` and `RENAME` queries are executed on a single server and are not replicated:
|
||||
|
||||
- The `CREATE TABLE` query creates a new replicatable table on the server where the query is run. If this table already exists on other servers, it adds a new replica.
|
||||
- The `DROP TABLE` query deletes the replica located on the server where the query is run.
|
||||
- The `RENAME` query renames the table on one of the replicas. In other words, replicated tables can have different names on different replicas.
|
||||
- The `CREATE TABLE` query creates a new replicatable table on the server where the query is run. If this table already exists on other servers, it adds a new replica.
|
||||
- The `DROP TABLE` query deletes the replica located on the server where the query is run.
|
||||
- The `RENAME` query renames the table on one of the replicas. In other words, replicated tables can have different names on different replicas.
|
||||
|
||||
ClickHouse uses [ClickHouse Keeper](/docs/en/guides/sre/keeper/index.md) for storing replicas meta information. It is possible to use ZooKeeper version 3.4.5 or newer, but ClickHouse Keeper is recommended.
|
||||
|
||||
@ -316,8 +316,8 @@ Create a MergeTree table with a different name. Move all the data from the direc
|
||||
|
||||
If you want to get rid of a `ReplicatedMergeTree` table without launching the server:
|
||||
|
||||
- Delete the corresponding `.sql` file in the metadata directory (`/var/lib/clickhouse/metadata/`).
|
||||
- Delete the corresponding path in ClickHouse Keeper (`/path_to_table/replica_name`).
|
||||
- Delete the corresponding `.sql` file in the metadata directory (`/var/lib/clickhouse/metadata/`).
|
||||
- Delete the corresponding path in ClickHouse Keeper (`/path_to_table/replica_name`).
|
||||
|
||||
After this, you can launch the server, create a `MergeTree` table, move the data to its directory, and then restart the server.
|
||||
|
||||
@ -327,8 +327,8 @@ If the data in ClickHouse Keeper was lost or damaged, you can save data by movin
|
||||
|
||||
**See Also**
|
||||
|
||||
- [background_schedule_pool_size](/docs/en/operations/server-configuration-parameters/settings.md/#background_schedule_pool_size)
|
||||
- [background_fetches_pool_size](/docs/en/operations/server-configuration-parameters/settings.md/#background_fetches_pool_size)
|
||||
- [execute_merges_on_single_replica_time_threshold](/docs/en/operations/settings/settings.md/#execute-merges-on-single-replica-time-threshold)
|
||||
- [max_replicated_fetches_network_bandwidth](/docs/en/operations/settings/merge-tree-settings.md/#max_replicated_fetches_network_bandwidth)
|
||||
- [max_replicated_sends_network_bandwidth](/docs/en/operations/settings/merge-tree-settings.md/#max_replicated_sends_network_bandwidth)
|
||||
- [background_schedule_pool_size](/docs/en/operations/server-configuration-parameters/settings.md/#background_schedule_pool_size)
|
||||
- [background_fetches_pool_size](/docs/en/operations/server-configuration-parameters/settings.md/#background_fetches_pool_size)
|
||||
- [execute_merges_on_single_replica_time_threshold](/docs/en/operations/settings/settings.md/#execute-merges-on-single-replica-time-threshold)
|
||||
- [max_replicated_fetches_network_bandwidth](/docs/en/operations/settings/merge-tree-settings.md/#max_replicated_fetches_network_bandwidth)
|
||||
- [max_replicated_sends_network_bandwidth](/docs/en/operations/settings/merge-tree-settings.md/#max_replicated_sends_network_bandwidth)
|
||||
|
@ -59,7 +59,7 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
|
||||
|
||||
All of the parameters excepting `columns` have the same meaning as in `MergeTree`.
|
||||
|
||||
- `columns` — tuple with names of columns values of which will be summarized. Optional parameter. For a description, see the text above.
|
||||
- `columns` — tuple with names of columns values of which will be summarized. Optional parameter. For a description, see the text above.
|
||||
|
||||
</details>
|
||||
|
||||
@ -122,8 +122,8 @@ Table can have nested data structures that are processed in a special way.
|
||||
|
||||
If the name of a nested table ends with `Map` and it contains at least two columns that meet the following criteria:
|
||||
|
||||
- the first column is numeric `(*Int*, Date, DateTime)` or a string `(String, FixedString)`, let’s call it `key`,
|
||||
- the other columns are arithmetic `(*Int*, Float32/64)`, let’s call it `(values...)`,
|
||||
- the first column is numeric `(*Int*, Date, DateTime)` or a string `(String, FixedString)`, let’s call it `key`,
|
||||
- the other columns are arithmetic `(*Int*, Float32/64)`, let’s call it `(values...)`,
|
||||
|
||||
then this nested table is interpreted as a mapping of `key => (values...)`, and when merging its rows, the elements of two data sets are merged by `key` with a summation of the corresponding `(values...)`.
|
||||
|
||||
|
@ -8,8 +8,8 @@ sidebar_label: VersionedCollapsingMergeTree
|
||||
|
||||
This engine:
|
||||
|
||||
- Allows quick writing of object states that are continually changing.
|
||||
- Deletes old object states in the background. This significantly reduces the volume of storage.
|
||||
- Allows quick writing of object states that are continually changing.
|
||||
- Deletes old object states in the background. This significantly reduces the volume of storage.
|
||||
|
||||
See the section [Collapsing](#table_engines_versionedcollapsingmergetree) for details.
|
||||
|
||||
@ -73,11 +73,11 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
|
||||
|
||||
All of the parameters except `sign` and `version` have the same meaning as in `MergeTree`.
|
||||
|
||||
- `sign` — Name of the column with the type of row: `1` is a “state” row, `-1` is a “cancel” row.
|
||||
- `sign` — Name of the column with the type of row: `1` is a “state” row, `-1` is a “cancel” row.
|
||||
|
||||
Column Data Type — `Int8`.
|
||||
|
||||
- `version` — Name of the column with the version of the object state.
|
||||
- `version` — Name of the column with the version of the object state.
|
||||
|
||||
The column data type should be `UInt*`.
|
||||
|
||||
|
@ -97,4 +97,4 @@ select * from products limit 1;
|
||||
|
||||
**See Also**
|
||||
|
||||
- [Dictionary function](../../../sql-reference/table-functions/dictionary.md#dictionary-function)
|
||||
- [Dictionary function](../../../sql-reference/table-functions/dictionary.md#dictionary-function)
|
||||
|
@ -229,8 +229,8 @@ A simple remainder from the division is a limited solution for sharding and isn
|
||||
|
||||
You should be concerned about the sharding scheme in the following cases:
|
||||
|
||||
- Queries are used that require joining data (`IN` or `JOIN`) by a specific key. If data is sharded by this key, you can use local `IN` or `JOIN` instead of `GLOBAL IN` or `GLOBAL JOIN`, which is much more efficient.
|
||||
- A large number of servers is used (hundreds or more) with a large number of small queries, for example, queries for data of individual clients (e.g. websites, advertisers, or partners). In order for the small queries to not affect the entire cluster, it makes sense to locate data for a single client on a single shard. Alternatively, you can set up bi-level sharding: divide the entire cluster into “layers”, where a layer may consist of multiple shards. Data for a single client is located on a single layer, but shards can be added to a layer as necessary, and data is randomly distributed within them. `Distributed` tables are created for each layer, and a single shared distributed table is created for global queries.
|
||||
- Queries are used that require joining data (`IN` or `JOIN`) by a specific key. If data is sharded by this key, you can use local `IN` or `JOIN` instead of `GLOBAL IN` or `GLOBAL JOIN`, which is much more efficient.
|
||||
- A large number of servers is used (hundreds or more) with a large number of small queries, for example, queries for data of individual clients (e.g. websites, advertisers, or partners). In order for the small queries to not affect the entire cluster, it makes sense to locate data for a single client on a single shard. Alternatively, you can set up bi-level sharding: divide the entire cluster into “layers”, where a layer may consist of multiple shards. Data for a single client is located on a single layer, but shards can be added to a layer as necessary, and data is randomly distributed within them. `Distributed` tables are created for each layer, and a single shared distributed table is created for global queries.
|
||||
|
||||
Data is written asynchronously. When inserted in the table, the data block is just written to the local file system. The data is sent to the remote servers in the background as soon as possible. The periodicity for sending data is managed by the [distributed_directory_monitor_sleep_time_ms](../../../operations/settings/settings.md#distributed_directory_monitor_sleep_time_ms) and [distributed_directory_monitor_max_sleep_time_ms](../../../operations/settings/settings.md#distributed_directory_monitor_max_sleep_time_ms) settings. The `Distributed` engine sends each file with inserted data separately, but you can enable batch sending of files with the [distributed_directory_monitor_batch_inserts](../../../operations/settings/settings.md#distributed_directory_monitor_batch_inserts) setting. This setting improves cluster performance by better utilizing local server and network resources. You should check whether data is sent successfully by checking the list of files (data waiting to be sent) in the table directory: `/var/lib/clickhouse/data/database/table/`. The number of threads performing background tasks can be set by [background_distributed_schedule_pool_size](../../../operations/settings/settings.md#background_distributed_schedule_pool_size) setting.
|
||||
|
||||
@ -256,6 +256,6 @@ Since [remote](../../../sql-reference/table-functions/remote.md) and [cluster](.
|
||||
|
||||
**See Also**
|
||||
|
||||
- [Virtual columns](../../../engines/table-engines/index.md#table_engines-virtual_columns) description
|
||||
- [background_distributed_schedule_pool_size](../../../operations/settings/settings.md#background_distributed_schedule_pool_size) setting
|
||||
- [shardNum()](../../../sql-reference/functions/other-functions.md#shard-num) and [shardCount()](../../../sql-reference/functions/other-functions.md#shard-count) functions
|
||||
- [Virtual columns](../../../engines/table-engines/index.md#table_engines-virtual_columns) description
|
||||
- [background_distributed_schedule_pool_size](../../../operations/settings/settings.md#background_distributed_schedule_pool_size) setting
|
||||
- [shardNum()](../../../sql-reference/functions/other-functions.md#shard-num) and [shardCount()](../../../sql-reference/functions/other-functions.md#shard-count) functions
|
||||
|
@ -10,9 +10,9 @@ The File table engine keeps the data in a file in one of the supported [file for
|
||||
|
||||
Usage scenarios:
|
||||
|
||||
- Data export from ClickHouse to file.
|
||||
- Convert data from one format to another.
|
||||
- Updating data in ClickHouse via editing a file on a disk.
|
||||
- Data export from ClickHouse to file.
|
||||
- Convert data from one format to another.
|
||||
- Updating data in ClickHouse via editing a file on a disk.
|
||||
|
||||
## Usage in ClickHouse Server {#usage-in-clickhouse-server}
|
||||
|
||||
@ -78,14 +78,14 @@ $ echo -e "1,2\n3,4" | clickhouse-local -q "CREATE TABLE table (a Int64, b Int64
|
||||
|
||||
## Details of Implementation {#details-of-implementation}
|
||||
|
||||
- Multiple `SELECT` queries can be performed concurrently, but `INSERT` queries will wait each other.
|
||||
- Supported creating new file by `INSERT` query.
|
||||
- If file exists, `INSERT` would append new values in it.
|
||||
- Not supported:
|
||||
- `ALTER`
|
||||
- `SELECT ... SAMPLE`
|
||||
- Indices
|
||||
- Replication
|
||||
- Multiple `SELECT` queries can be performed concurrently, but `INSERT` queries will wait each other.
|
||||
- Supported creating new file by `INSERT` query.
|
||||
- If file exists, `INSERT` would append new values in it.
|
||||
- Not supported:
|
||||
- `ALTER`
|
||||
- `SELECT ... SAMPLE`
|
||||
- Indices
|
||||
- Replication
|
||||
|
||||
## PARTITION BY
|
||||
|
||||
|
@ -9,8 +9,8 @@ The GenerateRandom table engine produces random data for given table schema.
|
||||
|
||||
Usage examples:
|
||||
|
||||
- Use in test to populate reproducible large table.
|
||||
- Generate random input for fuzzing tests.
|
||||
- Use in test to populate reproducible large table.
|
||||
- Generate random input for fuzzing tests.
|
||||
|
||||
## Usage in ClickHouse Server {#usage-in-clickhouse-server}
|
||||
|
||||
@ -49,9 +49,9 @@ SELECT * FROM generate_engine_table LIMIT 3
|
||||
|
||||
## Details of Implementation {#details-of-implementation}
|
||||
|
||||
- Not supported:
|
||||
- `ALTER`
|
||||
- `SELECT ... SAMPLE`
|
||||
- `INSERT`
|
||||
- Indices
|
||||
- Replication
|
||||
- Not supported:
|
||||
- `ALTER`
|
||||
- `SELECT ... SAMPLE`
|
||||
- `INSERT`
|
||||
- Indices
|
||||
- Replication
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user