Add double-conversion to third_party (#447)

This commit is contained in:
Gautham 2022-06-26 16:11:55 +05:30 committed by GitHub
parent 2f515ac5e3
commit b1de862e16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 329324 additions and 0 deletions

View file

@ -0,0 +1,135 @@
// Copyright 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 "third_party/double-conversion/test/cctest.h"
#include "libc/isystem/stdio.h"
#include "libc/isystem/stdlib.h"
#include "libc/isystem/string.h"
CcTest* CcTest::last_ = NULL;
CcTest::CcTest(TestFunction* callback, const char* test_file,
const char* test_name, const char* test_dependency,
bool test_is_enabled)
: callback_(callback), name_(test_name), dependency_(test_dependency),
prev_(last_) {
// Find the base name of this test (const_cast required on Windows).
char *basename = strrchr(const_cast<char *>(test_file), '/');
if (!basename) {
basename = strrchr(const_cast<char *>(test_file), '\\');
}
if (!basename) {
basename = strdup(test_file);
} else {
basename = strdup(basename + 1);
}
// Drop the extension, if there is one.
char *extension = strrchr(basename, '.');
if (extension) *extension = 0;
// Install this test in the list of tests
file_ = basename;
enabled_ = test_is_enabled;
prev_ = last_;
last_ = this;
}
static void PrintTestList(CcTest* current) {
if (current == NULL) return;
PrintTestList(current->prev());
if (current->dependency() != NULL) {
printf("%s/%s<%s\n",
current->file(), current->name(), current->dependency());
} else {
printf("%s/%s<\n", current->file(), current->name());
}
}
int main(int argc, char* argv[]) {
int tests_run = 0;
bool print_run_count = true;
if (argc == 1) {
// Just run all the tests.
CcTest* test = CcTest::last();
while (test != NULL) {
if (test->enabled()) {
test->Run();
tests_run++;
}
test = test->prev();
}
}
for (int i = 1; i < argc; i++) {
char* arg = argv[i];
if (strcmp(arg, "--list") == 0) {
PrintTestList(CcTest::last());
print_run_count = false;
} else {
char* arg_copy = strdup(arg);
char* testname = strchr(arg_copy, '/');
if (testname) {
// Split the string in two by nulling the slash and then run
// exact matches.
*testname = 0;
char* file = arg_copy;
char* name = testname + 1;
CcTest* test = CcTest::last();
while (test != NULL) {
if (test->enabled()
&& strcmp(test->file(), file) == 0
&& strcmp(test->name(), name) == 0) {
test->Run();
tests_run++;
}
test = test->prev();
}
} else {
// Run all tests with the specified file or test name.
char* file_or_name = arg_copy;
CcTest* test = CcTest::last();
while (test != NULL) {
if (test->enabled()
&& (strcmp(test->file(), file_or_name) == 0
|| strcmp(test->name(), file_or_name) == 0)) {
test->Run();
tests_run++;
}
test = test->prev();
}
}
free(arg_copy);
}
}
if (print_run_count && tests_run != 1)
printf("Ran %i tests.\n", tests_run);
return 0;
}

View file

@ -0,0 +1,144 @@
// Copyright 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.
#ifndef CCTEST_H_
#define CCTEST_H_
#include "libc/isystem/stdio.h"
#include "libc/isystem/string.h"
#include "third_party/double-conversion/utils.h"
#ifndef TEST
#define TEST(Name) \
static void Test##Name(); \
CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, true); \
static void Test##Name()
#endif
#ifndef DEPENDENT_TEST
#define DEPENDENT_TEST(Name, Dep) \
static void Test##Name(); \
CcTest register_test_##Name(Test##Name, __FILE__, #Name, #Dep, true); \
static void Test##Name()
#endif
#ifndef DISABLED_TEST
#define DISABLED_TEST(Name) \
static void Test##Name(); \
CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, false); \
static void Test##Name()
#endif
#define CHECK(condition) CheckHelper(__FILE__, __LINE__, #condition, condition)
#define CHECK_GE(a, b) CHECK((a) >= (b))
static inline void CheckHelper(const char* file,
int line,
const char* source,
bool condition) {
if (!condition) {
printf("%s:%d:\n CHECK(%s) failed\n", file, line, source);
abort();
}
}
#define CHECK_EQ(a, b) CheckEqualsHelper(__FILE__, __LINE__, #a, a, #b, b)
static inline void CheckEqualsHelper(const char* file, int line,
const char* expected_source,
const char* expected,
const char* value_source,
const char* value) {
if ((expected == NULL && value != NULL) ||
(expected != NULL && value == NULL)) {
abort();
}
if ((expected != NULL && value != NULL && strcmp(expected, value) != 0)) {
printf("%s:%d:\n CHECK_EQ(%s, %s) failed\n"
"# Expected: %s\n"
"# Found: %s\n",
file, line, expected_source, value_source, expected, value);
abort();
}
}
static inline void CheckEqualsHelper(const char* file, int line,
const char* expected_source,
int expected,
const char* value_source,
int value) {
if (expected != value) {
printf("%s:%d:\n CHECK_EQ(%s, %s) failed\n"
"# Expected: %d\n"
"# Found: %d\n",
file, line, expected_source, value_source, expected, value);
abort();
}
}
static inline void CheckEqualsHelper(const char* file, int line,
const char* expected_source,
double expected,
const char* value_source,
double value) {
// If expected and value are NaNs then expected != value.
if (expected != value && (expected == expected || value == value)) {
printf("%s:%d:\n CHECK_EQ(%s, %s) failed\n"
"# Expected: %.30e\n"
"# Found: %.30e\n",
file, line, expected_source, value_source, expected, value);
abort();
}
}
class CcTest {
public:
typedef void (TestFunction)();
CcTest(TestFunction* callback, const char* file, const char* name,
const char* dependency, bool enabled);
void Run() { callback_(); }
static int test_count();
static CcTest* last() { return last_; }
CcTest* prev() { return prev_; }
const char* file() const { return file_; }
const char* name() const { return name_; }
const char* dependency() const { return dependency_; }
bool enabled() const { return enabled_; }
private:
TestFunction* callback_;
const char* file_;
const char* name_;
const char* dependency_;
bool enabled_;
static CcTest* last_;
CcTest* prev_;
};
#endif // ifndef CCTEST_H_

View file

