AK: Add an exact and fast floating point parsing algorithm

This is based on the paper by Daniel Lemire called
"Number parsing at a Gigabyte per second", currently available at
https://arxiv.org/abs/2101.11408
An implementation can be found at
https://github.com/fastfloat/fast_float

To support both strtod like methods and String::to_double we have two
different APIs. The parse_first_floating_point gives back both the
result, next character to read and the error/out of range status.
Out of range here means we rounded to infinity 0.

The other API, parse_floating_point_completely, will return a floating
point only if the given character range contains just the floating point
and nothing else. This can be much faster as we can skip actually
computing the value if we notice we did not parse the whole range.

Both of these APIs support a very lenient format to be usable in as many
places as possible. Also it does not check for "named" values like
"nan", "inf", "NAN" etc. Because this can be different for every usage.

For integers and small values this new method is not faster and often
even a tiny bit slower than the current strtod implementation. However
the strtod implementation is wrong for a lot of values and has a much
less predictable running time.

For correctness this method was tested against known string -> double
datasets from https://github.com/nigeltao/parse-number-fxx-test-data
This method gives 100% accuracy.
The old strtod gave an incorrect value in over 50% of the numbers
tested.
This commit is contained in:
davidot 2022-10-13 02:18:56 +02:00 committed by Linus Groh
parent bf6d4a5cbf
commit 53b7f5e6a1
Notes: sideshowbarker 2024-07-17 20:58:35 +09:00
5 changed files with 2500 additions and 0 deletions

View file

