| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "absl/strings/charconv.h" |
|
|
| #include <cfloat> |
| #include <cmath> |
| #include <cstdlib> |
| #include <functional> |
| #include <limits> |
| #include <string> |
| #include <system_error> |
|
|
| #include "gtest/gtest.h" |
| #include "absl/strings/internal/pow10_helper.h" |
| #include "absl/strings/str_cat.h" |
| #include "absl/strings/str_format.h" |
| #include "absl/strings/string_view.h" |
|
|
| #ifdef _MSC_FULL_VER |
| #define ABSL_COMPILER_DOES_EXACT_ROUNDING 0 |
| #define ABSL_STRTOD_HANDLES_NAN_CORRECTLY 0 |
| #else |
| #define ABSL_COMPILER_DOES_EXACT_ROUNDING 1 |
| #define ABSL_STRTOD_HANDLES_NAN_CORRECTLY 1 |
| #endif |
|
|
| namespace { |
|
|
| using absl::strings_internal::Pow10; |
|
|
| #if ABSL_COMPILER_DOES_EXACT_ROUNDING |
|
|
| |
| |
| void TestDoubleParse(absl::string_view str, double expected_number) { |
| SCOPED_TRACE(str); |
| double actual_number = 0.0; |
| absl::from_chars_result result = |
| absl::from_chars(str.data(), str.data() + str.length(), actual_number); |
| EXPECT_EQ(result.ec, std::errc()); |
| EXPECT_EQ(result.ptr, str.data() + str.length()); |
| EXPECT_EQ(actual_number, expected_number); |
| } |
|
|
| void TestFloatParse(absl::string_view str, float expected_number) { |
| SCOPED_TRACE(str); |
| float actual_number = 0.0; |
| absl::from_chars_result result = |
| absl::from_chars(str.data(), str.data() + str.length(), actual_number); |
| EXPECT_EQ(result.ec, std::errc()); |
| EXPECT_EQ(result.ptr, str.data() + str.length()); |
| EXPECT_EQ(actual_number, expected_number); |
| } |
|
|
| |
| |
| |
| |
| |
| #define FROM_CHARS_TEST_DOUBLE(number) \ |
| { \ |
| TestDoubleParse(#number, number); \ |
| TestDoubleParse("-" #number, -number); \ |
| } |
|
|
| #define FROM_CHARS_TEST_FLOAT(number) \ |
| { \ |
| TestFloatParse(#number, number##f); \ |
| TestFloatParse("-" #number, -number##f); \ |
| } |
|
|
| TEST(FromChars, NearRoundingCases) { |
| |
| |
|
|
| |
| |
| FROM_CHARS_TEST_DOUBLE(5.e125); |
| FROM_CHARS_TEST_DOUBLE(69.e267); |
| FROM_CHARS_TEST_DOUBLE(999.e-026); |
| FROM_CHARS_TEST_DOUBLE(7861.e-034); |
| FROM_CHARS_TEST_DOUBLE(75569.e-254); |
| FROM_CHARS_TEST_DOUBLE(928609.e-261); |
| FROM_CHARS_TEST_DOUBLE(9210917.e080); |
| FROM_CHARS_TEST_DOUBLE(84863171.e114); |
| FROM_CHARS_TEST_DOUBLE(653777767.e273); |
| FROM_CHARS_TEST_DOUBLE(5232604057.e-298); |
| FROM_CHARS_TEST_DOUBLE(27235667517.e-109); |
| FROM_CHARS_TEST_DOUBLE(653532977297.e-123); |
| FROM_CHARS_TEST_DOUBLE(3142213164987.e-294); |
| FROM_CHARS_TEST_DOUBLE(46202199371337.e-072); |
| FROM_CHARS_TEST_DOUBLE(231010996856685.e-073); |
| FROM_CHARS_TEST_DOUBLE(9324754620109615.e212); |
| FROM_CHARS_TEST_DOUBLE(78459735791271921.e049); |
| FROM_CHARS_TEST_DOUBLE(272104041512242479.e200); |
| FROM_CHARS_TEST_DOUBLE(6802601037806061975.e198); |
| FROM_CHARS_TEST_DOUBLE(20505426358836677347.e-221); |
| FROM_CHARS_TEST_DOUBLE(836168422905420598437.e-234); |
| FROM_CHARS_TEST_DOUBLE(4891559871276714924261.e222); |
| FROM_CHARS_TEST_FLOAT(5.e-20); |
| FROM_CHARS_TEST_FLOAT(67.e14); |
| FROM_CHARS_TEST_FLOAT(985.e15); |
| FROM_CHARS_TEST_FLOAT(7693.e-42); |
| FROM_CHARS_TEST_FLOAT(55895.e-16); |
| FROM_CHARS_TEST_FLOAT(996622.e-44); |
| FROM_CHARS_TEST_FLOAT(7038531.e-32); |
| FROM_CHARS_TEST_FLOAT(60419369.e-46); |
| FROM_CHARS_TEST_FLOAT(702990899.e-20); |
| FROM_CHARS_TEST_FLOAT(6930161142.e-48); |
| FROM_CHARS_TEST_FLOAT(25933168707.e-13); |
| FROM_CHARS_TEST_FLOAT(596428896559.e20); |
|
|
| |
| FROM_CHARS_TEST_DOUBLE(9.e-265); |
| FROM_CHARS_TEST_DOUBLE(85.e-037); |
| FROM_CHARS_TEST_DOUBLE(623.e100); |
| FROM_CHARS_TEST_DOUBLE(3571.e263); |
| FROM_CHARS_TEST_DOUBLE(81661.e153); |
| FROM_CHARS_TEST_DOUBLE(920657.e-023); |
| FROM_CHARS_TEST_DOUBLE(4603285.e-024); |
| FROM_CHARS_TEST_DOUBLE(87575437.e-309); |
| FROM_CHARS_TEST_DOUBLE(245540327.e122); |
| FROM_CHARS_TEST_DOUBLE(6138508175.e120); |
| FROM_CHARS_TEST_DOUBLE(83356057653.e193); |
| FROM_CHARS_TEST_DOUBLE(619534293513.e124); |
| FROM_CHARS_TEST_DOUBLE(2335141086879.e218); |
| FROM_CHARS_TEST_DOUBLE(36167929443327.e-159); |
| FROM_CHARS_TEST_DOUBLE(609610927149051.e-255); |
| FROM_CHARS_TEST_DOUBLE(3743626360493413.e-165); |
| FROM_CHARS_TEST_DOUBLE(94080055902682397.e-242); |
| FROM_CHARS_TEST_DOUBLE(899810892172646163.e283); |
| FROM_CHARS_TEST_DOUBLE(7120190517612959703.e120); |
| FROM_CHARS_TEST_DOUBLE(25188282901709339043.e-252); |
| FROM_CHARS_TEST_DOUBLE(308984926168550152811.e-052); |
| FROM_CHARS_TEST_DOUBLE(6372891218502368041059.e064); |
| FROM_CHARS_TEST_FLOAT(3.e-23); |
| FROM_CHARS_TEST_FLOAT(57.e18); |
| FROM_CHARS_TEST_FLOAT(789.e-35); |
| FROM_CHARS_TEST_FLOAT(2539.e-18); |
| FROM_CHARS_TEST_FLOAT(76173.e28); |
| FROM_CHARS_TEST_FLOAT(887745.e-11); |
| FROM_CHARS_TEST_FLOAT(5382571.e-37); |
| FROM_CHARS_TEST_FLOAT(82381273.e-35); |
| FROM_CHARS_TEST_FLOAT(750486563.e-38); |
| FROM_CHARS_TEST_FLOAT(3752432815.e-39); |
| FROM_CHARS_TEST_FLOAT(75224575729.e-45); |
| FROM_CHARS_TEST_FLOAT(459926601011.e15); |
| } |
|
|
| #undef FROM_CHARS_TEST_DOUBLE |
| #undef FROM_CHARS_TEST_FLOAT |
| #endif |
|
|
| float ToFloat(absl::string_view s) { |
| float f; |
| absl::from_chars(s.data(), s.data() + s.size(), f); |
| return f; |
| } |
|
|
| double ToDouble(absl::string_view s) { |
| double d; |
| absl::from_chars(s.data(), s.data() + s.size(), d); |
| return d; |
| } |
|
|
| |
| |
| |
| |
| TEST(FromChars, NearRoundingCasesExplicit) { |
| EXPECT_EQ(ToDouble("5.e125"), ldexp(6653062250012735, 365)); |
| EXPECT_EQ(ToDouble("69.e267"), ldexp(4705683757438170, 841)); |
| EXPECT_EQ(ToDouble("999.e-026"), ldexp(6798841691080350, -129)); |
| EXPECT_EQ(ToDouble("7861.e-034"), ldexp(8975675289889240, -153)); |
| EXPECT_EQ(ToDouble("75569.e-254"), ldexp(6091718967192243, -880)); |
| EXPECT_EQ(ToDouble("928609.e-261"), ldexp(7849264900213743, -900)); |
| EXPECT_EQ(ToDouble("9210917.e080"), ldexp(8341110837370930, 236)); |
| EXPECT_EQ(ToDouble("84863171.e114"), ldexp(4625202867375927, 353)); |
| EXPECT_EQ(ToDouble("653777767.e273"), ldexp(5068902999763073, 884)); |
| EXPECT_EQ(ToDouble("5232604057.e-298"), ldexp(5741343011915040, -1010)); |
| EXPECT_EQ(ToDouble("27235667517.e-109"), ldexp(6707124626673586, -380)); |
| EXPECT_EQ(ToDouble("653532977297.e-123"), ldexp(7078246407265384, -422)); |
| EXPECT_EQ(ToDouble("3142213164987.e-294"), ldexp(8219991337640559, -988)); |
| EXPECT_EQ(ToDouble("46202199371337.e-072"), ldexp(5224462102115359, -246)); |
| EXPECT_EQ(ToDouble("231010996856685.e-073"), ldexp(5224462102115359, -247)); |
| EXPECT_EQ(ToDouble("9324754620109615.e212"), ldexp(5539753864394442, 705)); |
| EXPECT_EQ(ToDouble("78459735791271921.e049"), ldexp(8388176519442766, 166)); |
| EXPECT_EQ(ToDouble("272104041512242479.e200"), ldexp(5554409530847367, 670)); |
| EXPECT_EQ(ToDouble("6802601037806061975.e198"), ldexp(5554409530847367, 668)); |
| EXPECT_EQ(ToDouble("20505426358836677347.e-221"), |
| ldexp(4524032052079546, -722)); |
| EXPECT_EQ(ToDouble("836168422905420598437.e-234"), |
| ldexp(5070963299887562, -760)); |
| EXPECT_EQ(ToDouble("4891559871276714924261.e222"), |
| ldexp(6452687840519111, 757)); |
| EXPECT_EQ(ToFloat("5.e-20"), ldexpf(15474250, -88)); |
| EXPECT_EQ(ToFloat("67.e14"), ldexpf(12479722, 29)); |
| EXPECT_EQ(ToFloat("985.e15"), ldexpf(14333636, 36)); |
| EXPECT_EQ(ToFloat("7693.e-42"), ldexpf(10979816, -150)); |
| EXPECT_EQ(ToFloat("55895.e-16"), ldexpf(12888509, -61)); |
| EXPECT_EQ(ToFloat("996622.e-44"), ldexpf(14224264, -150)); |
| EXPECT_EQ(ToFloat("7038531.e-32"), ldexpf(11420669, -107)); |
| EXPECT_EQ(ToFloat("60419369.e-46"), ldexpf(8623340, -150)); |
| EXPECT_EQ(ToFloat("702990899.e-20"), ldexpf(16209866, -61)); |
| EXPECT_EQ(ToFloat("6930161142.e-48"), ldexpf(9891056, -150)); |
| EXPECT_EQ(ToFloat("25933168707.e-13"), ldexpf(11138211, -32)); |
| EXPECT_EQ(ToFloat("596428896559.e20"), ldexpf(12333860, 82)); |
|
|
|
|
| EXPECT_EQ(ToDouble("9.e-265"), ldexp(8168427841980010, -930)); |
| EXPECT_EQ(ToDouble("85.e-037"), ldexp(6360455125664090, -169)); |
| EXPECT_EQ(ToDouble("623.e100"), ldexp(6263531988747231, 289)); |
| EXPECT_EQ(ToDouble("3571.e263"), ldexp(6234526311072170, 833)); |
| EXPECT_EQ(ToDouble("81661.e153"), ldexp(6696636728760206, 472)); |
| EXPECT_EQ(ToDouble("920657.e-023"), ldexp(5975405561110124, -109)); |
| EXPECT_EQ(ToDouble("4603285.e-024"), ldexp(5975405561110124, -110)); |
| EXPECT_EQ(ToDouble("87575437.e-309"), ldexp(8452160731874668, -1053)); |
| EXPECT_EQ(ToDouble("245540327.e122"), ldexp(4985336549131723, 381)); |
| EXPECT_EQ(ToDouble("6138508175.e120"), ldexp(4985336549131723, 379)); |
| EXPECT_EQ(ToDouble("83356057653.e193"), ldexp(5986732817132056, 625)); |
| EXPECT_EQ(ToDouble("619534293513.e124"), ldexp(4798406992060657, 399)); |
| EXPECT_EQ(ToDouble("2335141086879.e218"), ldexp(5419088166961646, 713)); |
| EXPECT_EQ(ToDouble("36167929443327.e-159"), ldexp(8135819834632444, -536)); |
| EXPECT_EQ(ToDouble("609610927149051.e-255"), ldexp(4576664294594737, -850)); |
| EXPECT_EQ(ToDouble("3743626360493413.e-165"), ldexp(6898586531774201, -549)); |
| EXPECT_EQ(ToDouble("94080055902682397.e-242"), ldexp(6273271706052298, -800)); |
| EXPECT_EQ(ToDouble("899810892172646163.e283"), ldexp(7563892574477827, 947)); |
| EXPECT_EQ(ToDouble("7120190517612959703.e120"), ldexp(5385467232557565, 409)); |
| EXPECT_EQ(ToDouble("25188282901709339043.e-252"), |
| ldexp(5635662608542340, -825)); |
| EXPECT_EQ(ToDouble("308984926168550152811.e-052"), |
| ldexp(5644774693823803, -157)); |
| EXPECT_EQ(ToDouble("6372891218502368041059.e064"), |
| ldexp(4616868614322430, 233)); |
|
|
| EXPECT_EQ(ToFloat("3.e-23"), ldexpf(9507380, -98)); |
| EXPECT_EQ(ToFloat("57.e18"), ldexpf(12960300, 42)); |
| EXPECT_EQ(ToFloat("789.e-35"), ldexpf(10739312, -130)); |
| EXPECT_EQ(ToFloat("2539.e-18"), ldexpf(11990089, -72)); |
| EXPECT_EQ(ToFloat("76173.e28"), ldexpf(9845130, 86)); |
| EXPECT_EQ(ToFloat("887745.e-11"), ldexpf(9760860, -40)); |
| EXPECT_EQ(ToFloat("5382571.e-37"), ldexpf(11447463, -124)); |
| EXPECT_EQ(ToFloat("82381273.e-35"), ldexpf(8554961, -113)); |
| EXPECT_EQ(ToFloat("750486563.e-38"), ldexpf(9975678, -120)); |
| EXPECT_EQ(ToFloat("3752432815.e-39"), ldexpf(9975678, -121)); |
| EXPECT_EQ(ToFloat("75224575729.e-45"), ldexpf(13105970, -137)); |
| EXPECT_EQ(ToFloat("459926601011.e15"), ldexpf(12466336, 65)); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| template <typename FloatType> |
| void TestHalfwayValue(const std::string& mantissa, int exponent, |
| FloatType expected_low, FloatType expected_high, |
| FloatType expected_half) { |
| std::string low_rep = mantissa; |
| low_rep[low_rep.size() - 1] -= 1; |
| absl::StrAppend(&low_rep, std::string(1000, '9'), "e", exponent); |
|
|
| FloatType actual_low = 0; |
| absl::from_chars(low_rep.data(), low_rep.data() + low_rep.size(), actual_low); |
| EXPECT_EQ(expected_low, actual_low); |
|
|
| std::string high_rep = |
| absl::StrCat(mantissa, std::string(1000, '0'), "1e", exponent); |
| FloatType actual_high = 0; |
| absl::from_chars(high_rep.data(), high_rep.data() + high_rep.size(), |
| actual_high); |
| EXPECT_EQ(expected_high, actual_high); |
|
|
| std::string halfway_rep = absl::StrCat(mantissa, "e", exponent); |
| FloatType actual_half = 0; |
| absl::from_chars(halfway_rep.data(), halfway_rep.data() + halfway_rep.size(), |
| actual_half); |
| EXPECT_EQ(expected_half, actual_half); |
| } |
|
|
| TEST(FromChars, DoubleRounding) { |
| const double zero = 0.0; |
| const double first_subnormal = nextafter(zero, 1.0); |
| const double second_subnormal = nextafter(first_subnormal, 1.0); |
|
|
| const double first_normal = DBL_MIN; |
| const double last_subnormal = nextafter(first_normal, 0.0); |
| const double second_normal = nextafter(first_normal, 1.0); |
|
|
| const double last_normal = DBL_MAX; |
| const double penultimate_normal = nextafter(last_normal, 0.0); |
|
|
| |
| |
| |
|
|
| |
| TestHalfwayValue( |
| "2." |
| "470328229206232720882843964341106861825299013071623822127928412503377536" |
| "351043759326499181808179961898982823477228588654633283551779698981993873" |
| "980053909390631503565951557022639229085839244910518443593180284993653615" |
| "250031937045767824921936562366986365848075700158576926990370631192827955" |
| "855133292783433840935197801553124659726357957462276646527282722005637400" |
| "648549997709659947045402082816622623785739345073633900796776193057750674" |
| "017632467360096895134053553745851666113422376667860416215968046191446729" |
| "184030053005753084904876539171138659164623952491262365388187963623937328" |
| "042389101867234849766823508986338858792562830275599565752445550725518931" |
| "369083625477918694866799496832404970582102851318545139621383772282614543" |
| "7693412532098591327667236328125", |
| -324, zero, first_subnormal, zero); |
|
|
| |
| TestHalfwayValue( |
| "7." |
| "410984687618698162648531893023320585475897039214871466383785237510132609" |
| "053131277979497545424539885696948470431685765963899850655339096945981621" |
| "940161728171894510697854671067917687257517734731555330779540854980960845" |
| "750095811137303474765809687100959097544227100475730780971111893578483867" |
| "565399878350301522805593404659373979179073872386829939581848166016912201" |
| "945649993128979841136206248449867871357218035220901702390328579173252022" |
| "052897402080290685402160661237554998340267130003581248647904138574340187" |
| "552090159017259254714629617513415977493871857473787096164563890871811984" |
| "127167305601704549300470526959016576377688490826798697257336652176556794" |
| "107250876433756084600398490497214911746308553955635418864151316847843631" |
| "3080237596295773983001708984375", |
| -324, first_subnormal, second_subnormal, second_subnormal); |
|
|
| |
| TestHalfwayValue( |
| "2." |
| "225073858507201136057409796709131975934819546351645648023426109724822222" |
| "021076945516529523908135087914149158913039621106870086438694594645527657" |
| "207407820621743379988141063267329253552286881372149012981122451451889849" |
| "057222307285255133155755015914397476397983411801999323962548289017107081" |
| "850690630666655994938275772572015763062690663332647565300009245888316433" |
| "037779791869612049497390377829704905051080609940730262937128958950003583" |
| "799967207254304360284078895771796150945516748243471030702609144621572289" |
| "880258182545180325707018860872113128079512233426288368622321503775666622" |
| "503982534335974568884423900265498198385487948292206894721689831099698365" |
| "846814022854243330660339850886445804001034933970427567186443383770486037" |
| "86162277173854562306587467901408672332763671875", |
| -308, last_subnormal, first_normal, first_normal); |
|
|
| |
| TestHalfwayValue( |
| "2." |
| "225073858507201630123055637955676152503612414573018013083228724049586647" |
| "606759446192036794116886953213985520549032000903434781884412325572184367" |
| "563347617020518175998922941393629966742598285899994830148971433555578567" |
| "693279306015978183162142425067962460785295885199272493577688320732492479" |
| "924816869232247165964934329258783950102250973957579510571600738343645738" |
| "494324192997092179207389919761694314131497173265255020084997973676783743" |
| "155205818804439163810572367791175177756227497413804253387084478193655533" |
| "073867420834526162513029462022730109054820067654020201547112002028139700" |
| "141575259123440177362244273712468151750189745559978653234255886219611516" |
| "335924167958029604477064946470184777360934300451421683607013647479513962" |
| "13837722826145437693412532098591327667236328125", |
| -308, first_normal, second_normal, first_normal); |
|
|
| |
| TestHalfwayValue( |
| "1." |
| "797693134862315608353258760581052985162070023416521662616611746258695532" |
| "672923265745300992879465492467506314903358770175220871059269879629062776" |
| "047355692132901909191523941804762171253349609463563872612866401980290377" |
| "995141836029815117562837277714038305214839639239356331336428021390916694" |
| "57927874464075218944", |
| 308, penultimate_normal, last_normal, penultimate_normal); |
| } |
|
|
| |
| |
| TEST(FromChars, FloatRounding) { |
| const float zero = 0.0; |
| const float first_subnormal = nextafterf(zero, 1.0); |
| const float second_subnormal = nextafterf(first_subnormal, 1.0); |
|
|
| const float first_normal = FLT_MIN; |
| const float last_subnormal = nextafterf(first_normal, 0.0); |
| const float second_normal = nextafterf(first_normal, 1.0); |
|
|
| const float last_normal = FLT_MAX; |
| const float penultimate_normal = nextafterf(last_normal, 0.0); |
|
|
| |
| TestHalfwayValue( |
| "7." |
| "006492321624085354618647916449580656401309709382578858785341419448955413" |
| "42930300743319094181060791015625", |
| -46, zero, first_subnormal, zero); |
|
|
| |
| TestHalfwayValue( |
| "2." |
| "101947696487225606385594374934874196920392912814773657635602425834686624" |
| "028790902229957282543182373046875", |
| -45, first_subnormal, second_subnormal, second_subnormal); |
|
|
| |
| TestHalfwayValue( |
| "1." |
| "175494280757364291727882991035766513322858992758990427682963118425003064" |
| "9651730385585324256680905818939208984375", |
| -38, last_subnormal, first_normal, first_normal); |
|
|
| |
| TestHalfwayValue( |
| "1." |
| "175494420887210724209590083408724842314472120785184615334540294131831453" |
| "9442813071445925743319094181060791015625", |
| -38, first_normal, second_normal, first_normal); |
|
|
| |
| TestHalfwayValue("3.40282336497324057985868971510891282432", 38, |
| penultimate_normal, last_normal, penultimate_normal); |
| } |
|
|
| TEST(FromChars, Underflow) { |
| |
| |
| double d; |
| float f; |
| absl::from_chars_result result; |
|
|
| std::string negative_underflow = "-1e-1000"; |
| const char* begin = negative_underflow.data(); |
| const char* end = begin + negative_underflow.size(); |
| d = 100.0; |
| result = absl::from_chars(begin, end, d); |
| EXPECT_EQ(result.ptr, end); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| EXPECT_TRUE(std::signbit(d)); |
| EXPECT_GE(d, -std::numeric_limits<double>::min()); |
| f = 100.0; |
| result = absl::from_chars(begin, end, f); |
| EXPECT_EQ(result.ptr, end); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| EXPECT_TRUE(std::signbit(f)); |
| EXPECT_GE(f, -std::numeric_limits<float>::min()); |
|
|
| std::string positive_underflow = "1e-1000"; |
| begin = positive_underflow.data(); |
| end = begin + positive_underflow.size(); |
| d = -100.0; |
| result = absl::from_chars(begin, end, d); |
| EXPECT_EQ(result.ptr, end); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| EXPECT_FALSE(std::signbit(d)); |
| EXPECT_LE(d, std::numeric_limits<double>::min()); |
| f = -100.0; |
| result = absl::from_chars(begin, end, f); |
| EXPECT_EQ(result.ptr, end); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| EXPECT_FALSE(std::signbit(f)); |
| EXPECT_LE(f, std::numeric_limits<float>::min()); |
| } |
|
|
| TEST(FromChars, Overflow) { |
| |
| |
| double d; |
| float f; |
| absl::from_chars_result result; |
|
|
| std::string negative_overflow = "-1e1000"; |
| const char* begin = negative_overflow.data(); |
| const char* end = begin + negative_overflow.size(); |
| d = 100.0; |
| result = absl::from_chars(begin, end, d); |
| EXPECT_EQ(result.ptr, end); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| EXPECT_TRUE(std::signbit(d)); |
| EXPECT_EQ(d, -std::numeric_limits<double>::max()); |
| f = 100.0; |
| result = absl::from_chars(begin, end, f); |
| EXPECT_EQ(result.ptr, end); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| EXPECT_TRUE(std::signbit(f)); |
| EXPECT_EQ(f, -std::numeric_limits<float>::max()); |
|
|
| std::string positive_overflow = "1e1000"; |
| begin = positive_overflow.data(); |
| end = begin + positive_overflow.size(); |
| d = -100.0; |
| result = absl::from_chars(begin, end, d); |
| EXPECT_EQ(result.ptr, end); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| EXPECT_FALSE(std::signbit(d)); |
| EXPECT_EQ(d, std::numeric_limits<double>::max()); |
| f = -100.0; |
| result = absl::from_chars(begin, end, f); |
| EXPECT_EQ(result.ptr, end); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| EXPECT_FALSE(std::signbit(f)); |
| EXPECT_EQ(f, std::numeric_limits<float>::max()); |
| } |
|
|
| TEST(FromChars, RegressionTestsFromFuzzer) { |
| absl::string_view src = "0x21900000p00000000099"; |
| float f; |
| auto result = absl::from_chars(src.data(), src.data() + src.size(), f); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| } |
|
|
| TEST(FromChars, ReturnValuePtr) { |
| |
| |
| double d; |
| absl::from_chars_result result; |
|
|
| std::string normal = "3.14@#$%@#$%"; |
| result = absl::from_chars(normal.data(), normal.data() + normal.size(), d); |
| EXPECT_EQ(result.ec, std::errc()); |
| EXPECT_EQ(result.ptr - normal.data(), 4); |
|
|
| std::string overflow = "1e1000@#$%@#$%"; |
| result = absl::from_chars(overflow.data(), |
| overflow.data() + overflow.size(), d); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| EXPECT_EQ(result.ptr - overflow.data(), 6); |
|
|
| std::string garbage = "#$%@#$%"; |
| result = absl::from_chars(garbage.data(), |
| garbage.data() + garbage.size(), d); |
| EXPECT_EQ(result.ec, std::errc::invalid_argument); |
| EXPECT_EQ(result.ptr - garbage.data(), 0); |
| } |
|
|
| |
| |
| |
| |
| |
| TEST(FromChars, TestVersusStrtod) { |
| for (int mantissa = 1000000; mantissa <= 9999999; mantissa += 501) { |
| for (int exponent = -300; exponent < 300; ++exponent) { |
| std::string candidate = absl::StrCat(mantissa, "e", exponent); |
| double strtod_value = strtod(candidate.c_str(), nullptr); |
| double absl_value = 0; |
| absl::from_chars(candidate.data(), candidate.data() + candidate.size(), |
| absl_value); |
| ASSERT_EQ(strtod_value, absl_value) << candidate; |
| } |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| TEST(FromChars, TestVersusStrtof) { |
| for (int mantissa = 1000000; mantissa <= 9999999; mantissa += 501) { |
| for (int exponent = -43; exponent < 32; ++exponent) { |
| std::string candidate = absl::StrCat(mantissa, "e", exponent); |
| float strtod_value = strtof(candidate.c_str(), nullptr); |
| float absl_value = 0; |
| absl::from_chars(candidate.data(), candidate.data() + candidate.size(), |
| absl_value); |
| ASSERT_EQ(strtod_value, absl_value) << candidate; |
| } |
| } |
| } |
|
|
| |
| |
| template <typename Float> |
| bool Identical(Float a, Float b) { |
| return 0 == memcmp(&a, &b, sizeof(Float)); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| TEST(FromChars, NaNDoubles) { |
| for (std::string n_char_sequence : |
| {"", "1", "2", "3", "fff", "FFF", "200000", "400000", "4000000000000", |
| "8000000000000", "abc123", "legal_but_unexpected", |
| "99999999999999999999999", "_"}) { |
| std::string input = absl::StrCat("nan(", n_char_sequence, ")"); |
| SCOPED_TRACE(input); |
| double from_chars_double; |
| absl::from_chars(input.data(), input.data() + input.size(), |
| from_chars_double); |
| double std_nan_double = std::nan(n_char_sequence.c_str()); |
| EXPECT_TRUE(Identical(from_chars_double, std_nan_double)); |
|
|
| |
| |
| #if ABSL_STRTOD_HANDLES_NAN_CORRECTLY |
| double strtod_double = strtod(input.c_str(), nullptr); |
| EXPECT_TRUE(Identical(from_chars_double, strtod_double)); |
| #endif |
|
|
| |
| std::string negative_input = "-" + input; |
| double negative_from_chars_double; |
| absl::from_chars(negative_input.data(), |
| negative_input.data() + negative_input.size(), |
| negative_from_chars_double); |
| EXPECT_TRUE(std::signbit(negative_from_chars_double)); |
| EXPECT_FALSE(Identical(negative_from_chars_double, from_chars_double)); |
| from_chars_double = std::copysign(from_chars_double, -1.0); |
| EXPECT_TRUE(Identical(negative_from_chars_double, from_chars_double)); |
| } |
| } |
|
|
| TEST(FromChars, NaNFloats) { |
| for (std::string n_char_sequence : |
| {"", "1", "2", "3", "fff", "FFF", "200000", "400000", "4000000000000", |
| "8000000000000", "abc123", "legal_but_unexpected", |
| "99999999999999999999999", "_"}) { |
| std::string input = absl::StrCat("nan(", n_char_sequence, ")"); |
| SCOPED_TRACE(input); |
| float from_chars_float; |
| absl::from_chars(input.data(), input.data() + input.size(), |
| from_chars_float); |
| float std_nan_float = std::nanf(n_char_sequence.c_str()); |
| EXPECT_TRUE(Identical(from_chars_float, std_nan_float)); |
|
|
| |
| |
| #if ABSL_STRTOD_HANDLES_NAN_CORRECTLY |
| float strtof_float = strtof(input.c_str(), nullptr); |
| EXPECT_TRUE(Identical(from_chars_float, strtof_float)); |
| #endif |
|
|
| |
| std::string negative_input = "-" + input; |
| float negative_from_chars_float; |
| absl::from_chars(negative_input.data(), |
| negative_input.data() + negative_input.size(), |
| negative_from_chars_float); |
| EXPECT_TRUE(std::signbit(negative_from_chars_float)); |
| EXPECT_FALSE(Identical(negative_from_chars_float, from_chars_float)); |
| |
| |
| from_chars_float = std::copysign(from_chars_float, -1.0f); |
| EXPECT_TRUE(Identical(negative_from_chars_float, from_chars_float)); |
| } |
| } |
|
|
| |
| int NextStep(int step) { |
| return step + (step >> 2) + 1; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| template <typename Float> |
| void TestOverflowAndUnderflow( |
| const std::function<std::string(int)>& input_generator, |
| const std::function<Float(int)>& expected_generator, int lower_bound, |
| int upper_bound) { |
| |
| int index, step; |
| for (index = lower_bound, step = 1; index < upper_bound; |
| index += step, step = NextStep(step)) { |
| std::string input = input_generator(index); |
| SCOPED_TRACE(input); |
| Float expected = expected_generator(index); |
| Float actual; |
| auto result = |
| absl::from_chars(input.data(), input.data() + input.size(), actual); |
| EXPECT_EQ(result.ec, std::errc()); |
| EXPECT_EQ(expected, actual) |
| << absl::StrFormat("%a vs %a", expected, actual); |
| } |
| |
| for (index = upper_bound, step = 1; index > lower_bound; |
| index -= step, step = NextStep(step)) { |
| std::string input = input_generator(index); |
| SCOPED_TRACE(input); |
| Float expected = expected_generator(index); |
| Float actual; |
| auto result = |
| absl::from_chars(input.data(), input.data() + input.size(), actual); |
| EXPECT_EQ(result.ec, std::errc()); |
| EXPECT_EQ(expected, actual) |
| << absl::StrFormat("%a vs %a", expected, actual); |
| } |
| |
| for (index = lower_bound - 1, step = 1; index > -1000000; |
| index -= step, step = NextStep(step)) { |
| std::string input = input_generator(index); |
| SCOPED_TRACE(input); |
| Float actual; |
| auto result = |
| absl::from_chars(input.data(), input.data() + input.size(), actual); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| EXPECT_LT(actual, 1.0); |
| } |
| |
| for (index = upper_bound + 1, step = 1; index < 1000000; |
| index += step, step = NextStep(step)) { |
| std::string input = input_generator(index); |
| SCOPED_TRACE(input); |
| Float actual; |
| auto result = |
| absl::from_chars(input.data(), input.data() + input.size(), actual); |
| EXPECT_EQ(result.ec, std::errc::result_out_of_range); |
| EXPECT_GT(actual, 1.0); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| TEST(FromChars, HexdecimalDoubleLimits) { |
| auto input_gen = [](int index) { return absl::StrCat("0x1.0p", index); }; |
| auto expected_gen = [](int index) { return std::ldexp(1.0, index); }; |
| TestOverflowAndUnderflow<double>(input_gen, expected_gen, -1074, 1023); |
| } |
|
|
| |
| |
| |
| |
| |
| TEST(FromChars, HexdecimalFloatLimits) { |
| auto input_gen = [](int index) { return absl::StrCat("0x1.0p", index); }; |
| auto expected_gen = [](int index) { return std::ldexp(1.0f, index); }; |
| TestOverflowAndUnderflow<float>(input_gen, expected_gen, -149, 127); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| TEST(FromChars, DecimalDoubleLimits) { |
| auto input_gen = [](int index) { return absl::StrCat("1.0e", index); }; |
| auto expected_gen = [](int index) { return Pow10(index); }; |
| TestOverflowAndUnderflow<double>(input_gen, expected_gen, -323, 308); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| TEST(FromChars, DecimalFloatLimits) { |
| auto input_gen = [](int index) { return absl::StrCat("1.0e", index); }; |
| auto expected_gen = [](int index) { return Pow10(index); }; |
| TestOverflowAndUnderflow<float>(input_gen, expected_gen, -45, 38); |
| } |
|
|
| } |
|
|