@ -0,0 +1,314 @@
// 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.
#ifndef V8_CHECKS_H_
#define V8_CHECKS_H_
#include "libc/isystem/string.h"
#include "third_party/double-conversion/test/flags.h"
extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);
void API_Fatal(const char* location, const char* format, ...);
// The FATAL, DOUBLE_CONVERSION_UNREACHABLE and DOUBLE_CONVERSION_UNIMPLEMENTED macros are useful during
// development, but they should not be relied on in the final product.
#ifdef DEBUG
#define FATAL(msg) \
V8_Fatal(__FILE__, __LINE__, "%s", (msg))
#define DOUBLE_CONVERSION_UNIMPLEMENTED() \
V8_Fatal(__FILE__, __LINE__, "unimplemented code")
#define DOUBLE_CONVERSION_UNREACHABLE() \
V8_Fatal(__FILE__, __LINE__, "unreachable code")
#else
#define FATAL(msg) \
V8_Fatal("", 0, "%s", (msg))
#define DOUBLE_CONVERSION_UNIMPLEMENTED() \
V8_Fatal("", 0, "unimplemented code")
#define DOUBLE_CONVERSION_UNREACHABLE() ((void) 0)
#endif
// Used by the CHECK macro -- should not be called directly.
static inline void CheckHelper(const char* file,
int line,
const char* source,
bool condition) {
if (!condition)
V8_Fatal(file, line, "CHECK(%s) failed", source);
}
// The CHECK macro checks that the given condition is true; if not, it
// prints a message to stderr and aborts.
#define CHECK(condition) CheckHelper(__FILE__, __LINE__, #condition, condition)
// Helper function used by the CHECK_EQ function when given int
// arguments. Should not be called directly.
static inline void CheckEqualsHelper(const char* file, int line,
const char* expected_source, int expected,
const char* value_source, int value) {
if (expected != value) {
V8_Fatal(file, line,
"CHECK_EQ(%s, %s) failed\n# Expected: %i\n# Found: %i",
expected_source, value_source, expected, value);
}
}
// Helper function used by the CHECK_EQ function when given int64_t
// arguments. Should not be called directly.
static inline void CheckEqualsHelper(const char* file, int line,
const char* expected_source,
int64_t expected,
const char* value_source,
int64_t value) {
if (expected != value) {
// Print int64_t values in hex, as two int32s,
// to avoid platform-dependencies.
V8_Fatal(file, line,
"CHECK_EQ(%s, %s) failed\n#"
" Expected: 0x%08x%08x\n# Found: 0x%08x%08x",
expected_source, value_source,
static_cast<uint32_t>(expected >> 32),
static_cast<uint32_t>(expected),
static_cast<uint32_t>(value >> 32),
static_cast<uint32_t>(value));
}
}
// Helper function used by the CHECK_NE function when given int
// arguments. Should not be called directly.
static inline void CheckNonEqualsHelper(const char* file,
int line,
const char* unexpected_source,
int unexpected,
const char* value_source,
int value) {
if (unexpected == value) {
V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n# Value: %i",
unexpected_source, value_source, value);
}
}
// Helper function used by the CHECK function when given string
// arguments. Should not be called directly.
static inline void CheckEqualsHelper(const char* file,
int line,
const char* expected_source,
const char* expected,
const char* value_source,
const char* value) {
if ((expected == NULL && value != NULL) ||
(expected != NULL && value == NULL) ||
(expected != NULL && value != NULL && strcmp(expected, value) != 0)) {
V8_Fatal(file, line,
"CHECK_EQ(%s, %s) failed\n# Expected: %s\n# Found: %s",
expected_source, value_source, expected, value);
}
}
static inline void CheckNonEqualsHelper(const char* file,
int line,
const char* expected_source,
const char* expected,
const char* value_source,
const char* value) {
if (expected == value ||
(expected != NULL && value != NULL && strcmp(expected, value) == 0)) {
V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n# Value: %s",
expected_source, value_source, value);
}
}
// Helper function used by the CHECK function when given pointer
// arguments. Should not be called directly.
static inline void CheckEqualsHelper(const char* file,
int line,
const char* expected_source,
const void* expected,
const char* value_source,
const void* value) {
if (expected != value) {
V8_Fatal(file, line,
"CHECK_EQ(%s, %s) failed\n# Expected: %p\n# Found: %p",
expected_source, value_source,
expected, value);
}
}
static inline void CheckNonEqualsHelper(const char* file,
int line,
const char* expected_source,
const void* expected,
const char* value_source,
const void* value) {
if (expected == value) {
V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n# Value: %p",
expected_source, value_source, value);
}
}
// Helper function used by the CHECK function when given floating
// point arguments. Should not be called directly.
static inline void CheckEqualsHelper(const char* file,
int line,
const char* expected_source,
double expected,
const char* value_source,
double value) {
// Force values to 64 bit memory to truncate 80 bit precision on IA32.
volatile double* exp = new double[1];
*exp = expected;
volatile double* val = new double[1];
*val = value;
if (*exp != *val) {
V8_Fatal(file, line,
"CHECK_EQ(%s, %s) failed\n# Expected: %f\n# Found: %f",
expected_source, value_source, *exp, *val);
}
delete[] exp;
delete[] val;
}
static inline void CheckNonEqualsHelper(const char* file,
int line,
const char* expected_source,
double expected,
const char* value_source,
double value) {
// Force values to 64 bit memory to truncate 80 bit precision on IA32.
volatile double* exp = new double[1];
*exp = expected;
volatile double* val = new double[1];
*val = value;
if (*exp == *val) {
V8_Fatal(file, line,
"CHECK_NE(%s, %s) failed\n# Value: %f",
expected_source, value_source, *val);
}
delete[] exp;
delete[] val;
}
namespace v8 {
class Value;
template <class T> class Handle;
}
void CheckNonEqualsHelper(const char* file,
int line,
const char* unexpected_source,
v8::Handle<v8::Value> unexpected,
const char* value_source,
v8::Handle<v8::Value> value);
void CheckEqualsHelper(const char* file,
int line,
const char* expected_source,
v8::Handle<v8::Value> expected,
const char* value_source,
v8::Handle<v8::Value> value);
#define CHECK_EQ(expected, value) CheckEqualsHelper(__FILE__, __LINE__, \
#expected, expected, #value, value)
#define CHECK_NE(unexpected, value) CheckNonEqualsHelper(__FILE__, __LINE__, \
#unexpected, unexpected, #value, value)
#define CHECK_GT(a, b) CHECK((a) > (b))
#define CHECK_GE(a, b) CHECK((a) >= (b))
// This is inspired by the static assertion facility in boost. This
// is pretty magical. If it causes you trouble on a platform you may
// find a fix in the boost code.
template <bool> class StaticAssertion;
template <> class StaticAssertion<true> { };
// This macro joins two tokens. If one of the tokens is a macro the
// helper call causes it to be resolved before joining.
#define SEMI_STATIC_JOIN(a, b) SEMI_STATIC_JOIN_HELPER(a, b)
#define SEMI_STATIC_JOIN_HELPER(a, b) a##b
// Causes an error during compilation of the condition is not
// statically known to be true. It is formulated as a typedef so that
// it can be used wherever a typedef can be used. Beware that this
// actually causes each use to introduce a new defined type with a
// name depending on the source line.
template <int> class StaticAssertionHelper { };
#define STATIC_CHECK(test) \
typedef \
StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>(test)>)> \
SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)
// The DOUBLE_CONVERSION_ASSERT macro is equivalent to CHECK except that it only
// generates code in debug builds.
#ifdef DEBUG
#define DOUBLE_CONVERSION_ASSERT_RESULT(expr) CHECK(expr)
#define DOUBLE_CONVERSION_ASSERT(condition) CHECK(condition)
#define DOUBLE_CONVERSION_ASSERT_EQ(v1, v2) CHECK_EQ(v1, v2)
#define DOUBLE_CONVERSION_ASSERT_NE(v1, v2) CHECK_NE(v1, v2)
#define DOUBLE_CONVERSION_ASSERT_GE(v1, v2) CHECK_GE(v1, v2)
#define SLOW_DOUBLE_CONVERSION_ASSERT(condition) if (FLAG_enable_slow_asserts) CHECK(condition)
#else
#define DOUBLE_CONVERSION_ASSERT_RESULT(expr) (expr)
#define DOUBLE_CONVERSION_ASSERT(condition) ((void) 0)
#define DOUBLE_CONVERSION_ASSERT_EQ(v1, v2) ((void) 0)
#define DOUBLE_CONVERSION_ASSERT_NE(v1, v2) ((void) 0)
#define DOUBLE_CONVERSION_ASSERT_GE(v1, v2) ((void) 0)
#define SLOW_DOUBLE_CONVERSION_ASSERT(condition) ((void) 0)
#endif
// Static asserts has no impact on runtime performance, so they can be
// safely enabled in release mode. Moreover, the ((void) 0) expression
// obeys different syntax rules than typedef's, e.g. it can't appear
// inside class declaration, this leads to inconsistency between debug
// and release compilation modes behaviour.
#define STATIC_DOUBLE_CONVERSION_ASSERT(test) STATIC_CHECK(test)
#define DOUBLE_CONVERSION_ASSERT_TAG_ALIGNED(address) \
DOUBLE_CONVERSION_ASSERT((reinterpret_cast<intptr_t>(address) & kHeapObjectTagMask) == 0)
#define DOUBLE_CONVERSION_ASSERT_SIZE_TAG_ALIGNED(size) DOUBLE_CONVERSION_ASSERT((size & kHeapObjectTagMask) == 0)
#define DOUBLE_CONVERSION_ASSERT_NOT_NULL(p) DOUBLE_CONVERSION_ASSERT_NE(NULL, p)
#endif // V8_CHECKS_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,46 @@
// 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.
#ifndef GAY_FIXED_H_
#define GAY_FIXED_H_
namespace double_conversion {
struct PrecomputedFixed {
double v;
int number_digits;
const char* representation;
int decimal_point;
};
// Returns precomputed values of dtoa. The strings have been generated using
// Gay's dtoa in mode "fixed".
Vector<const PrecomputedFixed> PrecomputedFixedRepresentations();
} // namespace double_conversion
#endif // GAY_FIXED_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,46 @@
// 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.
#ifndef GAY_PRECISION_H_
#define GAY_PRECISION_H_
namespace double_conversion {
struct PrecomputedPrecision {
double v;
int number_digits;
const char* representation;
int decimal_point;
};
// Returns precomputed values of dtoa. The strings have been generated using
// Gay's dtoa in mode "precision".
Vector<const PrecomputedPrecision> PrecomputedPrecisionRepresentations();
} // namespace double_conversion
#endif // GAY_PRECISION_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,44 @@
// Copyright 2011, the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GAY_SHORTEST_SINGLE_H_
#define GAY_SHORTEST_SINGLE_H_
namespace double_conversion {
struct PrecomputedShortestSingle {
float v;
const char* representation;
int decimal_point;
};
Vector<const PrecomputedShortestSingle>
PrecomputedShortestSingleRepresentations();
} // namespace double_conversion
#endif // GAY_SHORTEST_SINGLE_H_

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,43 @@
// 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.
#ifndef GAY_SHORTEST_H_
#define GAY_SHORTEST_H_
namespace double_conversion {
struct PrecomputedShortest {
double v;
const char* representation;
int decimal_point;
};
Vector<const PrecomputedShortest> PrecomputedShortestRepresentations();
} // namespace double_conversion
#endif // GAY_SHORTEST_H_

View file