@ -1,6 +1,7 @@
set(AK_SOURCES set(AK_SOURCES
Assertions.cpp Assertions.cpp
Base64.cpp Base64.cpp
FloatingPointStringConversions.cpp
FlyString.cpp FlyString.cpp
Format.cpp Format.cpp
FuzzyMatch.cpp FuzzyMatch.cpp

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2022, David Tuin <davidot@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#ifdef KERNEL
# error This file should not be included in the KERNEL as it deals with doubles \
and there is no guraantee does not do any floating point computations.
#endif
#include <AK/StringView.h>
namespace AK {
static constexpr char floating_point_decimal_separator = '.';
enum class FloatingPointError {
None,
NoOrInvalidInput,
OutOfRange,
RoundedDownToZero
};
template<FloatingPoint T>
struct FloatingPointParseResults {
char const* end_ptr { nullptr };
FloatingPointError error = FloatingPointError::None;
T value {};
[[nodiscard]] bool parsed_value() const
{
// All other errors do indicate out of range but did produce a valid value.
return error != FloatingPointError::NoOrInvalidInput;
}
};
/// This function finds the first floating point within [start, end). The accepted format is
/// intentionally as lenient as possible. If your format is stricter you must validate it
/// first. The format accepts:
/// - An optional sign, both + and - are supported
/// - 0 or more decimal digits, with leading zeros allowed [1]
/// - A decimal point '.', which can have no digits after it
/// - 0 or more decimal digits, unless the first digits [1] doesn't have any digits,
/// then this must have at least one
/// - An exponent 'e' or 'E' followed by an optional sign '+' or '-' and at least one digit
/// This function additionally detects out of range values which have been rounded to
/// [-]infinity or 0 and gives the next character to read after the floating point.
template<FloatingPoint T = double>
FloatingPointParseResults<T> parse_first_floating_point(char const* start, char const* end);
/// This function finds the first floating point starting at start up to the first '\0'.
/// The format is identical to parse_first_floating_point above.
template<FloatingPoint T = double>
FloatingPointParseResults<T> parse_first_floating_point_until_zero_character(char const* start);
/// This function will return either a floating point, or an empty optional if the given StringView
/// does not a floating point or contains more characters beyond the floating point. For the format
/// check the comment on parse_first_floating_point.
template<FloatingPoint T = double>
Optional<T> parse_floating_point_completely(char const* start, char const* end);
}
using AK::parse_first_floating_point;
using AK::parse_floating_point_completely;

View file

@ -27,6 +27,7 @@ set(AK_TEST_SOURCES
TestFind.cpp TestFind.cpp
TestFixedArray.cpp TestFixedArray.cpp
TestFloatingPoint.cpp TestFloatingPoint.cpp
TestFloatingPointParsing.cpp
TestFormat.cpp TestFormat.cpp
TestGenericLexer.cpp TestGenericLexer.cpp
TestHashFunctions.cpp TestHashFunctions.cpp

View file

@ -0,0 +1,412 @@
/*
* Copyright (c) 2020, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibTest/TestCase.h>
#include <AK/FloatingPointStringConversions.h>
static double parse_complete_double(StringView view)
{
char const* start = view.characters_without_null_termination();
return parse_floating_point_completely<double>(start, start + view.length()).release_value();
}
static float parse_complete_float(StringView view)
{
char const* start = view.characters_without_null_termination();
return parse_floating_point_completely<float>(start, start + view.length()).release_value();
}
TEST_CASE(simple_cases)
{
#define DOES_PARSE_DOUBLE_LIKE_CPP(value) \
do { \
EXPECT_EQ(static_cast<double>(value), parse_complete_double(#value##sv)); \
EXPECT_EQ(-static_cast<double>(value), parse_complete_double("-" #value##sv)); \
} while (false)
#define DOES_PARSE_FLOAT_LIKE_CPP(value) \
do { \
float val = parse_complete_float(#value##sv); \
EXPECT_EQ(static_cast<float>(value##f), val); \
EXPECT_EQ(-static_cast<float>(value##f), parse_complete_float("-" #value##sv)); \
} while (false)
#define DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(value) \
DOES_PARSE_DOUBLE_LIKE_CPP(value); \
DOES_PARSE_FLOAT_LIKE_CPP(value);
DOES_PARSE_DOUBLE_LIKE_CPP(2.22507385850720138309e-308);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(10090518465521146875.);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(10052108125844341766.);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(0.);
constexpr u64 negative_zero = 1ull << 63;
EXPECT_EQ(0ull, bit_cast<u64>(parse_complete_double("0"sv)));
EXPECT_EQ(negative_zero, bit_cast<u64>(parse_complete_double("-0"sv)));
EXPECT_EQ(negative_zero, bit_cast<u64>(parse_complete_double("-0."sv)));
EXPECT_EQ(negative_zero, bit_cast<u64>(parse_complete_double("-0.0"sv)));
DOES_PARSE_DOUBLE_LIKE_CPP(2.2222222222223e-322);
DOES_PARSE_DOUBLE_LIKE_CPP(2.2250738585072013e-308);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(1.0);
DOES_PARSE_DOUBLE_LIKE_CPP(0.54e-85);
DOES_PARSE_DOUBLE_LIKE_CPP(123);
DOES_PARSE_DOUBLE_LIKE_CPP(1e10);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(001234.0);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(123.456);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(0.456);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(0.456);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(0.45689544977495495495197116546843576574949654);
DOES_PARSE_DOUBLE_LIKE_CPP(0.45689544977495495495197116546843576574949654e81);
DOES_PARSE_DOUBLE_LIKE_CPP(0.45689544977495495495197116546843576574949654e-81);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(7.2057594037927933e+8);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(234532.3426362);
DOES_PARSE_DOUBLE_LIKE_CPP(860228122.6654514319E+90);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009195);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009200);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009199);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009198);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009208);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009204);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009200);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009201);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009202);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009203);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009205);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009206);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.000);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.0001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.0000);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.00001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.0000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.00000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.0000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.00000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.0000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.00000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.000000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.0000000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.00000000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.000000000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.0000000000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.00000000000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.000000000000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(69294956446009204.0000000000000000000001);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009196);
DOES_PARSE_DOUBLE_LIKE_CPP(69294956446009115);
DOES_PARSE_DOUBLE_LIKE_CPP(692949564460091155);
DOES_PARSE_DOUBLE_LIKE_CPP(6929495644600911557);
DOES_PARSE_DOUBLE_LIKE_CPP(7.0420557077594588669468784357561207962098443483187940792729600000e+59);
DOES_PARSE_DOUBLE_LIKE_CPP(7.0420557077594588669468784357561207962098443483187940792729600000e+59);
DOES_PARSE_DOUBLE_LIKE_CPP(1.7339253062092163730578609458683877051596800000000000000000000000e+42);
DOES_PARSE_DOUBLE_LIKE_CPP(2.0972622234386619214559824785284023792871122537545728000000000000e+52);
DOES_PARSE_DOUBLE_LIKE_CPP(1.0001803374372191849407179462120053338028379051879898808320000000e+57);
DOES_PARSE_DOUBLE_LIKE_CPP(1.8607245283054342363818436991534856973992070520151142825984000000e+58);
DOES_PARSE_DOUBLE_LIKE_CPP(1.9189205311132686907264385602245237137907390376574976000000000000e+52);
DOES_PARSE_DOUBLE_LIKE_CPP(2.8184483231688951563253238886553506793085187889855201280000000000e+54);
DOES_PARSE_DOUBLE_LIKE_CPP(1.7664960224650106892054063261344555646357024359107788800000000000e+53);
DOES_PARSE_DOUBLE_LIKE_CPP(2.1470977154320536489471030463761883783915110400000000000000000000e+45);
DOES_PARSE_DOUBLE_LIKE_CPP(4.4900312744003159009338275160799498340862630046359789166919680000e+61);
DOES_PARSE_DOUBLE_LIKE_CPP(2.2222222222223e-322);
DOES_PARSE_DOUBLE_LIKE_CPP(860228122.6654514319E+90);
DOES_PARSE_DOUBLE_LIKE_CPP(4.9406564584124653e-324);
DOES_PARSE_DOUBLE_LIKE_CPP(4.9406564584124654e-324);
DOES_PARSE_DOUBLE_LIKE_CPP(2.2250738585072009e-308);
DOES_PARSE_DOUBLE_LIKE_CPP(2.2250738585072014e-308);
DOES_PARSE_DOUBLE_LIKE_CPP(1.7976931348623157e308);
DOES_PARSE_DOUBLE_LIKE_CPP(1.7976931348623158e308);
DOES_PARSE_DOUBLE_LIKE_CPP(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375);
DOES_PARSE_DOUBLE_LIKE_CPP(0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(9007199254740993.);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(9007199254740993.1);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(9007199254740993.0000000000000000000000000000000000000000000000000);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(9007199254740993.0000000000000000000000000000000000000000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(9007199254740993.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(9007199254740993.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(9007199254740993.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009007199254740993.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009007199254740993.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(1.17549414062751785924617589866280818433124586473279624003138594271817467598606476997247227700427174568176269531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-38);
DOES_PARSE_DOUBLE_LIKE_CPP(179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.);
DOES_PARSE_DOUBLE_LIKE_CPP(179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858369.);
DOES_PARSE_DOUBLE_LIKE_CPP(179769313486231579999999999999999999999999999999999999999917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.);
DOES_PARSE_DOUBLE_LIKE_CPP(179769313486231580000000000000000000000000000000000000000000000000057260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.);
DOES_PARSE_DOUBLE_LIKE_CPP(179769313486231580790000000000000000000000000000000000000000000000057260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.);
DOES_PARSE_DOUBLE_LIKE_CPP(179769313486231580793700000000000000000000000000000000000000000000057260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.);
DOES_PARSE_DOUBLE_LIKE_CPP(179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(7.2057594037927933e+16);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(7.3177701707893310e+15);
DOES_PARSE_DOUBLE_LIKE_CPP(4.2523296908380055e94);
DOES_PARSE_DOUBLE_LIKE_CPP(4.2523296908380052e94);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(6865415254.161212);
DOES_PARSE_DOUBLE_LIKE_CPP(4.9406564584124654416987984e-324);
DOES_PARSE_DOUBLE_LIKE_CPP(4.94065645841246544177987491e-324);
DOES_PARSE_DOUBLE_LIKE_CPP(1.4821969375237396325297063786046641170951794078429742932767570475020265218106262555958995090849079771393896940863371531927799701310678193891963243880323456343789021395709342135835374515035469463110661559081709961921691500191622274606949531619374201918195088454200951461561942223787156967735130799756700603045611186809318747958358147744773659879163696332033824403891299986257959682272412496899735742714436070441803404780657158346504044105794804160581370804321322475109996680534260007162497295808277148680375104180318034518509429259235026831954987743714947574192329127781743623968254334611203409098600941053918033152755376981653597394514673304353113588214501752867512169200796980994429823492617107911270837728302633695687262616047519259154796600341796875e-323);
DOES_PARSE_DOUBLE_LIKE_CPP(0.14821969375237396325297063786046641170951794078429742932767570475020265218106262555958995090849079771393896940863371531927799701310678193891963243880323456343789021395709342135835374515035469463110661559081709961921691500191622274606949531619374201918195088454200951461561942223787156967735130799756700603045611186809318747958358147744773659879163696332033824403891299986257959682272412496899735742714436070441803404780657158346504044105794804160581370804321322475109996680534260007162497295808277148680375104180318034518509429259235026831954987743714947574192329127781743623968254334611203409098600941053918033152755376981653597394514673304353113588214501752867512169200796980994429823492617107911270837728302633695687262616047519259154796600341796875e-322);
DOES_PARSE_DOUBLE_LIKE_CPP(0000000000000000000000000000.14821969375237396325297063786046641170951794078429742932767570475020265218106262555958995090849079771393896940863371531927799701310678193891963243880323456343789021395709342135835374515035469463110661559081709961921691500191622274606949531619374201918195088454200951461561942223787156967735130799756700603045611186809318747958358147744773659879163696332033824403891299986257959682272412496899735742714436070441803404780657158346504044105794804160581370804321322475109996680534260007162497295808277148680375104180318034518509429259235026831954987743714947574192329127781743623968254334611203409098600941053918033152755376981653597394514673304353113588214501752867512169200796980994429823492617107911270837728302633695687262616047519259154796600341796875e-322);
DOES_PARSE_DOUBLE_LIKE_CPP(0000000000000000000000000000.000000000014821969375237396325297063786046641170951794078429742932767570475020265218106262555958995090849079771393896940863371531927799701310678193891963243880323456343789021395709342135835374515035469463110661559081709961921691500191622274606949531619374201918195088454200951461561942223787156967735130799756700603045611186809318747958358147744773659879163696332033824403891299986257959682272412496899735742714436070441803404780657158346504044105794804160581370804321322475109996680534260007162497295808277148680375104180318034518509429259235026831954987743714947574192329127781743623968254334611203409098600941053918033152755376981653597394514673304353113588214501752867512169200796980994429823492617107911270837728302633695687262616047519259154796600341796875e-312);
DOES_PARSE_DOUBLE_LIKE_CPP(6.422853395936205074295394307286877840745777433986221937532613872508781594512713774248897872701267900937355341040794330502046537234627217353184072348140164415641909271474048258861995623182036767347953342268740983499399650083036318996344797035062154164551204996820412300010174963641101352685223346561236927986431514284038124115288530689401919280970935077214657241686229994045115862318045415323218821842922297191448142071618101950151752445844415136251927e-323);
DOES_PARSE_DOUBLE_LIKE_CPP(6.522853395936205074295394307286877840745777433986221937532613872508781594512713774248897872701267900937355341040794330502046537234627217353184072348140164415641909271474048258861995623182036767347953342268740983499399650083036318996344797035062154164551204996820412300010174963641101352685223346561236927986431514284038124115288530689401919280970935077214657241686229994045115862318045415323218821842922297191448142071618101950151752445844415136251927e-323);
DOES_PARSE_DOUBLE_LIKE_CPP(7.522853395936205074295394307286877840745777433986221937532613872508781594512713774248897872701267900937355341040794330502046537234627217353184072348140164415641909271474048258861995623182036767347953342268740983499399650083036318996344797035062154164551204996820412300010174963641101352685223346561236927986431514284038124115288530689401919280970935077214657241686229994045115862318045415323218821842922297191448142071618101950151752445844415136251927e-323);
DOES_PARSE_DOUBLE_LIKE_CPP(7.5228498395936205074295394307286877840745777433986221937532613872508781594512713774248897872701267900937355341040794330502046537234627217353184072348140164415641909271474048258861995623182036767347953342268740983499399650083036318996344797035062154164551204996820412300010174963641101352685223346561236927986431514284038124115288530689401919280970935077214657241686229994045115862318045415323218821842922297191448142071618101950151752445844415136251927e-323);
DOES_PARSE_DOUBLE_LIKE_CPP(0.5228498395936205074295394307286877840745777433986221937532613872508781594512713774248897872701267900937355341040794330502046537234627217353184072348140164415641909271474048258861995623182036767347953342268740983499399650083036318996344797035062154164551204996820412300010174963641101352685223346561236927986431514284038124115288530689401919280970935077214657241686229994045115862318045415323218821842922297191448142071618101950151752445844415136251927e-323);
// actual interesting (non 19+ digit) failures from current strtod'
DOES_PARSE_DOUBLE_LIKE_CPP(1e126);
DOES_PARSE_DOUBLE_LIKE_CPP(1e210);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(358416272e-33);
// FIXME: These are different in 32 bit, since that will be removed some time (soon?)
// we can remove this guard at that point.
#if not defined(__serenity__) || not ARCH(I386)
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(89255e-22);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(8925.5e-21);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(8.9255e-18);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(8925500e-24);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(89256e-22);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(89254e-22);
#endif
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(3.518437208883201171875e13);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(62.5364939768271845828);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(8.10109172351e-10);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(1.50000000000000011102230246251565404236316680908203125);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(9007199254740991.4999999999999999999999999999999995);
DOES_PARSE_DOUBLE_LIKE_CPP(7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375001e-324);
DOES_PARSE_DOUBLE_LIKE_CPP(7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984375e-324);
DOES_PARSE_DOUBLE_LIKE_CPP(7.4109846876186981626485318930233205854758970392148714663837852375101326090531312779794975454245398856969484704316857659638998506553390969459816219401617281718945106978546710679176872575177347315553307795408549809608457500958111373034747658096871009590975442271004757307809711118935784838675653998783503015228055934046593739791790738723868299395818481660169122019456499931289798411362062484498678713572180352209017023903285791732520220528974020802906854021606612375549983402671300035812486479041385743401875520901590172592547146296175134159774938718574737870961645638908718119841271673056017045493004705269590165763776884908267986972573366521765567941072508764337560846003984904972149117463085539556354188641513168478436313080237596295773983001708984374999e-324);
DOES_PARSE_DOUBLE_LIKE_CPP(2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125001e-324);
DOES_PARSE_DOUBLE_LIKE_CPP(2.22507385850720138309e-308);
DOES_PARSE_DOUBLE_LIKE_CPP(1e55);
DOES_PARSE_DOUBLE_LIKE_CPP(1e300);
DOES_PARSE_DOUBLE_LIKE_CPP(1e301);
DOES_PARSE_DOUBLE_LIKE_CPP(1e302);
DOES_PARSE_DOUBLE_LIKE_CPP(1e303);
DOES_PARSE_DOUBLE_LIKE_CPP(1e304);
DOES_PARSE_DOUBLE_LIKE_CPP(1e305);
DOES_PARSE_DOUBLE_LIKE_CPP(1e299);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(3.4028235E38);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(4e31);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(9007199254740991.);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(7.038531E-26);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(46116538.);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(20040229.);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(9771305410219737088.);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(1146.);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(7.0064923216240854e-46);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(1.1877630352973938);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(2.1665680640000002384185791015625e9);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(8.589934335999999523162841796875e+09);
DOES_PARSE_FLOAT_AND_DOUBLE_LIKE_CPP(0.09289376810193062);
#define DOES_PARSE_INT_LIKE_VALUE_LIKE_CPP(value) \
do { \
EXPECT_EQ(static_cast<double>(value##.), parse_complete_double(#value##sv)); \
EXPECT_EQ(-static_cast<double>(value##.), parse_complete_double("-" #value##sv)); \
} while (false)
DOES_PARSE_INT_LIKE_VALUE_LIKE_CPP(0);
DOES_PARSE_INT_LIKE_VALUE_LIKE_CPP(1);
DOES_PARSE_INT_LIKE_VALUE_LIKE_CPP(2);
DOES_PARSE_INT_LIKE_VALUE_LIKE_CPP(20);
DOES_PARSE_INT_LIKE_VALUE_LIKE_CPP(200);
DOES_PARSE_INT_LIKE_VALUE_LIKE_CPP(234);
DOES_PARSE_INT_LIKE_VALUE_LIKE_CPP(8419841);
EXPECT_EQ(67677557565221539913., parse_complete_double("67677557565221539913"sv));
EXPECT_EQ(0., parse_complete_double("2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125e-324"sv));
EXPECT_EQ(0., parse_complete_double("2.4703282292062327208828439643411068618252990130716238221279284125033775363510437593264991818081799618989828234772285886546332835517796989819938739800539093906315035659515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001585769269903706311928279558551332927834338409351978015531246597263579574622766465272827220056374006485499977096599470454020828166226237857393450736339007967761930577506740176324673600968951340535537458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623653881879636239373280423891018672348497668235089863388587925628302755995657524455507255189313690836254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328124999e-324"sv));
#define EXPECT_TO_PARSE_TO_VALUE_EQUAL_TO(expected_val, str) \
EXPECT_EQ(bit_cast<u64>(expected_val), bit_cast<u64>(parse_complete_double(str##sv)));
EXPECT_TO_PARSE_TO_VALUE_EQUAL_TO(0., "1e-324");
EXPECT_TO_PARSE_TO_VALUE_EQUAL_TO(-0., "-1e-324");
EXPECT_TO_PARSE_TO_VALUE_EQUAL_TO(.09289376810193062, "+.09289376810193062");
EXPECT_TO_PARSE_TO_VALUE_EQUAL_TO(-.09289376810193062, "-.09289376810193062");
EXPECT_TO_PARSE_TO_VALUE_EQUAL_TO(0., "+.0e10");
EXPECT_TO_PARSE_TO_VALUE_EQUAL_TO(-0., "-.0e10");
#define EXPECT_TO_PARSE_TO_INFINITY(str) \
EXPECT_EQ(__builtin_huge_val(), parse_complete_double(str##sv)); \
EXPECT_EQ(__builtin_huge_val(), parse_complete_double("+" str##sv)); \
EXPECT_EQ(-__builtin_huge_val(), parse_complete_double("-" str##sv)); \
EXPECT_EQ(static_cast<float>(__builtin_huge_valf()), parse_complete_float(str##sv)); \
EXPECT_EQ(static_cast<float>(__builtin_huge_valf()), parse_complete_float("+" str##sv)); \
EXPECT_EQ(static_cast<float>(-__builtin_huge_valf()), parse_complete_float("-" str##sv))
EXPECT_TO_PARSE_TO_INFINITY("123.456e789");
EXPECT_TO_PARSE_TO_INFINITY("123456.456789e789");
EXPECT_TO_PARSE_TO_INFINITY("1438456663141390273526118207642235581183227845246331231162636653790368152091394196930365828634687637948157940776599182791387527135353034738357134110310609455693900824193549772792016543182680519740580354365467985440183598701312257624545562331397018329928613196125590274187720073914818062530830316533158098624984118889298281371812288789537310599037529113415438738954894752124724983067241108764488346454376699018673078404751121414804937224240805993123816932326223683090770561597570457793932985826162604255884529134126396282202126526253389383421806727954588525596114379801269094096329805054803089299736996870951258573010877404407451953846698609198213926882692078557033228265259305481198526059813164469187586693257335779522020407645498684263339921905227556616698129967412891282231685504660671277927198290009824680186319750978665734576683784255802269708917361719466043175201158849097881370477111850171579869056016061666173029059588433776015644439705050377554277696143928278093453792803846252715966016733222646442382892123940052441346822429721593884378212558701004356924243030059517489346646577724622498919752597382095222500311124181823512251071356181769376577651390028297796156208815375089159128394945710515861334486267101797497111125909272505194792870889617179758703442608016143343262159998149700606597792535574457560429226974273443630323818747730771316763398572110874959981923732463076884528677392654150010269822239401993427482376513231389212353583573566376915572650916866553612366187378959554983566712767093372906030188976220169058025354973622211666504549316958271880975697143546564469806791358707318873075708383345004090151974068325838177531266954177406661392229801349994695941509935655355652985723782153570084089560139142231.738475042362596875449154552392299548947138162081694168675340677843807613129780449323363759027012972466987370921816813162658754726545121090545507240267000456594786540949605260722461937870630634874991729398208026467698131898691830012167897399682179601734569071423681e-733");
EXPECT_TO_PARSE_TO_INFINITY("3e182947912346759234");
EXPECT_TO_PARSE_TO_INFINITY("3e70000000000000");
EXPECT_TO_PARSE_TO_INFINITY("3e70000000000");
EXPECT_TO_PARSE_TO_INFINITY("3e70000000");
EXPECT_TO_PARSE_TO_INFINITY("1e681");
EXPECT_TO_PARSE_TO_INFINITY("7e312");
EXPECT_TO_PARSE_TO_INFINITY("184467440737095516151234567890e2147483639");
}
TEST_CASE(partial_parse_stops_at_right_spot)
{
#define EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS(string_value, double_value, chars_parsed) \
do { \
StringView view = string_value##sv; \
char const* start = view.characters_without_null_termination(); \
auto result = parse_first_floating_point<double>(start, start + view.length()); \
EXPECT(result.error == AK::FloatingPointError::None); \
EXPECT_EQ(bit_cast<u64>(result.value), bit_cast<u64>(static_cast<double>(double_value))); \
EXPECT_EQ(result.end_ptr - start, chars_parsed); \
} while (false)
EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS("0x", 0., 1);
EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS("0e", 0., 1);
EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS("0e+", 0., 1);
EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS("0e1", 0., 3);
EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS("0beef", 0., 1);
EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS("0p123", 0., 1);
EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS("0e1", 0., 3);
EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS("0e1abc", 0., 3);
EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS("0e1e1", 0., 3);
EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS("0e1+", 0., 3);
EXPECT_PARSE_TO_VALUE_AND_CONSUME_CHARS("0e-+1", 0., 1);
}
TEST_CASE(invalid_parse)
{
#define EXPECT_PARSE_TO_FAIL(string_value) \
do { \
StringView view = string_value##sv; \
char const* start = view.characters_without_null_termination(); \
auto result = parse_first_floating_point<double>(start, start + view.length()); \
EXPECT(result.error == AK::FloatingPointError::NoOrInvalidInput); \
} while (false)
EXPECT_PARSE_TO_FAIL("");
EXPECT_PARSE_TO_FAIL("e");
EXPECT_PARSE_TO_FAIL(".");
EXPECT_PARSE_TO_FAIL("-.");
EXPECT_PARSE_TO_FAIL("+.");
EXPECT_PARSE_TO_FAIL(".e");
EXPECT_PARSE_TO_FAIL("-.e");
EXPECT_PARSE_TO_FAIL("+.e");
EXPECT_PARSE_TO_FAIL(".e1");
EXPECT_PARSE_TO_FAIL("-.e1");
EXPECT_PARSE_TO_FAIL("+.e1");
EXPECT_PARSE_TO_FAIL("++2");
EXPECT_PARSE_TO_FAIL("++1");
EXPECT_PARSE_TO_FAIL("++0");
EXPECT_PARSE_TO_FAIL("++2e1");
EXPECT_PARSE_TO_FAIL("++1e1");
EXPECT_PARSE_TO_FAIL("++0e1");
#define EXPECT_MULTI_SIGNS_TO_FAIL(base_string) \
EXPECT_PARSE_TO_FAIL("++" base_string); \
EXPECT_PARSE_TO_FAIL("--" base_string); \
EXPECT_PARSE_TO_FAIL("+-" base_string); \
EXPECT_PARSE_TO_FAIL("-+" base_string)
EXPECT_MULTI_SIGNS_TO_FAIL("1");
EXPECT_MULTI_SIGNS_TO_FAIL("1.");
EXPECT_MULTI_SIGNS_TO_FAIL("1e1");
EXPECT_MULTI_SIGNS_TO_FAIL("1.e1");
EXPECT_MULTI_SIGNS_TO_FAIL("1.0e1");
EXPECT_MULTI_SIGNS_TO_FAIL("1.0e+1");
EXPECT_MULTI_SIGNS_TO_FAIL("1.0e-1");
}
TEST_CASE(detect_out_of_range_values)
{
#define EXPECT_PARSE_TO_HAVE_ERROR(string_value, error_value) \
do { \
StringView view = string_value##sv; \
char const* start = view.characters_without_null_termination(); \
auto result = parse_first_floating_point<double>(start, start + view.length()); \
EXPECT(result.error == error_value); \
EXPECT(result.end_ptr == start + view.length()); \
} while (false)
EXPECT_PARSE_TO_HAVE_ERROR("10e-10000", AK::FloatingPointError::RoundedDownToZero);
EXPECT_PARSE_TO_HAVE_ERROR("-10e-10000", AK::FloatingPointError::RoundedDownToZero);
EXPECT_PARSE_TO_HAVE_ERROR("10e10000", AK::FloatingPointError::OutOfRange);
EXPECT_PARSE_TO_HAVE_ERROR("-10e10000", AK::FloatingPointError::OutOfRange);
}
static bool parse_completely_passes(StringView view)
{
char const* start = view.characters_without_null_termination();
return parse_floating_point_completely<double>(start, start + view.length()).has_value();
}
TEST_CASE(parse_completely_must_be_just_floating_point)
{
#define EXPECT_PARSE_COMPLETELY_TO_FAIL(value) \
EXPECT(!parse_completely_passes(value##sv))
EXPECT_PARSE_COMPLETELY_TO_FAIL("");
EXPECT_PARSE_COMPLETELY_TO_FAIL("-");
EXPECT_PARSE_COMPLETELY_TO_FAIL("+");
EXPECT_PARSE_COMPLETELY_TO_FAIL("++1");
EXPECT_PARSE_COMPLETELY_TO_FAIL("+-1");
EXPECT_PARSE_COMPLETELY_TO_FAIL("-+1");
EXPECT_PARSE_COMPLETELY_TO_FAIL("--1");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1 ");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1. ");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1e ");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1.e ");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1.e123 ");
EXPECT_PARSE_COMPLETELY_TO_FAIL("-1 ");
EXPECT_PARSE_COMPLETELY_TO_FAIL("-1. ");
EXPECT_PARSE_COMPLETELY_TO_FAIL("-1e ");
EXPECT_PARSE_COMPLETELY_TO_FAIL("-1.e ");
EXPECT_PARSE_COMPLETELY_TO_FAIL("-1.e123 ");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1A");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1.C");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1e*");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1.e(");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1.e123]");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1.e123&");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1.e123 ");
EXPECT_PARSE_COMPLETELY_TO_FAIL(":1234567890");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1:234567890");
EXPECT_PARSE_COMPLETELY_TO_FAIL("12:34567890");
EXPECT_PARSE_COMPLETELY_TO_FAIL("123:4567890");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1234:567890");
EXPECT_PARSE_COMPLETELY_TO_FAIL("12345:67890");
EXPECT_PARSE_COMPLETELY_TO_FAIL("123456:7890");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1234567:890");
EXPECT_PARSE_COMPLETELY_TO_FAIL("12345678:90");
EXPECT_PARSE_COMPLETELY_TO_FAIL("123456789:0");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1234567890:");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1;234567890");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1234567;890");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1=234567890");
EXPECT_PARSE_COMPLETELY_TO_FAIL("1234567=890");
}