@ -0,0 +1,400 @@
// 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 "libc/isystem/stdlib.h"
#include "third_party/double-conversion/bignum-dtoa.h"
#include "third_party/double-conversion/test/cctest.h"
#include "third_party/double-conversion/test/gay-fixed.h"
#include "third_party/double-conversion/test/gay-precision.h"
#include "third_party/double-conversion/test/gay-shortest.h"
#include "third_party/double-conversion/test/gay-shortest-single.h"
#include "third_party/double-conversion/ieee.h"
#include "third_party/double-conversion/utils.h"
using namespace double_conversion;
// Removes trailing '0' digits.
// Can return the empty string if all digits are 0.
static void TrimRepresentation(Vector<char> representation) {
int len = strlen(representation.start());
int i;
for (i = len - 1; i >= 0; --i) {
if (representation[i] != '0') break;
}
representation[i + 1] = '\0';
}
static const int kBufferSize = 100;
TEST(BignumDtoaVariousDoubles) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
int length;
int point;
BignumDtoa(1.0, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
BignumDtoa(1.0, BIGNUM_DTOA_FIXED, 3, buffer, &length, &point);
CHECK_GE(3, length - point);
TrimRepresentation(buffer);
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
BignumDtoa(1.0, BIGNUM_DTOA_PRECISION, 3, buffer, &length, &point);
CHECK_GE(3, length);
TrimRepresentation(buffer);
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
BignumDtoa(1.5, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
CHECK_EQ("15", buffer.start());
CHECK_EQ(1, point);
BignumDtoa(1.5, BIGNUM_DTOA_FIXED, 10, buffer, &length, &point);
CHECK_GE(10, length - point);
TrimRepresentation(buffer);
CHECK_EQ("15", buffer.start());
CHECK_EQ(1, point);
BignumDtoa(1.5, BIGNUM_DTOA_PRECISION, 10, buffer, &length, &point);
CHECK_GE(10, length);
TrimRepresentation(buffer);
CHECK_EQ("15", buffer.start());
CHECK_EQ(1, point);
double min_double = 5e-324;
BignumDtoa(min_double, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
CHECK_EQ("5", buffer.start());
CHECK_EQ(-323, point);
BignumDtoa(min_double, BIGNUM_DTOA_FIXED, 5, buffer, &length, &point);
CHECK_GE(5, length - point);
TrimRepresentation(buffer);
CHECK_EQ("", buffer.start());
BignumDtoa(min_double, BIGNUM_DTOA_PRECISION, 5, buffer, &length, &point);
CHECK_GE(5, length);
TrimRepresentation(buffer);
CHECK_EQ("49407", buffer.start());
CHECK_EQ(-323, point);
double max_double = 1.7976931348623157e308;
BignumDtoa(max_double, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
CHECK_EQ("17976931348623157", buffer.start());
CHECK_EQ(309, point);
BignumDtoa(max_double, BIGNUM_DTOA_PRECISION, 7, buffer, &length, &point);
CHECK_GE(7, length);
TrimRepresentation(buffer);
CHECK_EQ("1797693", buffer.start());
CHECK_EQ(309, point);
BignumDtoa(4294967272.0, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
CHECK_EQ("4294967272", buffer.start());
CHECK_EQ(10, point);
BignumDtoa(4294967272.0, BIGNUM_DTOA_FIXED, 5, buffer, &length, &point);
CHECK_EQ("429496727200000", buffer.start());
CHECK_EQ(10, point);
BignumDtoa(4294967272.0, BIGNUM_DTOA_PRECISION, 14, buffer, &length, &point);
CHECK_GE(14, length);
TrimRepresentation(buffer);
CHECK_EQ("4294967272", buffer.start());
CHECK_EQ(10, point);
BignumDtoa(4.1855804968213567e298, BIGNUM_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK_EQ("4185580496821357", buffer.start());
CHECK_EQ(299, point);
BignumDtoa(4.1855804968213567e298, BIGNUM_DTOA_PRECISION, 20,
buffer, &length, &point);
CHECK_GE(20, length);
TrimRepresentation(buffer);
CHECK_EQ("41855804968213567225", buffer.start());
CHECK_EQ(299, point);
BignumDtoa(5.5626846462680035e-309, BIGNUM_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK_EQ("5562684646268003", buffer.start());
CHECK_EQ(-308, point);
BignumDtoa(5.5626846462680035e-309, BIGNUM_DTOA_PRECISION, 1,
buffer, &length, &point);
CHECK_GE(1, length);
TrimRepresentation(buffer);
CHECK_EQ("6", buffer.start());
CHECK_EQ(-308, point);
BignumDtoa(2147483648.0, BIGNUM_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK_EQ("2147483648", buffer.start());
CHECK_EQ(10, point);
BignumDtoa(2147483648.0, BIGNUM_DTOA_FIXED, 2,
buffer, &length, &point);
CHECK_GE(2, length - point);
TrimRepresentation(buffer);
CHECK_EQ("2147483648", buffer.start());
CHECK_EQ(10, point);
BignumDtoa(2147483648.0, BIGNUM_DTOA_PRECISION, 5,
buffer, &length, &point);
CHECK_GE(5, length);
TrimRepresentation(buffer);
CHECK_EQ("21475", buffer.start());
CHECK_EQ(10, point);
BignumDtoa(3.5844466002796428e+298, BIGNUM_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK_EQ("35844466002796428", buffer.start());
CHECK_EQ(299, point);
BignumDtoa(3.5844466002796428e+298, BIGNUM_DTOA_PRECISION, 10,
buffer, &length, &point);
CHECK_GE(10, length);
TrimRepresentation(buffer);
CHECK_EQ("35844466", buffer.start());
CHECK_EQ(299, point);
BignumDtoa(1e-23, BIGNUM_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK_EQ("1", buffer.start());
CHECK_EQ(-22, point);
uint64_t smallest_normal64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000);
double v = Double(smallest_normal64).value();
BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
CHECK_EQ("22250738585072014", buffer.start());
CHECK_EQ(-307, point);
BignumDtoa(v, BIGNUM_DTOA_PRECISION, 20, buffer, &length, &point);
CHECK_GE(20, length);
TrimRepresentation(buffer);
CHECK_EQ("22250738585072013831", buffer.start());
CHECK_EQ(-307, point);
uint64_t largest_denormal64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
v = Double(largest_denormal64).value();
BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
CHECK_EQ("2225073858507201", buffer.start());
CHECK_EQ(-307, point);
BignumDtoa(v, BIGNUM_DTOA_PRECISION, 20, buffer, &length, &point);
CHECK_GE(20, length);
TrimRepresentation(buffer);
CHECK_EQ("2225073858507200889", buffer.start());
CHECK_EQ(-307, point);
BignumDtoa(4128420500802942e-24, BIGNUM_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK_EQ("4128420500802942", buffer.start());
CHECK_EQ(-8, point);
v = 3.9292015898194142585311918e-10;
BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
CHECK_EQ("39292015898194143", buffer.start());
v = 4194304.0;
BignumDtoa(v, BIGNUM_DTOA_FIXED, 5, buffer, &length, &point);
CHECK_GE(5, length - point);
TrimRepresentation(buffer);
CHECK_EQ("4194304", buffer.start());
v = 3.3161339052167390562200598e-237;
BignumDtoa(v, BIGNUM_DTOA_PRECISION, 19, buffer, &length, &point);
CHECK_GE(19, length);
TrimRepresentation(buffer);
CHECK_EQ("3316133905216739056", buffer.start());
CHECK_EQ(-236, point);
v = 7.9885183916008099497815232e+191;
BignumDtoa(v, BIGNUM_DTOA_PRECISION, 4, buffer, &length, &point);
CHECK_GE(4, length);
TrimRepresentation(buffer);
CHECK_EQ("7989", buffer.start());
CHECK_EQ(192, point);
v = 1.0000000000000012800000000e+17;
BignumDtoa(v, BIGNUM_DTOA_FIXED, 1, buffer, &length, &point);
CHECK_GE(1, length - point);
TrimRepresentation(buffer);
CHECK_EQ("100000000000000128", buffer.start());
CHECK_EQ(18, point);
}
TEST(BignumDtoaShortestVariousFloats) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
int length;
int point;
float min_float = 1e-45f;
BignumDtoa(min_float, BIGNUM_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK_EQ("1", buffer.start());
CHECK_EQ(-44, point);
float max_float = 3.4028234e38f;
BignumDtoa(max_float, BIGNUM_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK_EQ("34028235", buffer.start());
CHECK_EQ(39, point);
BignumDtoa(4294967272.0f, BIGNUM_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK_EQ("42949673", buffer.start());
CHECK_EQ(10, point);
BignumDtoa(3.32306998946228968226e+35f, BIGNUM_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK_EQ("332307", buffer.start());
CHECK_EQ(36, point);
BignumDtoa(1.2341e-41f, BIGNUM_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK_EQ("12341", buffer.start());
CHECK_EQ(-40, point);
BignumDtoa(3.3554432e7, BIGNUM_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK_EQ("33554432", buffer.start());
CHECK_EQ(8, point);
BignumDtoa(3.26494756798464e14f, BIGNUM_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK_EQ("32649476", buffer.start());
CHECK_EQ(15, point);
BignumDtoa(3.91132223637771935344e37f, BIGNUM_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK_EQ("39113222", buffer.start());
CHECK_EQ(38, point);
uint32_t smallest_normal32 = 0x00800000;
double v = Single(smallest_normal32).value();
BignumDtoa(v, BIGNUM_DTOA_SHORTEST_SINGLE, 0, buffer, &length, &point);
CHECK_EQ("11754944", buffer.start());
CHECK_EQ(-37, point);
uint32_t largest_denormal32 = 0x007FFFFF;
v = Single(largest_denormal32).value();
BignumDtoa(v, BIGNUM_DTOA_SHORTEST_SINGLE, 0, buffer, &length, &point);
CHECK_EQ("11754942", buffer.start());
CHECK_EQ(-37, point);
}
TEST(BignumDtoaGayShortest) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
int length;
int point;
Vector<const PrecomputedShortest> precomputed =
PrecomputedShortestRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedShortest current_test = precomputed[i];
double v = current_test.v;
BignumDtoa(v, BIGNUM_DTOA_SHORTEST, 0, buffer, &length, &point);
CHECK_EQ(current_test.decimal_point, point);
CHECK_EQ(current_test.representation, buffer.start());
}
}
TEST(BignumDtoaGayShortestSingle) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
int length;
int point;
Vector<const PrecomputedShortestSingle> precomputed =
PrecomputedShortestSingleRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedShortestSingle current_test = precomputed[i];
float v = current_test.v;
BignumDtoa(v, BIGNUM_DTOA_SHORTEST_SINGLE, 0, buffer, &length, &point);
CHECK_EQ(current_test.decimal_point, point);
CHECK_EQ(current_test.representation, buffer.start());
}
}
TEST(BignumDtoaGayFixed) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
int length;
int point;
Vector<const PrecomputedFixed> precomputed =
PrecomputedFixedRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedFixed current_test = precomputed[i];
double v = current_test.v;
int number_digits = current_test.number_digits;
BignumDtoa(v, BIGNUM_DTOA_FIXED, number_digits, buffer, &length, &point);
CHECK_EQ(current_test.decimal_point, point);
CHECK_GE(number_digits, length - point);
TrimRepresentation(buffer);
CHECK_EQ(current_test.representation, buffer.start());
}
}
TEST(BignumDtoaGayPrecision) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
int length;
int point;
Vector<const PrecomputedPrecision> precomputed =
PrecomputedPrecisionRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedPrecision current_test = precomputed[i];
double v = current_test.v;
int number_digits = current_test.number_digits;
BignumDtoa(v, BIGNUM_DTOA_PRECISION, number_digits,
buffer, &length, &point);
CHECK_EQ(current_test.decimal_point, point);
CHECK_GE(number_digits, length);
TrimRepresentation(buffer);
CHECK_EQ(current_test.representation, buffer.start());
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,90 @@
// 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 "libc/isystem/stdlib.h"
#include "third_party/double-conversion/test/cctest.h"
#include "third_party/double-conversion/diy-fp.h"
#include "third_party/double-conversion/utils.h"
using namespace double_conversion;
TEST(Subtract) {
DiyFp diy_fp1 = DiyFp(3, 0);
DiyFp diy_fp2 = DiyFp(1, 0);
DiyFp diff = DiyFp::Minus(diy_fp1, diy_fp2);
CHECK(2 == diff.f()); // NOLINT
CHECK_EQ(0, diff.e());
diy_fp1.Subtract(diy_fp2);
CHECK(2 == diy_fp1.f()); // NOLINT
CHECK_EQ(0, diy_fp1.e());
}
TEST(Multiply) {
DiyFp diy_fp1 = DiyFp(3, 0);
DiyFp diy_fp2 = DiyFp(2, 0);
DiyFp product = DiyFp::Times(diy_fp1, diy_fp2);
CHECK(0 == product.f()); // NOLINT
CHECK_EQ(64, product.e());
diy_fp1.Multiply(diy_fp2);
CHECK(0 == diy_fp1.f()); // NOLINT
CHECK_EQ(64, diy_fp1.e());
diy_fp1 = DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000000), 11);
diy_fp2 = DiyFp(2, 13);
product = DiyFp::Times(diy_fp1, diy_fp2);
CHECK(1 == product.f()); // NOLINT
CHECK_EQ(11 + 13 + 64, product.e());
// Test rounding.
diy_fp1 = DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000001), 11);
diy_fp2 = DiyFp(1, 13);
product = DiyFp::Times(diy_fp1, diy_fp2);
CHECK(1 == product.f()); // NOLINT
CHECK_EQ(11 + 13 + 64, product.e());
diy_fp1 = DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0x7fffffff, ffffffff), 11);
diy_fp2 = DiyFp(1, 13);
product = DiyFp::Times(diy_fp1, diy_fp2);
CHECK(0 == product.f()); // NOLINT
CHECK_EQ(11 + 13 + 64, product.e());
// Halfway cases are allowed to round either way. So don't check for it.
// Big numbers.
diy_fp1 = DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF), 11);
diy_fp2 = DiyFp(DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF), 13);
// 128bit result: 0xfffffffffffffffe0000000000000001
product = DiyFp::Times(diy_fp1, diy_fp2);
CHECK(DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, FFFFFFFe) == product.f());
CHECK_EQ(11 + 13 + 64, product.e());
}

View file

@ -0,0 +1,507 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "libc/isystem/stdlib.h"
#include "third_party/double-conversion/double-conversion.h"
#include "third_party/double-conversion/test/cctest.h"
#include "third_party/double-conversion/test/gay-fixed.h"
#include "third_party/double-conversion/test/gay-precision.h"
#include "third_party/double-conversion/test/gay-shortest.h"
#include "third_party/double-conversion/test/gay-shortest-single.h"
#include "third_party/double-conversion/ieee.h"
using namespace double_conversion;
enum DtoaMode {
SHORTEST,
SHORTEST_SINGLE,
FIXED,
PRECISION
};
static void DoubleToAscii(double v, DtoaMode test_mode, int requested_digits,
Vector<char> buffer, bool* sign, int* length,
int* point) {
DoubleToStringConverter::DtoaMode mode = DoubleToStringConverter::SHORTEST;
switch (test_mode) {
case SHORTEST: mode = DoubleToStringConverter::SHORTEST; break;
case SHORTEST_SINGLE:
mode = DoubleToStringConverter::SHORTEST_SINGLE;
break;
case FIXED: mode = DoubleToStringConverter::FIXED; break;
case PRECISION: mode = DoubleToStringConverter::PRECISION; break;
}
DoubleToStringConverter::DoubleToAscii(v, mode, requested_digits,
buffer.start(), buffer.length(),
sign, length, point);
}
// Removes trailing '0' digits.
static void TrimRepresentation(Vector<char> representation) {
int len = strlen(representation.start());
int i;
for (i = len - 1; i >= 0; --i) {
if (representation[i] != '0') break;
}
representation[i + 1] = '\0';
}
static const int kBufferSize = 100;
TEST(DtoaVariousDoubles) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
int length;
int point;
bool sign;
DoubleToAscii(0.0, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK_EQ("0", buffer.start());
CHECK_EQ(1, point);
DoubleToAscii(0.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK_EQ("0", buffer.start());
CHECK_EQ(1, point);
DoubleToAscii(0.0, FIXED, 2, buffer, &sign, &length, &point);
CHECK_EQ(1, length);
CHECK_EQ("0", buffer.start());
CHECK_EQ(1, point);
DoubleToAscii(0.0, PRECISION, 3, buffer, &sign, &length, &point);
CHECK_EQ(1, length);
CHECK_EQ("0", buffer.start());
CHECK_EQ(1, point);
DoubleToAscii(1.0, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
DoubleToAscii(1.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
DoubleToAscii(1.0, FIXED, 3, buffer, &sign, &length, &point);
CHECK_GE(3, length - point);
TrimRepresentation(buffer);
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
DoubleToAscii(1.0, PRECISION, 3, buffer, &sign, &length, &point);
CHECK_GE(3, length);
TrimRepresentation(buffer);
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
DoubleToAscii(1.5, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK_EQ("15", buffer.start());
CHECK_EQ(1, point);
DoubleToAscii(1.5f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK_EQ("15", buffer.start());
CHECK_EQ(1, point);
DoubleToAscii(1.5, FIXED, 10, buffer, &sign, &length, &point);
CHECK_GE(10, length - point);
TrimRepresentation(buffer);
CHECK_EQ("15", buffer.start());
CHECK_EQ(1, point);
DoubleToAscii(1.5, PRECISION, 10, buffer, &sign, &length, &point);
CHECK_GE(10, length);
TrimRepresentation(buffer);
CHECK_EQ("15", buffer.start());
CHECK_EQ(1, point);
double min_double = 5e-324;
DoubleToAscii(min_double, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK_EQ("5", buffer.start());
CHECK_EQ(-323, point);
float min_float = 1e-45f;
DoubleToAscii(min_float, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK_EQ("1", buffer.start());
CHECK_EQ(-44, point);
DoubleToAscii(min_double, FIXED, 5, buffer, &sign, &length, &point);
CHECK_GE(5, length - point);
TrimRepresentation(buffer);
CHECK_EQ("", buffer.start());
CHECK_GE(-5, point);
DoubleToAscii(min_double, PRECISION, 5, buffer, &sign, &length, &point);
CHECK_GE(5, length);
TrimRepresentation(buffer);
CHECK_EQ("49407", buffer.start());
CHECK_EQ(-323, point);
double max_double = 1.7976931348623157e308;
DoubleToAscii(max_double, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK_EQ("17976931348623157", buffer.start());
CHECK_EQ(309, point);
float max_float = 3.4028234e38f;
DoubleToAscii(max_float, SHORTEST_SINGLE, 0,
buffer, &sign, &length, &point);
CHECK_EQ("34028235", buffer.start());
CHECK_EQ(39, point);
DoubleToAscii(max_double, PRECISION, 7, buffer, &sign, &length, &point);
CHECK_GE(7, length);
TrimRepresentation(buffer);
CHECK_EQ("1797693", buffer.start());
CHECK_EQ(309, point);
DoubleToAscii(4294967272.0, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK_EQ("4294967272", buffer.start());
CHECK_EQ(10, point);
DoubleToAscii(4294967272.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK_EQ("42949673", buffer.start());
CHECK_EQ(10, point);
DoubleToAscii(4294967272.0, FIXED, 5, buffer, &sign, &length, &point);
CHECK_GE(5, length - point);
TrimRepresentation(buffer);
CHECK_EQ("4294967272", buffer.start());
CHECK_EQ(10, point);
DoubleToAscii(4294967272.0, PRECISION, 14,
buffer, &sign, &length, &point);
CHECK_GE(14, length);
TrimRepresentation(buffer);
CHECK_EQ("4294967272", buffer.start());
CHECK_EQ(10, point);
DoubleToAscii(4.1855804968213567e298, SHORTEST, 0,
buffer, &sign, &length, &point);
CHECK_EQ("4185580496821357", buffer.start());
CHECK_EQ(299, point);
DoubleToAscii(4.1855804968213567e298, PRECISION, 20,
buffer, &sign, &length, &point);
CHECK_GE(20, length);
TrimRepresentation(buffer);
CHECK_EQ("41855804968213567225", buffer.start());
CHECK_EQ(299, point);
DoubleToAscii(5.5626846462680035e-309, SHORTEST, 0,
buffer, &sign, &length, &point);
CHECK_EQ("5562684646268003", buffer.start());
CHECK_EQ(-308, point);
DoubleToAscii(5.5626846462680035e-309, PRECISION, 1,
buffer, &sign, &length, &point);
CHECK_GE(1, length);
TrimRepresentation(buffer);
CHECK_EQ("6", buffer.start());
CHECK_EQ(-308, point);
DoubleToAscii(-2147483648.0, SHORTEST, 0,
buffer, &sign, &length, &point);
CHECK_EQ(1, sign);
CHECK_EQ("2147483648", buffer.start());
CHECK_EQ(10, point);
DoubleToAscii(-2147483648.0, SHORTEST_SINGLE, 0,
buffer, &sign, &length, &point);
CHECK_EQ(1, sign);
CHECK_EQ("21474836", buffer.start());
CHECK_EQ(10, point);
DoubleToAscii(-2147483648.0, FIXED, 2, buffer, &sign, &length, &point);
CHECK_GE(2, length - point);
TrimRepresentation(buffer);
CHECK_EQ(1, sign);
CHECK_EQ("2147483648", buffer.start());
CHECK_EQ(10, point);
DoubleToAscii(-2147483648.0, PRECISION, 5,
buffer, &sign, &length, &point);
CHECK_GE(5, length);
TrimRepresentation(buffer);
CHECK_EQ(1, sign);
CHECK_EQ("21475", buffer.start());
CHECK_EQ(10, point);
DoubleToAscii(-3.5844466002796428e+298, SHORTEST, 0,
buffer, &sign, &length, &point);
CHECK_EQ(1, sign);
CHECK_EQ("35844466002796428", buffer.start());
CHECK_EQ(299, point);
DoubleToAscii(-3.5844466002796428e+298, PRECISION, 10,
buffer, &sign, &length, &point);
CHECK_EQ(1, sign);
CHECK_GE(10, length);
TrimRepresentation(buffer);
CHECK_EQ("35844466", buffer.start());
CHECK_EQ(299, point);
uint64_t smallest_normal64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000);
double v = Double(smallest_normal64).value();
DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK_EQ("22250738585072014", buffer.start());
CHECK_EQ(-307, point);
uint32_t smallest_normal32 = 0x00800000;
float f = Single(smallest_normal32).value();
DoubleToAscii(f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK_EQ("11754944", buffer.start());
CHECK_EQ(-37, point);
DoubleToAscii(v, PRECISION, 20, buffer, &sign, &length, &point);
CHECK_GE(20, length);
TrimRepresentation(buffer);
CHECK_EQ("22250738585072013831", buffer.start());
CHECK_EQ(-307, point);
uint64_t largest_denormal64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
v = Double(largest_denormal64).value();
DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK_EQ("2225073858507201", buffer.start());
CHECK_EQ(-307, point);
uint32_t largest_denormal32 = 0x007FFFFF;
f = Single(largest_denormal32).value();
DoubleToAscii(f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK_EQ("11754942", buffer.start());
CHECK_EQ(-37, point);
DoubleToAscii(v, PRECISION, 20, buffer, &sign, &length, &point);
CHECK_GE(20, length);
TrimRepresentation(buffer);
CHECK_EQ("2225073858507200889", buffer.start());
CHECK_EQ(-307, point);
DoubleToAscii(4128420500802942e-24, SHORTEST, 0,
buffer, &sign, &length, &point);
CHECK_EQ(0, sign);
CHECK_EQ("4128420500802942", buffer.start());
CHECK_EQ(-8, point);
v = -3.9292015898194142585311918e-10;
DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK_EQ("39292015898194143", buffer.start());
f = -3.9292015898194142585311918e-10f;
DoubleToAscii(f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK_EQ("39292017", buffer.start());
v = 4194304.0;
DoubleToAscii(v, FIXED, 5, buffer, &sign, &length, &point);
CHECK_GE(5, length - point);
TrimRepresentation(buffer);
CHECK_EQ("4194304", buffer.start());
v = 3.3161339052167390562200598e-237;
DoubleToAscii(v, PRECISION, 19, buffer, &sign, &length, &point);
CHECK_GE(19, length);
TrimRepresentation(buffer);
CHECK_EQ("3316133905216739056", buffer.start());
CHECK_EQ(-236, point);
}
TEST(DtoaSign) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
bool sign;
int length;
int point;
DoubleToAscii(0.0, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK(!sign);
DoubleToAscii(-0.0, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK(sign);
DoubleToAscii(1.0, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK(!sign);
DoubleToAscii(-1.0, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK(sign);
DoubleToAscii(0.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK(!sign);
DoubleToAscii(-0.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK(sign);
DoubleToAscii(1.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK(!sign);
DoubleToAscii(-1.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK(sign);
DoubleToAscii(0.0, PRECISION, 1, buffer, &sign, &length, &point);
CHECK(!sign);
DoubleToAscii(-0.0, PRECISION, 1, buffer, &sign, &length, &point);
CHECK(sign);
DoubleToAscii(1.0, PRECISION, 1, buffer, &sign, &length, &point);
CHECK(!sign);
DoubleToAscii(-1.0, PRECISION, 1, buffer, &sign, &length, &point);
CHECK(sign);
DoubleToAscii(0.0, FIXED, 1, buffer, &sign, &length, &point);
CHECK(!sign);
DoubleToAscii(-0.0, FIXED, 1, buffer, &sign, &length, &point);
CHECK(sign);
DoubleToAscii(1.0, FIXED, 1, buffer, &sign, &length, &point);
CHECK(!sign);
DoubleToAscii(-1.0, FIXED, 1, buffer, &sign, &length, &point);
CHECK(sign);
}
TEST(DtoaCorners) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
bool sign;
int length;
int point;
DoubleToAscii(0.0, PRECISION, 0, buffer, &sign, &length, &point);
CHECK_EQ(0, length);
CHECK_EQ("", buffer.start());
CHECK(!sign);
DoubleToAscii(1.0, PRECISION, 0, buffer, &sign, &length, &point);
CHECK_EQ(0, length);
CHECK_EQ("", buffer.start());
CHECK(!sign);
DoubleToAscii(0.0, FIXED, 0, buffer, &sign, &length, &point);
CHECK_EQ(1, length);
CHECK_EQ("0", buffer.start());
CHECK(!sign);
DoubleToAscii(1.0, FIXED, 0, buffer, &sign, &length, &point);
CHECK_EQ(1, length);
CHECK_EQ("1", buffer.start());
CHECK(!sign);
}
TEST(DtoaGayShortest) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
bool sign;
int length;
int point;
Vector<const PrecomputedShortest> precomputed =
PrecomputedShortestRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedShortest current_test = precomputed[i];
double v = current_test.v;
DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);
CHECK(!sign); // All precomputed numbers are positive.
CHECK_EQ(current_test.decimal_point, point);
CHECK_EQ(current_test.representation, buffer.start());
}
}
TEST(DtoaGayShortestSingle) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
bool sign;
int length;
int point;
Vector<const PrecomputedShortestSingle> precomputed =
PrecomputedShortestSingleRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedShortestSingle current_test = precomputed[i];
float v = current_test.v;
DoubleToAscii(v, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
CHECK(!sign); // All precomputed numbers are positive.
CHECK_EQ(current_test.decimal_point, point);
CHECK_EQ(current_test.representation, buffer.start());
}
}
TEST(DtoaGayFixed) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
bool sign;
int length;
int point;
Vector<const PrecomputedFixed> precomputed =
PrecomputedFixedRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedFixed current_test = precomputed[i];
double v = current_test.v;
int number_digits = current_test.number_digits;
DoubleToAscii(v, FIXED, number_digits, buffer, &sign, &length, &point);
CHECK(!sign); // All precomputed numbers are positive.
CHECK_EQ(current_test.decimal_point, point);
CHECK_GE(number_digits, length - point);
TrimRepresentation(buffer);
CHECK_EQ(current_test.representation, buffer.start());
}
}
TEST(DtoaGayPrecision) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
bool sign;
int length;
int point;
Vector<const PrecomputedPrecision> precomputed =
PrecomputedPrecisionRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedPrecision current_test = precomputed[i];
double v = current_test.v;
int number_digits = current_test.number_digits;
DoubleToAscii(v, PRECISION, number_digits,
buffer, &sign, &length, &point);
CHECK(!sign); // All precomputed numbers are positive.
CHECK_EQ(current_test.decimal_point, point);
CHECK_GE(number_digits, length);
TrimRepresentation(buffer);
CHECK_EQ(current_test.representation, buffer.start());
}
}

View file

@ -0,0 +1,397 @@
// 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 "libc/isystem/stdlib.h"
#include "third_party/double-conversion/test/cctest.h"
#include "third_party/double-conversion/diy-fp.h"
#include "third_party/double-conversion/fast-dtoa.h"
#include "third_party/double-conversion/test/gay-precision.h"
#include "third_party/double-conversion/test/gay-shortest.h"
#include "third_party/double-conversion/test/gay-shortest-single.h"
#include "third_party/double-conversion/ieee.h"
#include "third_party/double-conversion/utils.h"
using namespace double_conversion;
static const int kBufferSize = 100;
// Removes trailing '0' digits.
static void TrimRepresentation(Vector<char> representation) {
int len = strlen(representation.start());
int i;
for (i = len - 1; i >= 0; --i) {
if (representation[i] != '0') break;
}
representation[i + 1] = '\0';
}
TEST(FastDtoaShortestVariousDoubles) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
int length;
int point;
bool status;
double min_double = 5e-324;
status = FastDtoa(min_double, FAST_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("5", buffer.start());
CHECK_EQ(-323, point);
double max_double = 1.7976931348623157e308;
status = FastDtoa(max_double, FAST_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("17976931348623157", buffer.start());
CHECK_EQ(309, point);
status = FastDtoa(4294967272.0, FAST_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("4294967272", buffer.start());
CHECK_EQ(10, point);
status = FastDtoa(4.1855804968213567e298, FAST_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("4185580496821357", buffer.start());
CHECK_EQ(299, point);
status = FastDtoa(5.5626846462680035e-309, FAST_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("5562684646268003", buffer.start());
CHECK_EQ(-308, point);
status = FastDtoa(2147483648.0, FAST_DTOA_SHORTEST, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("2147483648", buffer.start());
CHECK_EQ(10, point);
status = FastDtoa(3.5844466002796428e+298, FAST_DTOA_SHORTEST, 0,
buffer, &length, &point);
if (status) { // Not all FastDtoa variants manage to compute this number.
CHECK_EQ("35844466002796428", buffer.start());
CHECK_EQ(299, point);
}
uint64_t smallest_normal64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000);
double v = Double(smallest_normal64).value();
status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);
if (status) {
CHECK_EQ("22250738585072014", buffer.start());
CHECK_EQ(-307, point);
}
uint64_t largest_denormal64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
v = Double(largest_denormal64).value();
status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);
if (status) {
CHECK_EQ("2225073858507201", buffer.start());
CHECK_EQ(-307, point);
}
}
TEST(FastDtoaShortestVariousFloats) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
int length;
int point;
bool status;
float min_float = 1e-45f;
status = FastDtoa(min_float, FAST_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("1", buffer.start());
CHECK_EQ(-44, point);
float max_float = 3.4028234e38f;
status = FastDtoa(max_float, FAST_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("34028235", buffer.start());
CHECK_EQ(39, point);
status = FastDtoa(4294967272.0f, FAST_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("42949673", buffer.start());
CHECK_EQ(10, point);
status = FastDtoa(3.32306998946228968226e+35f, FAST_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("332307", buffer.start());
CHECK_EQ(36, point);
status = FastDtoa(1.2341e-41f, FAST_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("12341", buffer.start());
CHECK_EQ(-40, point);
status = FastDtoa(3.3554432e7, FAST_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("33554432", buffer.start());
CHECK_EQ(8, point);
status = FastDtoa(3.26494756798464e14f, FAST_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("32649476", buffer.start());
CHECK_EQ(15, point);
status = FastDtoa(3.91132223637771935344e37f, FAST_DTOA_SHORTEST_SINGLE, 0,
buffer, &length, &point);
if (status) { // Not all FastDtoa variants manage to compute this number.
CHECK_EQ("39113222", buffer.start());
CHECK_EQ(38, point);
}
uint32_t smallest_normal32 = 0x00800000;
float v = Single(smallest_normal32).value();
status = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0, buffer, &length, &point);
if (status) {
CHECK_EQ("11754944", buffer.start());
CHECK_EQ(-37, point);
}
uint32_t largest_denormal32 = 0x007FFFFF;
v = Single(largest_denormal32).value();
status = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0, buffer, &length, &point);
CHECK(status);
CHECK_EQ("11754942", buffer.start());
CHECK_EQ(-37, point);
}
TEST(FastDtoaPrecisionVariousDoubles) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
int length;
int point;
bool status;
status = FastDtoa(1.0, FAST_DTOA_PRECISION, 3, buffer, &length, &point);
CHECK(status);
CHECK(3 >= length);
TrimRepresentation(buffer);
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
status = FastDtoa(1.5, FAST_DTOA_PRECISION, 10, buffer, &length, &point);
if (status) {
CHECK(10 >= length);
TrimRepresentation(buffer);
CHECK_EQ("15", buffer.start());
CHECK_EQ(1, point);
}
double min_double = 5e-324;
status = FastDtoa(min_double, FAST_DTOA_PRECISION, 5,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("49407", buffer.start());
CHECK_EQ(-323, point);
double max_double = 1.7976931348623157e308;
status = FastDtoa(max_double, FAST_DTOA_PRECISION, 7,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("1797693", buffer.start());
CHECK_EQ(309, point);
status = FastDtoa(4294967272.0, FAST_DTOA_PRECISION, 14,
buffer, &length, &point);
if (status) {
CHECK(14 >= length);
TrimRepresentation(buffer);
CHECK_EQ("4294967272", buffer.start());
CHECK_EQ(10, point);
}
status = FastDtoa(4.1855804968213567e298, FAST_DTOA_PRECISION, 17,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("41855804968213567", buffer.start());
CHECK_EQ(299, point);
status = FastDtoa(5.5626846462680035e-309, FAST_DTOA_PRECISION, 1,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("6", buffer.start());
CHECK_EQ(-308, point);
status = FastDtoa(2147483648.0, FAST_DTOA_PRECISION, 5,
buffer, &length, &point);
CHECK(status);
CHECK_EQ("21475", buffer.start());
CHECK_EQ(10, point);
status = FastDtoa(3.5844466002796428e+298, FAST_DTOA_PRECISION, 10,
buffer, &length, &point);
CHECK(status);
CHECK(10 >= length);
TrimRepresentation(buffer);
CHECK_EQ("35844466", buffer.start());
CHECK_EQ(299, point);
uint64_t smallest_normal64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000);
double v = Double(smallest_normal64).value();
status = FastDtoa(v, FAST_DTOA_PRECISION, 17, buffer, &length, &point);
CHECK(status);
CHECK_EQ("22250738585072014", buffer.start());
CHECK_EQ(-307, point);
uint64_t largest_denormal64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
v = Double(largest_denormal64).value();
status = FastDtoa(v, FAST_DTOA_PRECISION, 17, buffer, &length, &point);
CHECK(status);
CHECK(20 >= length);
TrimRepresentation(buffer);
CHECK_EQ("22250738585072009", buffer.start());
CHECK_EQ(-307, point);
v = 3.3161339052167390562200598e-237;
status = FastDtoa(v, FAST_DTOA_PRECISION, 18, buffer, &length, &point);
CHECK(status);
CHECK_EQ("331613390521673906", buffer.start());
CHECK_EQ(-236, point);
v = 7.9885183916008099497815232e+191;
status = FastDtoa(v, FAST_DTOA_PRECISION, 4, buffer, &length, &point);
CHECK(status);
CHECK_EQ("7989", buffer.start());
CHECK_EQ(192, point);
}
TEST(FastDtoaGayShortest) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
bool status;
int length;
int point;
int succeeded = 0;
int total = 0;
bool needed_max_length = false;
Vector<const PrecomputedShortest> precomputed =
PrecomputedShortestRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedShortest current_test = precomputed[i];
total++;
double v = current_test.v;
status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);
CHECK(kFastDtoaMaximalLength >= length);
if (!status) continue;
if (length == kFastDtoaMaximalLength) needed_max_length = true;
succeeded++;
CHECK_EQ(current_test.decimal_point, point);
CHECK_EQ(current_test.representation, buffer.start());
}
CHECK(succeeded*1.0/total > 0.99);
CHECK(needed_max_length);
}
TEST(FastDtoaGayShortestSingle) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
bool status;
int length;
int point;
int succeeded = 0;
int total = 0;
bool needed_max_length = false;
Vector<const PrecomputedShortestSingle> precomputed =
PrecomputedShortestSingleRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedShortestSingle current_test = precomputed[i];
total++;
float v = current_test.v;
status = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0, buffer, &length, &point);
CHECK(kFastDtoaMaximalSingleLength >= length);
if (!status) continue;
if (length == kFastDtoaMaximalSingleLength) needed_max_length = true;
succeeded++;
CHECK_EQ(current_test.decimal_point, point);
CHECK_EQ(current_test.representation, buffer.start());
}
CHECK(succeeded*1.0/total > 0.98);
CHECK(needed_max_length);
}
TEST(FastDtoaGayPrecision) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
bool status;
int length;
int point;
int succeeded = 0;
int total = 0;
// Count separately for entries with less than 15 requested digits.
int succeeded_15 = 0;
int total_15 = 0;
Vector<const PrecomputedPrecision> precomputed =
PrecomputedPrecisionRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedPrecision current_test = precomputed[i];
double v = current_test.v;
int number_digits = current_test.number_digits;
total++;
if (number_digits <= 15) total_15++;
status = FastDtoa(v, FAST_DTOA_PRECISION, number_digits,
buffer, &length, &point);
CHECK(number_digits >= length);
if (!status) continue;
succeeded++;
if (number_digits <= 15) succeeded_15++;
TrimRepresentation(buffer);
CHECK_EQ(current_test.decimal_point, point);
CHECK_EQ(current_test.representation, buffer.start());
}
// The precomputed numbers contain many entries with many requested
// digits. These have a high failure rate and we therefore expect a lower
// success rate than for the shortest representation.
CHECK(succeeded*1.0/total > 0.85);
// However with less than 15 digits almost the algorithm should almost always
// succeed.
CHECK(succeeded_15*1.0/total_15 > 0.9999);
}

View file

@ -0,0 +1,515 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "libc/isystem/stdlib.h"
#include "third_party/double-conversion/test/cctest.h"
#include "third_party/double-conversion/fixed-dtoa.h"
#include "third_party/double-conversion/test/gay-fixed.h"
#include "third_party/double-conversion/ieee.h"
#include "third_party/double-conversion/utils.h"
using namespace double_conversion;
static const int kBufferSize = 500;
TEST(FastFixedVariousDoubles) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
int length;
int point;
CHECK(FastFixedDtoa(1.0, 1, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(1.0, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(1.0, 0, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0xFFFFFFFF, 5, buffer, &length, &point));
CHECK_EQ("4294967295", buffer.start());
CHECK_EQ(10, point);
CHECK(FastFixedDtoa(4294967296.0, 5, buffer, &length, &point));
CHECK_EQ("4294967296", buffer.start());
CHECK_EQ(10, point);
CHECK(FastFixedDtoa(1e21, 5, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
// CHECK_EQ(22, point);
CHECK_EQ(22, point);
CHECK(FastFixedDtoa(999999999999999868928.00, 2, buffer, &length, &point));
CHECK_EQ("999999999999999868928", buffer.start());
CHECK_EQ(21, point);
CHECK(FastFixedDtoa(6.9999999999999989514240000e+21, 5, buffer,
&length, &point));
CHECK_EQ("6999999999999998951424", buffer.start());
CHECK_EQ(22, point);
CHECK(FastFixedDtoa(1.5, 5, buffer, &length, &point));
CHECK_EQ("15", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(1.55, 5, buffer, &length, &point));
CHECK_EQ("155", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(1.55, 1, buffer, &length, &point));
CHECK_EQ("16", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(1.00000001, 15, buffer, &length, &point));
CHECK_EQ("100000001", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.1, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(0, point);
CHECK(FastFixedDtoa(0.01, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-1, point);
CHECK(FastFixedDtoa(0.001, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-2, point);
CHECK(FastFixedDtoa(0.0001, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-3, point);
CHECK(FastFixedDtoa(0.00001, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-4, point);
CHECK(FastFixedDtoa(0.000001, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-5, point);
CHECK(FastFixedDtoa(0.0000001, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-6, point);
CHECK(FastFixedDtoa(0.00000001, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-7, point);
CHECK(FastFixedDtoa(0.000000001, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-8, point);
CHECK(FastFixedDtoa(0.0000000001, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-9, point);
CHECK(FastFixedDtoa(0.00000000001, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-10, point);
CHECK(FastFixedDtoa(0.000000000001, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-11, point);
CHECK(FastFixedDtoa(0.0000000000001, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-12, point);
CHECK(FastFixedDtoa(0.00000000000001, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-13, point);
CHECK(FastFixedDtoa(0.000000000000001, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-14, point);
CHECK(FastFixedDtoa(0.0000000000000001, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-15, point);
CHECK(FastFixedDtoa(0.00000000000000001, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-16, point);
CHECK(FastFixedDtoa(0.000000000000000001, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-17, point);
CHECK(FastFixedDtoa(0.0000000000000000001, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-18, point);
CHECK(FastFixedDtoa(0.00000000000000000001, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-19, point);
CHECK(FastFixedDtoa(0.10000000004, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(0, point);
CHECK(FastFixedDtoa(0.01000000004, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-1, point);
CHECK(FastFixedDtoa(0.00100000004, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-2, point);
CHECK(FastFixedDtoa(0.00010000004, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-3, point);
CHECK(FastFixedDtoa(0.00001000004, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-4, point);
CHECK(FastFixedDtoa(0.00000100004, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-5, point);
CHECK(FastFixedDtoa(0.00000010004, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-6, point);
CHECK(FastFixedDtoa(0.00000001004, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-7, point);
CHECK(FastFixedDtoa(0.00000000104, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-8, point);
CHECK(FastFixedDtoa(0.0000000001000004, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-9, point);
CHECK(FastFixedDtoa(0.0000000000100004, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-10, point);
CHECK(FastFixedDtoa(0.0000000000010004, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-11, point);
CHECK(FastFixedDtoa(0.0000000000001004, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-12, point);
CHECK(FastFixedDtoa(0.0000000000000104, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-13, point);
CHECK(FastFixedDtoa(0.000000000000001000004, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-14, point);
CHECK(FastFixedDtoa(0.000000000000000100004, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-15, point);
CHECK(FastFixedDtoa(0.000000000000000010004, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-16, point);
CHECK(FastFixedDtoa(0.000000000000000001004, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-17, point);
CHECK(FastFixedDtoa(0.000000000000000000104, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-18, point);
CHECK(FastFixedDtoa(0.000000000000000000014, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-19, point);
CHECK(FastFixedDtoa(0.10000000006, 10, buffer, &length, &point));
CHECK_EQ("1000000001", buffer.start());
CHECK_EQ(0, point);
CHECK(FastFixedDtoa(0.01000000006, 10, buffer, &length, &point));
CHECK_EQ("100000001", buffer.start());
CHECK_EQ(-1, point);
CHECK(FastFixedDtoa(0.00100000006, 10, buffer, &length, &point));
CHECK_EQ("10000001", buffer.start());
CHECK_EQ(-2, point);
CHECK(FastFixedDtoa(0.00010000006, 10, buffer, &length, &point));
CHECK_EQ("1000001", buffer.start());
CHECK_EQ(-3, point);
CHECK(FastFixedDtoa(0.00001000006, 10, buffer, &length, &point));
CHECK_EQ("100001", buffer.start());
CHECK_EQ(-4, point);
CHECK(FastFixedDtoa(0.00000100006, 10, buffer, &length, &point));
CHECK_EQ("10001", buffer.start());
CHECK_EQ(-5, point);
CHECK(FastFixedDtoa(0.00000010006, 10, buffer, &length, &point));
CHECK_EQ("1001", buffer.start());
CHECK_EQ(-6, point);
CHECK(FastFixedDtoa(0.00000001006, 10, buffer, &length, &point));
CHECK_EQ("101", buffer.start());
CHECK_EQ(-7, point);
CHECK(FastFixedDtoa(0.00000000106, 10, buffer, &length, &point));
CHECK_EQ("11", buffer.start());
CHECK_EQ(-8, point);
CHECK(FastFixedDtoa(0.0000000001000006, 15, buffer, &length, &point));
CHECK_EQ("100001", buffer.start());
CHECK_EQ(-9, point);
CHECK(FastFixedDtoa(0.0000000000100006, 15, buffer, &length, &point));
CHECK_EQ("10001", buffer.start());
CHECK_EQ(-10, point);
CHECK(FastFixedDtoa(0.0000000000010006, 15, buffer, &length, &point));
CHECK_EQ("1001", buffer.start());
CHECK_EQ(-11, point);
CHECK(FastFixedDtoa(0.0000000000001006, 15, buffer, &length, &point));
CHECK_EQ("101", buffer.start());
CHECK_EQ(-12, point);
CHECK(FastFixedDtoa(0.0000000000000106, 15, buffer, &length, &point));
CHECK_EQ("11", buffer.start());
CHECK_EQ(-13, point);
CHECK(FastFixedDtoa(0.000000000000001000006, 20, buffer, &length, &point));
CHECK_EQ("100001", buffer.start());
CHECK_EQ(-14, point);
CHECK(FastFixedDtoa(0.000000000000000100006, 20, buffer, &length, &point));
CHECK_EQ("10001", buffer.start());
CHECK_EQ(-15, point);
CHECK(FastFixedDtoa(0.000000000000000010006, 20, buffer, &length, &point));
CHECK_EQ("1001", buffer.start());
CHECK_EQ(-16, point);
CHECK(FastFixedDtoa(0.000000000000000001006, 20, buffer, &length, &point));
CHECK_EQ("101", buffer.start());
CHECK_EQ(-17, point);
CHECK(FastFixedDtoa(0.000000000000000000106, 20, buffer, &length, &point));
CHECK_EQ("11", buffer.start());
CHECK_EQ(-18, point);
CHECK(FastFixedDtoa(0.000000000000000000016, 20, buffer, &length, &point));
CHECK_EQ("2", buffer.start());
CHECK_EQ(-19, point);
CHECK(FastFixedDtoa(0.6, 0, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.96, 1, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.996, 2, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.9996, 3, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.99996, 4, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.999996, 5, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.9999996, 6, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.99999996, 7, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.999999996, 8, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.9999999996, 9, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.99999999996, 10, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.999999999996, 11, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.9999999999996, 12, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.99999999999996, 13, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.999999999999996, 14, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.9999999999999996, 15, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(0.00999999999999996, 16, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-1, point);
CHECK(FastFixedDtoa(0.000999999999999996, 17, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-2, point);
CHECK(FastFixedDtoa(0.0000999999999999996, 18, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-3, point);
CHECK(FastFixedDtoa(0.00000999999999999996, 19, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-4, point);
CHECK(FastFixedDtoa(0.000000999999999999996, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-5, point);
CHECK(FastFixedDtoa(323423.234234, 10, buffer, &length, &point));
CHECK_EQ("323423234234", buffer.start());
CHECK_EQ(6, point);
CHECK(FastFixedDtoa(12345678.901234, 4, buffer, &length, &point));
CHECK_EQ("123456789012", buffer.start());
CHECK_EQ(8, point);
CHECK(FastFixedDtoa(98765.432109, 5, buffer, &length, &point));
CHECK_EQ("9876543211", buffer.start());
CHECK_EQ(5, point);
CHECK(FastFixedDtoa(42, 20, buffer, &length, &point));
CHECK_EQ("42", buffer.start());
CHECK_EQ(2, point);
CHECK(FastFixedDtoa(0.5, 0, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(1, point);
CHECK(FastFixedDtoa(1e-23, 10, buffer, &length, &point));
CHECK_EQ("", buffer.start());
CHECK_EQ(-10, point);
CHECK(FastFixedDtoa(1e-123, 2, buffer, &length, &point));
CHECK_EQ("", buffer.start());
CHECK_EQ(-2, point);
CHECK(FastFixedDtoa(1e-123, 0, buffer, &length, &point));
CHECK_EQ("", buffer.start());
CHECK_EQ(0, point);
CHECK(FastFixedDtoa(1e-23, 20, buffer, &length, &point));
CHECK_EQ("", buffer.start());
CHECK_EQ(-20, point);
CHECK(FastFixedDtoa(1e-21, 20, buffer, &length, &point));
CHECK_EQ("", buffer.start());
CHECK_EQ(-20, point);
CHECK(FastFixedDtoa(1e-22, 20, buffer, &length, &point));
CHECK_EQ("", buffer.start());
CHECK_EQ(-20, point);
CHECK(FastFixedDtoa(6e-21, 20, buffer, &length, &point));
CHECK_EQ("1", buffer.start());
CHECK_EQ(-19, point);
CHECK(FastFixedDtoa(9.1193616301674545152000000e+19, 0,
buffer, &length, &point));
CHECK_EQ("91193616301674545152", buffer.start());
CHECK_EQ(20, point);
CHECK(FastFixedDtoa(4.8184662102767651659096515e-04, 19,
buffer, &length, &point));
CHECK_EQ("4818466210276765", buffer.start());
CHECK_EQ(-3, point);
CHECK(FastFixedDtoa(1.9023164229540652612705182e-23, 8,
buffer, &length, &point));
CHECK_EQ("", buffer.start());
CHECK_EQ(-8, point);
CHECK(FastFixedDtoa(1000000000000000128.0, 0,
buffer, &length, &point));
CHECK_EQ("1000000000000000128", buffer.start());
CHECK_EQ(19, point);
CHECK(FastFixedDtoa(2.10861548515811875e+15, 17, buffer, &length, &point));
CHECK_EQ("210861548515811875", buffer.start());
CHECK_EQ(16, point);
}
TEST(FastFixedDtoaGayFixed) {
char buffer_container[kBufferSize];
Vector<char> buffer(buffer_container, kBufferSize);
bool status;
int length;
int point;
Vector<const PrecomputedFixed> precomputed =
PrecomputedFixedRepresentations();
for (int i = 0; i < precomputed.length(); ++i) {
const PrecomputedFixed current_test = precomputed[i];
double v = current_test.v;
int number_digits = current_test.number_digits;
status = FastFixedDtoa(v, number_digits,
buffer, &length, &point);
CHECK(status);
CHECK_EQ(current_test.decimal_point, point);
CHECK(number_digits >= length - point);
CHECK_EQ(current_test.representation, buffer.start());
}
}

View file

@ -0,0 +1,463 @@
// 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 "libc/isystem/stdlib.h"
#include "third_party/libcxx/limits"
#include "third_party/double-conversion/test/cctest.h"
#include "third_party/double-conversion/diy-fp.h"
#include "third_party/double-conversion/utils.h"
#include "third_party/double-conversion/ieee.h"
using namespace double_conversion;
TEST(Uint64Conversions) {
// Start by checking the byte-order.
uint64_t ordered = DOUBLE_CONVERSION_UINT64_2PART_C(0x01234567, 89ABCDEF);
CHECK_EQ(3512700564088504e-318, Double(ordered).value());
uint64_t min_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00000000, 00000001);
CHECK_EQ(5e-324, Double(min_double64).value());
uint64_t max_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x7fefffff, ffffffff);
CHECK_EQ(1.7976931348623157e308, Double(max_double64).value());
}
TEST(Uint32Conversions) {
// Start by checking the byte-order.
uint32_t ordered = 0x01234567;
CHECK_EQ(2.9988165487136453e-38f, Single(ordered).value());
uint32_t min_float32 = 0x00000001;
CHECK_EQ(1.4e-45f, Single(min_float32).value());
uint32_t max_float32 = 0x7f7fffff;
CHECK_EQ(3.4028234e38f, Single(max_float32).value());
}
TEST(Double_AsDiyFp) {
uint64_t ordered = DOUBLE_CONVERSION_UINT64_2PART_C(0x01234567, 89ABCDEF);
DiyFp diy_fp = Double(ordered).AsDiyFp();
CHECK_EQ(0x12 - 0x3FF - 52, diy_fp.e());
// The 52 mantissa bits, plus the implicit 1 in bit 52 as a UINT64.
CHECK(DOUBLE_CONVERSION_UINT64_2PART_C(0x00134567, 89ABCDEF) == diy_fp.f()); // NOLINT
uint64_t min_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00000000, 00000001);
diy_fp = Double(min_double64).AsDiyFp();
CHECK_EQ(-0x3FF - 52 + 1, diy_fp.e());
// This is a denormal; so no hidden bit.
CHECK(1 == diy_fp.f()); // NOLINT
uint64_t max_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x7fefffff, ffffffff);
diy_fp = Double(max_double64).AsDiyFp();
CHECK_EQ(0x7FE - 0x3FF - 52, diy_fp.e());
CHECK(DOUBLE_CONVERSION_UINT64_2PART_C(0x001fffff, ffffffff) == diy_fp.f()); // NOLINT
}
TEST(Single_AsDiyFp) {
uint32_t ordered = 0x01234567;
DiyFp diy_fp = Single(ordered).AsDiyFp();
CHECK_EQ(0x2 - 0x7F - 23, diy_fp.e());
// The 23 mantissa bits, plus the implicit 1 in bit 24 as a uint32_t.
CHECK_EQ(0xA34567, diy_fp.f());
uint32_t min_float32 = 0x00000001;
diy_fp = Single(min_float32).AsDiyFp();
CHECK_EQ(-0x7F - 23 + 1, diy_fp.e());
// This is a denormal; so no hidden bit.
CHECK_EQ(1, diy_fp.f());
uint32_t max_float32 = 0x7f7fffff;
diy_fp = Single(max_float32).AsDiyFp();
CHECK_EQ(0xFE - 0x7F - 23, diy_fp.e());
CHECK_EQ(0x00ffffff, diy_fp.f());
}
TEST(AsNormalizedDiyFp) {
uint64_t ordered = DOUBLE_CONVERSION_UINT64_2PART_C(0x01234567, 89ABCDEF);
DiyFp diy_fp = Double(ordered).AsNormalizedDiyFp();
CHECK_EQ(0x12 - 0x3FF - 52 - 11, diy_fp.e());
CHECK((DOUBLE_CONVERSION_UINT64_2PART_C(0x00134567, 89ABCDEF) << 11) ==
diy_fp.f()); // NOLINT
uint64_t min_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00000000, 00000001);
diy_fp = Double(min_double64).AsNormalizedDiyFp();
CHECK_EQ(-0x3FF - 52 + 1 - 63, diy_fp.e());
// This is a denormal; so no hidden bit.
CHECK(DOUBLE_CONVERSION_UINT64_2PART_C(0x80000000, 00000000) == diy_fp.f()); // NOLINT
uint64_t max_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x7fefffff, ffffffff);
diy_fp = Double(max_double64).AsNormalizedDiyFp();
CHECK_EQ(0x7FE - 0x3FF - 52 - 11, diy_fp.e());
CHECK((DOUBLE_CONVERSION_UINT64_2PART_C(0x001fffff, ffffffff) << 11) ==
diy_fp.f()); // NOLINT
}
TEST(Double_IsDenormal) {
uint64_t min_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00000000, 00000001);
CHECK(Double(min_double64).IsDenormal());
uint64_t bits = DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
CHECK(Double(bits).IsDenormal());
bits = DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000);
CHECK(!Double(bits).IsDenormal());
}
TEST(Single_IsDenormal) {
uint32_t min_float32 = 0x00000001;
CHECK(Single(min_float32).IsDenormal());
uint32_t bits = 0x007FFFFF;
CHECK(Single(bits).IsDenormal());
bits = 0x00800000;
CHECK(!Single(bits).IsDenormal());
}
TEST(Double_IsSpecial) {
CHECK(Double(Double::Infinity()).IsSpecial());
CHECK(Double(-Double::Infinity()).IsSpecial());
CHECK(Double(Double::NaN()).IsSpecial());
uint64_t bits = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFF12345, 00000000);
CHECK(Double(bits).IsSpecial());
// Denormals are not special:
CHECK(!Double(5e-324).IsSpecial());
CHECK(!Double(-5e-324).IsSpecial());
// And some random numbers:
CHECK(!Double(0.0).IsSpecial());
CHECK(!Double(-0.0).IsSpecial());
CHECK(!Double(1.0).IsSpecial());
CHECK(!Double(-1.0).IsSpecial());
CHECK(!Double(1000000.0).IsSpecial());
CHECK(!Double(-1000000.0).IsSpecial());
CHECK(!Double(1e23).IsSpecial());
CHECK(!Double(-1e23).IsSpecial());
CHECK(!Double(1.7976931348623157e308).IsSpecial());
CHECK(!Double(-1.7976931348623157e308).IsSpecial());
}
TEST(Single_IsSpecial) {
CHECK(Single(Single::Infinity()).IsSpecial());
CHECK(Single(-Single::Infinity()).IsSpecial());
CHECK(Single(Single::NaN()).IsSpecial());
uint32_t bits = 0xFFF12345;
CHECK(Single(bits).IsSpecial());
// Denormals are not special:
CHECK(!Single(1.4e-45f).IsSpecial());
CHECK(!Single(-1.4e-45f).IsSpecial());
// And some random numbers:
CHECK(!Single(0.0f).IsSpecial());
CHECK(!Single(-0.0f).IsSpecial());
CHECK(!Single(1.0f).IsSpecial());
CHECK(!Single(-1.0f).IsSpecial());
CHECK(!Single(1000000.0f).IsSpecial());
CHECK(!Single(-1000000.0f).IsSpecial());
CHECK(!Single(1e23f).IsSpecial());
CHECK(!Single(-1e23f).IsSpecial());
CHECK(!Single(1.18e-38f).IsSpecial());
CHECK(!Single(-1.18e-38f).IsSpecial());
}
TEST(Double_IsInfinite) {
CHECK(Double(Double::Infinity()).IsInfinite());
CHECK(Double(-Double::Infinity()).IsInfinite());
CHECK(!Double(Double::NaN()).IsInfinite());
CHECK(!Double(0.0).IsInfinite());
CHECK(!Double(-0.0).IsInfinite());
CHECK(!Double(1.0).IsInfinite());
CHECK(!Double(-1.0).IsInfinite());
uint64_t min_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00000000, 00000001);
CHECK(!Double(min_double64).IsInfinite());
}
TEST(Single_IsInfinite) {
CHECK(Single(Single::Infinity()).IsInfinite());
CHECK(Single(-Single::Infinity()).IsInfinite());
CHECK(!Single(Single::NaN()).IsInfinite());
CHECK(!Single(0.0f).IsInfinite());
CHECK(!Single(-0.0f).IsInfinite());
CHECK(!Single(1.0f).IsInfinite());
CHECK(!Single(-1.0f).IsInfinite());
uint32_t min_float32 = 0x00000001;
CHECK(!Single(min_float32).IsInfinite());
}
TEST(Double_IsNan) {
CHECK(Double(Double::NaN()).IsNan());
uint64_t other_nan = DOUBLE_CONVERSION_UINT64_2PART_C(0xFFFFFFFF, 00000001);
CHECK(Double(other_nan).IsNan());
CHECK(!Double(Double::Infinity()).IsNan());
CHECK(!Double(-Double::Infinity()).IsNan());
CHECK(!Double(0.0).IsNan());
CHECK(!Double(-0.0).IsNan());
CHECK(!Double(1.0).IsNan());
CHECK(!Double(-1.0).IsNan());
uint64_t min_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00000000, 00000001);
CHECK(!Double(min_double64).IsNan());
}
TEST(Single_IsNan) {
CHECK(Single(Single::NaN()).IsNan());
uint32_t other_nan = 0xFFFFF001;
CHECK(Single(other_nan).IsNan());
CHECK(!Single(Single::Infinity()).IsNan());
CHECK(!Single(-Single::Infinity()).IsNan());
CHECK(!Single(0.0f).IsNan());
CHECK(!Single(-0.0f).IsNan());
CHECK(!Single(1.0f).IsNan());
CHECK(!Single(-1.0f).IsNan());
uint32_t min_float32 = 0x00000001;
CHECK(!Single(min_float32).IsNan());
}
TEST(Double_Sign) {
CHECK_EQ(1, Double(1.0).Sign());
CHECK_EQ(1, Double(Double::Infinity()).Sign());
CHECK_EQ(-1, Double(-Double::Infinity()).Sign());
CHECK_EQ(1, Double(0.0).Sign());
CHECK_EQ(-1, Double(-0.0).Sign());
uint64_t min_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00000000, 00000001);
CHECK_EQ(1, Double(min_double64).Sign());
}
TEST(Single_Sign) {
CHECK_EQ(1, Single(1.0f).Sign());
CHECK_EQ(1, Single(Single::Infinity()).Sign());
CHECK_EQ(-1, Single(-Single::Infinity()).Sign());
CHECK_EQ(1, Single(0.0f).Sign());
CHECK_EQ(-1, Single(-0.0f).Sign());
uint32_t min_float32 = 0x00000001;
CHECK_EQ(1, Single(min_float32).Sign());
}
TEST(Double_NormalizedBoundaries) {
DiyFp boundary_plus;
DiyFp boundary_minus;
DiyFp diy_fp = Double(1.5).AsNormalizedDiyFp();
Double(1.5).NormalizedBoundaries(&boundary_minus, &boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
// 1.5 does not have a significand of the form 2^p (for some p).
// Therefore its boundaries are at the same distance.
CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
CHECK((1 << 10) == diy_fp.f() - boundary_minus.f()); // NOLINT
diy_fp = Double(1.0).AsNormalizedDiyFp();
Double(1.0).NormalizedBoundaries(&boundary_minus, &boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
// 1.0 does have a significand of the form 2^p (for some p).
// Therefore its lower boundary is twice as close as the upper boundary.
CHECK(boundary_plus.f() - diy_fp.f() > diy_fp.f() - boundary_minus.f());
CHECK((1 << 9) == diy_fp.f() - boundary_minus.f()); // NOLINT
CHECK((1 << 10) == boundary_plus.f() - diy_fp.f()); // NOLINT
uint64_t min_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00000000, 00000001);
diy_fp = Double(min_double64).AsNormalizedDiyFp();
Double(min_double64).NormalizedBoundaries(&boundary_minus, &boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
// min-value does not have a significand of the form 2^p (for some p).
// Therefore its boundaries are at the same distance.
CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
// Denormals have their boundaries much closer.
CHECK((static_cast<uint64_t>(1) << 62) ==
diy_fp.f() - boundary_minus.f()); // NOLINT
uint64_t smallest_normal64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x00100000, 00000000);
diy_fp = Double(smallest_normal64).AsNormalizedDiyFp();
Double(smallest_normal64).NormalizedBoundaries(&boundary_minus,
&boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
// Even though the significand is of the form 2^p (for some p), its boundaries
// are at the same distance. (This is the only exception).
CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
CHECK((1 << 10) == diy_fp.f() - boundary_minus.f()); // NOLINT
uint64_t largest_denormal64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
diy_fp = Double(largest_denormal64).AsNormalizedDiyFp();
Double(largest_denormal64).NormalizedBoundaries(&boundary_minus,
&boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
CHECK((1 << 11) == diy_fp.f() - boundary_minus.f()); // NOLINT
uint64_t max_double64 = DOUBLE_CONVERSION_UINT64_2PART_C(0x7fefffff, ffffffff);
diy_fp = Double(max_double64).AsNormalizedDiyFp();
Double(max_double64).NormalizedBoundaries(&boundary_minus, &boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
// max-value does not have a significand of the form 2^p (for some p).
// Therefore its boundaries are at the same distance.
CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
CHECK((1 << 10) == diy_fp.f() - boundary_minus.f()); // NOLINT
}
TEST(Single_NormalizedBoundaries) {
uint64_t kOne64 = 1;
DiyFp boundary_plus;
DiyFp boundary_minus;
DiyFp diy_fp = Single(1.5f).AsDiyFp();
diy_fp.Normalize();
Single(1.5f).NormalizedBoundaries(&boundary_minus, &boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
// 1.5 does not have a significand of the form 2^p (for some p).
// Therefore its boundaries are at the same distance.
CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
// Normalization shifts the significand by 8 bits. Add 32 bits for the bigger
// data-type, and remove 1 because boundaries are at half a ULP.
CHECK((kOne64 << 39) == diy_fp.f() - boundary_minus.f());
diy_fp = Single(1.0f).AsDiyFp();
diy_fp.Normalize();
Single(1.0f).NormalizedBoundaries(&boundary_minus, &boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
// 1.0 does have a significand of the form 2^p (for some p).
// Therefore its lower boundary is twice as close as the upper boundary.
CHECK(boundary_plus.f() - diy_fp.f() > diy_fp.f() - boundary_minus.f());
CHECK((kOne64 << 38) == diy_fp.f() - boundary_minus.f()); // NOLINT
CHECK((kOne64 << 39) == boundary_plus.f() - diy_fp.f()); // NOLINT
uint32_t min_float32 = 0x00000001;
diy_fp = Single(min_float32).AsDiyFp();
diy_fp.Normalize();
Single(min_float32).NormalizedBoundaries(&boundary_minus, &boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
// min-value does not have a significand of the form 2^p (for some p).
// Therefore its boundaries are at the same distance.
CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
// Denormals have their boundaries much closer.
CHECK((kOne64 << 62) == diy_fp.f() - boundary_minus.f()); // NOLINT
uint32_t smallest_normal32 = 0x00800000;
diy_fp = Single(smallest_normal32).AsDiyFp();
diy_fp.Normalize();
Single(smallest_normal32).NormalizedBoundaries(&boundary_minus,
&boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
// Even though the significand is of the form 2^p (for some p), its boundaries
// are at the same distance. (This is the only exception).
CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
CHECK((kOne64 << 39) == diy_fp.f() - boundary_minus.f()); // NOLINT
uint32_t largest_denormal32 = 0x007FFFFF;
diy_fp = Single(largest_denormal32).AsDiyFp();
diy_fp.Normalize();
Single(largest_denormal32).NormalizedBoundaries(&boundary_minus,
&boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
CHECK((kOne64 << 40) == diy_fp.f() - boundary_minus.f()); // NOLINT
uint32_t max_float32 = 0x7f7fffff;
diy_fp = Single(max_float32).AsDiyFp();
diy_fp.Normalize();
Single(max_float32).NormalizedBoundaries(&boundary_minus, &boundary_plus);
CHECK_EQ(diy_fp.e(), boundary_minus.e());
CHECK_EQ(diy_fp.e(), boundary_plus.e());
// max-value does not have a significand of the form 2^p (for some p).
// Therefore its boundaries are at the same distance.
CHECK(diy_fp.f() - boundary_minus.f() == boundary_plus.f() - diy_fp.f());
CHECK((kOne64 << 39) == diy_fp.f() - boundary_minus.f()); // NOLINT
}
TEST(NextDouble) {
CHECK_EQ(4e-324, Double(0.0).NextDouble());
CHECK_EQ(0.0, Double(-0.0).NextDouble());
CHECK_EQ(-0.0, Double(-4e-324).NextDouble());
CHECK(Double(Double(-0.0).NextDouble()).Sign() > 0);
CHECK(Double(Double(-4e-324).NextDouble()).Sign() < 0);
Double d0(-4e-324);
Double d1(d0.NextDouble());
Double d2(d1.NextDouble());
CHECK_EQ(-0.0, d1.value());
CHECK(d1.Sign() < 0);
CHECK_EQ(0.0, d2.value());
CHECK(d2.Sign() > 0);
CHECK_EQ(4e-324, d2.NextDouble());
CHECK_EQ(-1.7976931348623157e308, Double(-Double::Infinity()).NextDouble());
CHECK_EQ(Double::Infinity(),
Double(DOUBLE_CONVERSION_UINT64_2PART_C(0x7fefffff, ffffffff)).NextDouble());
}
TEST(PreviousDouble) {
CHECK_EQ(0.0, Double(4e-324).PreviousDouble());
CHECK_EQ(-0.0, Double(0.0).PreviousDouble());
CHECK(Double(Double(0.0).PreviousDouble()).Sign() < 0);
CHECK_EQ(-4e-324, Double(-0.0).PreviousDouble());
Double d0(4e-324);
Double d1(d0.PreviousDouble());
Double d2(d1.PreviousDouble());
CHECK_EQ(0.0, d1.value());
CHECK(d1.Sign() > 0);
CHECK_EQ(-0.0, d2.value());
CHECK(d2.Sign() < 0);
CHECK_EQ(-4e-324, d2.PreviousDouble());
CHECK_EQ(1.7976931348623157e308, Double(Double::Infinity()).PreviousDouble());
CHECK_EQ(-Double::Infinity(),
Double(DOUBLE_CONVERSION_UINT64_2PART_C(0xffefffff, ffffffff)).PreviousDouble());
}
TEST(SignalingNan) {
Double nan(Double::NaN());
CHECK(nan.IsNan());
CHECK(nan.IsQuietNan());
CHECK(Double(std::numeric_limits<double>::quiet_NaN()).IsQuietNan());
CHECK(Double(std::numeric_limits<double>::signaling_NaN()).IsSignalingNan());
}
TEST(SignalingNanSingle) {
Single nan(Single::NaN());
CHECK(nan.IsNan());
CHECK(nan.IsQuietNan());
CHECK(Single(std::numeric_limits<float>::quiet_NaN()).IsQuietNan());
CHECK(Single(std::numeric_limits<float>::signaling_NaN()).IsSignalingNan());
}

File diff suppressed because it is too large Load diff