diff --git a/include/fast_float/ascii_number.h b/include/fast_float/ascii_number.h index b372367..c231f31 100644 --- a/include/fast_float/ascii_number.h +++ b/include/fast_float/ascii_number.h @@ -35,22 +35,6 @@ fastfloat_really_inline bool is_made_of_eight_digits_fast(const char *chars) no return is_made_of_eight_digits_fast(val); } - -fastfloat_really_inline uint32_t parse_four_digits_unrolled(const char *chars) noexcept { - uint32_t val; - ::memcpy(&val, chars, sizeof(uint32_t)); - val = (val & 0x0F0F0F0F) * 2561 >> 8; - return (val & 0x00FF00FF) * 6553601 >> 16; -} - -fastfloat_really_inline bool is_made_of_four_digits_fast(const char *chars) noexcept { - uint32_t val; - ::memcpy(&val, chars, 4); - return (((val & 0xF0F0F0F0) | - (((val + 0x06060606) & 0xF0F0F0F0) >> 4)) == - 0x33333333); -} - struct parsed_number_string { int64_t exponent; uint64_t mantissa; @@ -114,9 +98,9 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_ int32_t digit_count = int32_t(p - start_digits - 1); // used later to guard against overflows - - if ((p != pend) && (('e' == *p) || ('E' == *p))) { - if((fmt & chars_format::fixed) && !(fmt & chars_format::scientific)) { return answer; } + + if ((fmt & chars_format::scientific) && (p != pend) && (('e' == *p) || ('E' == *p))) { + const char * location_of_e = p; int64_t exp_number = 0; // exponential part ++p; bool neg_exp = false; @@ -127,18 +111,24 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_ ++p; } if ((p == pend) || !is_integer(*p)) { - return answer; - } - while ((p != pend) && is_integer(*p)) { - uint8_t digit = uint8_t(*p - '0'); - if (exp_number < 0x10000) { - exp_number = 10 * exp_number + digit; + if(!(fmt & chars_format::fixed)) { + // We are in error. + return answer; } - ++p; + // Otherwise, we will be ignoring the 'e'. + } else { + while ((p != pend) && is_integer(*p)) { + uint8_t digit = uint8_t(*p - '0'); + if (exp_number < 0x10000) { + exp_number = 10 * exp_number + digit; + } + ++p; + } + exponent += (neg_exp ? -exp_number : exp_number); } - exponent += (neg_exp ? -exp_number : exp_number); } else { - if((fmt & chars_format::scientific) && !(fmt & chars_format::fixed)) { return answer; } + // If it scientific and not fixed, we have to bail out. + if((fmt & chars_format::scientific) && !(fmt & chars_format::fixed)) { return answer; } } answer.lastmatch = p; answer.valid = true; @@ -176,7 +166,6 @@ decimal parse_decimal(const char *p, const char *pend) noexcept { decimal answer; answer.num_digits = 0; answer.decimal_point = 0; - answer.negative = false; answer.truncated = false; // any whitespace has been skipped. answer.negative = (*p == '-'); @@ -194,10 +183,9 @@ decimal parse_decimal(const char *p, const char *pend) noexcept { answer.num_digits++; ++p; } - const char *first_after_period{}; if ((p != pend) && (*p == '.')) { ++p; - first_after_period = p; + const char *first_after_period = p; // if we have not yet encountered a zero, we have to skip it as well if(answer.num_digits == 0) { // skip zeros @@ -206,7 +194,7 @@ decimal parse_decimal(const char *p, const char *pend) noexcept { } } // We expect that this loop will often take the bulk of the running time - // because when a value has lots of digits, these digits often + // because when a value has lots of digits, these digits often while ((p + 8 <= pend) && (answer.num_digits + 8 < max_digits)) { uint64_t val; ::memcpy(&val, p, sizeof(uint64_t)); @@ -240,7 +228,7 @@ decimal parse_decimal(const char *p, const char *pend) noexcept { uint8_t digit = uint8_t(*p - '0'); if (exp_number < 0x10000) { exp_number = 10 * exp_number + digit; - } + } ++p; } answer.decimal_point += (neg_exp ? -exp_number : exp_number); diff --git a/include/fast_float/decimal_to_binary.h b/include/fast_float/decimal_to_binary.h index acc17cf..918f88d 100644 --- a/include/fast_float/decimal_to_binary.h +++ b/include/fast_float/decimal_to_binary.h @@ -17,18 +17,18 @@ namespace fast_float { // This will compute or rather approximate w * 5**q and return a pair of 64-bit words approximating // the result, with the "high" part corresponding to the most significant bits and the // low part corresponding to the least significant bits. -// +// template fastfloat_really_inline value128 compute_product_approximation(int64_t q, uint64_t w) { const int index = 2 * int(q - smallest_power_of_five); // For small values of q, e.g., q in [0,27], the answer is always exact because // The line value128 firstproduct = full_multiplication(w, power_of_five_128[index]); - // gives the exact answer. + // gives the exact answer. value128 firstproduct = full_multiplication(w, power_of_five_128[index]); static_assert((bit_precision >= 0) && (bit_precision <= 64), " precision should be in (0,64]"); - constexpr uint64_t precision_mask = (bit_precision < 64) ? - (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision) + constexpr uint64_t precision_mask = (bit_precision < 64) ? + (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision) : uint64_t(0xFFFFFFFFFFFFFFFF); if((firstproduct.high & precision_mask) == precision_mask) { // could further guard with (lower + w < lower) // regarding the second product, we only need secondproduct.high, but our expectation is that the compiler will optimize this extra work away if needed. @@ -58,7 +58,7 @@ namespace { // w * 10 ** q // The returned value should be a valid ieee64 number that simply need to be packed. -// However, in some very rare cases, the computation will fail. In such cases, we +// However, in some very rare cases, the computation will fail. In such cases, we // return an adjusted_mantissa with a negative power of 2: the caller should recompute // in such cases. template @@ -88,7 +88,7 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept { // 2. We need an extra bit for rounding purposes // 3. We might lose a bit due to the "upperbit" routine (result too small, requiring a shift) value128 product = compute_product_approximation(q, w); - if(product.low == 0xFFFFFFFFFFFFFFFF) { // could guard it further + if(product.low == 0xFFFFFFFFFFFFFFFF) { // could guard it further // In some very rare cases, this could happen, in which case we might need a more accurate // computation that what we can provide cheaply. This is very, very unlikely. answer.power2 = -1; // This (a negative value) indicates an error condition. @@ -111,7 +111,7 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept { answer.mantissa = 0; // result should be zero return answer; - } + } // next line is safe because -answer.power2 + 1 < 64 answer.mantissa >>= -answer.power2 + 1; // Thankfully, we can't have both "round-to-even" and subnormals because @@ -132,7 +132,7 @@ adjusted_mantissa compute_float(int64_t q, uint64_t w) noexcept { // usually, we round *up*, but if we fall right in between and and we have an // even basis, we need to round down // We are only concerned with the cases where 5**q fits in single 64-bit word. - if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) && (q <= binary::max_exponent_round_to_even()) && + if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) && (q <= binary::max_exponent_round_to_even()) && ((answer.mantissa & 3) == 1) ) { // we may fall between two floats! // To be in-between two floats we need that in doing // answer.mantissa = product.high >> (upperbit + 64 - binary::mantissa_explicit_bits() - 3); diff --git a/include/fast_float/fast_float.h b/include/fast_float/fast_float.h index bccac3f..ffad079 100644 --- a/include/fast_float/fast_float.h +++ b/include/fast_float/fast_float.h @@ -19,19 +19,19 @@ struct from_chars_result { /** * This function parses the character sequence [first,last) for a number. It parses floating-point numbers expecting - * a locale-indepent format equivalent to what is used by std::strtod in the default ("C") locale. - * The resulting floating-point value is the closest floating-point values (using either float or double), + * a locale-indepent format equivalent to what is used by std::strtod in the default ("C") locale. + * The resulting floating-point value is the closest floating-point values (using either float or double), * using the "round to even" convention for values that would otherwise fall right in-between two values. * That is, we provide exact parsing according to the IEEE standard. - * + * * Given a successful parse, the pointer (`ptr`) in the returned value is set to point right after the * parsed number, and the `value` referenced is set to the parsed value. In case of error, the returned * `ec` contains a representative error, otherwise the default (`std::errc()`) value is stored. - * + * * The implementation does not throw and does not allocate memory (e.g., with `new` or `malloc`). - * + * * Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of - * the type `fast_float::chars_format`. It is a bitset value: we check whether + * the type `fast_float::chars_format`. It is a bitset value: we check whether * `fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set * to determine whether we allowe the fixed point and scientific notation respectively. * The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`. diff --git a/include/fast_float/fast_table.h b/include/fast_float/fast_table.h index c24e9a7..f92d6f6 100644 --- a/include/fast_float/fast_table.h +++ b/include/fast_float/fast_table.h @@ -19,12 +19,12 @@ namespace fast_float { * The smallest non-zero float (binary64) is 2^−1074. * We take as input numbers of the form w x 10^q where w < 2^64. * We have that w * 10^-343 < 2^(64-344) 5^-343 < 2^-1076. - * However, we have that + * However, we have that * (2^64-1) * 10^-342 = (2^64-1) * 2^-342 * 5^-342 > 2^−1074. - * Thus it is possible for a number of the form w * 10^-342 where + * Thus it is possible for a number of the form w * 10^-342 where * w is a 64-bit value to be a non-zero floating-point number. ********* - * Any number of form w * 10^309 where w>= 1 is going to be + * Any number of form w * 10^309 where w>= 1 is going to be * infinite in binary64 so we never need to worry about powers * of 5 greater than 308. */ diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index 9b2d5b5..3e246d9 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -16,7 +16,7 @@ namespace fast_float { namespace { /** * Special case +inf, -inf, nan, infinity, -infinity. - * The case comparisons could be made much faster given that we know that the + * The case comparisons could be made much faster given that we know that the * strings a null-free and fixed. **/ template @@ -63,6 +63,7 @@ from_chars_result parse_infnan(const char *first, const char *last, T &value) n } } answer.ec = std::errc::invalid_argument; + answer.ptr = first; return answer; } } // namespace @@ -93,7 +94,7 @@ from_chars_result from_chars(const char *first, const char *last, if (binary_format::min_exponent_fast_path() <= pns.exponent && pns.exponent <= binary_format::max_exponent_fast_path() && pns.mantissa <=binary_format::max_mantissa_fast_path()) { value = T(pns.mantissa); - if (pns.exponent < 0) { value = value / binary_format::exact_power_of_ten(-pns.exponent); } + if (pns.exponent < 0) { value = value / binary_format::exact_power_of_ten(-pns.exponent); } else { value = value * binary_format::exact_power_of_ten(pns.exponent); } if (pns.negative) { value = -value; } return answer; @@ -104,7 +105,7 @@ from_chars_result from_chars(const char *first, const char *last, if(am.power2 < 0) { am = parse_long_mantissa>(first,last); } uint64_t word = am.mantissa; word |= uint64_t(am.power2) << binary_format::mantissa_explicit_bits(); - word = pns.negative + word = pns.negative ? word | (uint64_t(1) << binary_format::sign_index()) : word; ::memcpy(&value, &word, sizeof(T)); return answer; diff --git a/include/fast_float/simple_decimal_conversion.h b/include/fast_float/simple_decimal_conversion.h index 8ca0cb6..97fad93 100644 --- a/include/fast_float/simple_decimal_conversion.h +++ b/include/fast_float/simple_decimal_conversion.h @@ -3,13 +3,13 @@ /** * This code is meant to handle the case where we have more than 19 digits. - * + * * It is based on work by Nigel Tao (at https://github.com/google/wuffs/) * who credits Ken Thompson for the design (via a reference to the Go source * code). - * + * * Rob Pike suggested that this algorithm be called "Simple Decimal Conversion". - * + * * It is probably not very fast but it is a fallback that should almost never * be used in real life. Though it is not fast, it is "easily" understood and debugged. **/ @@ -30,7 +30,7 @@ inline void trim(decimal &h) { -uint32_t number_of_digits_decimal_left_shift(decimal &h, uint32_t shift) { +uint32_t number_of_digits_decimal_left_shift(const decimal &h, uint32_t shift) { shift &= 63; const static uint16_t number_of_digits_decimal_left_shift_table[65] = { 0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817, @@ -139,7 +139,7 @@ uint64_t round(decimal &h) { } bool round_up = false; if (dp < h.num_digits) { - round_up = h.digits[dp] >= 5; // normally, we round up + round_up = h.digits[dp] >= 5; // normally, we round up // but we may need to round to even! if ((h.digits[dp] == 5) && (dp + 1 == h.num_digits)) { round_up = h.truncated || ((dp > 0) && (1 & h.digits[dp - 1])); @@ -253,21 +253,21 @@ adjusted_mantissa compute_float(decimal &d) { // At this point, going further, we can assume that d.num_digits > 0. // // We want to guard against excessive decimal point values because - // they can result in long running times. Indeed, we do + // they can result in long running times. Indeed, we do // shifts by at most 60 bits. We have that log(10**400)/log(2**60) ~= 22 // which is fine, but log(10**299995)/log(2**60) ~= 16609 which is not // fine (runs for a long time). // if(d.decimal_point < -324) { // We have something smaller than 1e-324 which is always zero - // in binary64 and binary32. + // in binary64 and binary32. // It should be zero. answer.power2 = 0; answer.mantissa = 0; return answer; } else if(d.decimal_point >= 310) { // We have something at least as large as 0.1e310 which is - // always infinite. + // always infinite. answer.power2 = binary::infinite_power(); answer.mantissa = 0; return answer; diff --git a/tests/basictest.cpp b/tests/basictest.cpp index cd46a59..ec272b5 100644 --- a/tests/basictest.cpp +++ b/tests/basictest.cpp @@ -147,9 +147,42 @@ bool issue8() { return true; } +bool check_behavior() { + const std::string input = "abc"; + double result; + auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); + if(answer.ec != std::errc()) { + std::cerr << "parsing failure as expected\n"; + // specification says ptr should point at first + if(answer.ptr != input.data()) { + std::cerr << "If there is no pattern match, we should have ptr equals first\n"; + return false; + } + return true; + } + std::cout << "parsed the number " << result << std::endl; + return false; +} + +bool issue19() { + const std::string input = "3.14e"; + double result; + auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result); + if(answer.ec != std::errc()) { + std::cerr << "We want to parse up to 3.14\n"; + return false; + } + std::cout << "parsed the number " << result << std::endl; + if(answer.ptr != input.data() + 4) { + std::cout << "Parsed the number and stopped at the right character." << result << std::endl; + return true; + } + return false; +} + int main() { - - + Assert(issue19()); + Assert(check_behavior()); std::cout << "======= 64 bits " << std::endl; Assert(basic_test_64bit("INF",std::numeric_limits::infinity())); Assert(basic_test_64bit("-INF",-std::numeric_limits::infinity())); @@ -167,7 +200,7 @@ int main() { Assert(basic_test_64bit("2.2250738585072013e-308",2.2250738585072013e-308)); Assert(basic_test_64bit("-92666518056446206563E3", -92666518056446206563E3)); Assert(basic_test_64bit("-92666518056446206563E3", -92666518056446206563E3)); - Assert(basic_test_64bit("-42823146028335318693e-128",-42823146028335318693e-128)); + Assert(basic_test_64bit("-42823146028335318693e-128",-42823146028335318693e-128)); Assert(basic_test_64bit("90054602635948575728E72",90054602635948575728E72)); Assert(basic_test_64bit("1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309", 1.00000000000000188558920870223463870174566020691753515394643550663070558368373221972569761144603605635692374830246134201063722058e-309)); Assert(basic_test_64bit("0e9999999999999999999999999999", 0)); @@ -214,7 +247,7 @@ int main() { Assert(basic_test_64bit("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375)); Assert(basic_test_64bit("0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375", 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375)); Assert(basic_test_64bit("1438456663141390273526118207642235581183227845246331231162636653790368152091394196930365828634687637948157940776599182791387527135353034738357134110310609455693900824193549772792016543182680519740580354365467985440183598701312257624545562331397018329928613196125590274187720073914818062530830316533158098624984118889298281371812288789537310599037529113415438738954894752124724983067241108764488346454376699018673078404751121414804937224240805993123816932326223683090770561597570457793932985826162604255884529134126396282202126526253389383421806727954588525596114379801269094096329805054803089299736996870951258573010877404407451953846698609198213926882692078557033228265259305481198526059813164469187586693257335779522020407645498684263339921905227556616698129967412891282231685504660671277927198290009824680186319750978665734576683784255802269708917361719466043175201158849097881370477111850171579869056016061666173029059588433776015644439705050377554277696143928278093453792803846252715966016733222646442382892123940052441346822429721593884378212558701004356924243030059517489346646577724622498919752597382095222500311124181823512251071356181769376577651390028297796156208815375089159128394945710515861334486267101797497111125909272505194792870889617179758703442608016143343262159998149700606597792535574457560429226974273443630323818747730771316763398572110874959981923732463076884528677392654150010269822239401993427482376513231389212353583573566376915572650916866553612366187378959554983566712767093372906030188976220169058025354973622211666504549316958271880975697143546564469806791358707318873075708383345004090151974068325838177531266954177406661392229801349994695941509935655355652985723782153570084089560139142231.738475042362596875449154552392299548947138162081694168675340677843807613129780449323363759027012972466987370921816813162658754726545121090545507240267000456594786540949605260722461937870630634874991729398208026467698131898691830012167897399682179601734569071423681e-733", std::numeric_limits::infinity())); - + std::cout << std::endl; std::cout << "======= 32 bits " << std::endl; @@ -230,43 +263,43 @@ int main() { Assert(basic_test_32bit("1090544144181609348835077142190",0x1.b877ap+99f)); Assert(basic_test_32bit("1.1754943508e-38",1.1754943508e-38f)); Assert(basic_test_32bit("30219.0830078125",30219.0830078125f)); - Assert(basic_test_32bit("16252921.5",16252921.5f)); - Assert(basic_test_32bit("5322519.25",5322519.25f)); - Assert(basic_test_32bit("3900245.875",3900245.875f)); - Assert(basic_test_32bit("1510988.3125",1510988.3125f)); - Assert(basic_test_32bit("782262.28125",782262.28125f)); - Assert(basic_test_32bit("328381.484375",328381.484375f)); - Assert(basic_test_32bit("156782.0703125",156782.0703125f)); - Assert(basic_test_32bit("85003.24609375",85003.24609375f)); - Assert(basic_test_32bit("43827.048828125",43827.048828125f)); - Assert(basic_test_32bit("17419.6494140625",17419.6494140625f)); - Assert(basic_test_32bit("15498.36376953125",15498.36376953125f)); - Assert(basic_test_32bit("6318.580322265625",6318.580322265625f)); - Assert(basic_test_32bit("2525.2840576171875",2525.2840576171875f)); - Assert(basic_test_32bit("1370.9265747070312",1370.9265747070312f)); - Assert(basic_test_32bit("936.3702087402344",936.3702087402344f)); - Assert(basic_test_32bit("411.88682556152344",411.88682556152344f)); - Assert(basic_test_32bit("206.50310516357422",206.50310516357422f)); - Assert(basic_test_32bit("124.16878890991211",124.16878890991211f)); - Assert(basic_test_32bit("50.811574935913086",50.811574935913086f)); - Assert(basic_test_32bit("17.486443519592285",17.486443519592285f)); - Assert(basic_test_32bit("13.91745138168335",13.91745138168335f)); - Assert(basic_test_32bit("7.5464513301849365",0x1.e2f90ep+2f)); - Assert(basic_test_32bit("2.687217116355896",2.687217116355896f)); - Assert(basic_test_32bit("1.1877630352973938",0x1.30113ep+0f)); - Assert(basic_test_32bit("0.7622503340244293",0.7622503340244293f)); - Assert(basic_test_32bit("0.30531780421733856",0x1.38a53ap-2f)); - Assert(basic_test_32bit("0.21791061013936996",0x1.be47eap-3f)); - Assert(basic_test_32bit("0.09289376810193062",0x1.7c7e2ep-4f)); - Assert(basic_test_32bit("0.03706067614257336",0.03706067614257336f)); - Assert(basic_test_32bit("0.028068351559340954",0.028068351559340954f)); - Assert(basic_test_32bit("0.012114629615098238",0x1.8cf8e2p-7f)); - Assert(basic_test_32bit("0.004221370676532388",0x1.14a6dap-8f)); - Assert(basic_test_32bit("0.002153817447833717",0.002153817447833717f)); - Assert(basic_test_32bit("0.0015924838953651488",0x1.a175cap-10f)); - Assert(basic_test_32bit("0.0008602388261351734",0.0008602388261351734f)); - Assert(basic_test_32bit("0.00036393293703440577",0x1.7d9c82p-12f)); - Assert(basic_test_32bit("0.00013746770127909258",0.00013746770127909258)); + Assert(basic_test_32bit("16252921.5",16252921.5f)); + Assert(basic_test_32bit("5322519.25",5322519.25f)); + Assert(basic_test_32bit("3900245.875",3900245.875f)); + Assert(basic_test_32bit("1510988.3125",1510988.3125f)); + Assert(basic_test_32bit("782262.28125",782262.28125f)); + Assert(basic_test_32bit("328381.484375",328381.484375f)); + Assert(basic_test_32bit("156782.0703125",156782.0703125f)); + Assert(basic_test_32bit("85003.24609375",85003.24609375f)); + Assert(basic_test_32bit("43827.048828125",43827.048828125f)); + Assert(basic_test_32bit("17419.6494140625",17419.6494140625f)); + Assert(basic_test_32bit("15498.36376953125",15498.36376953125f)); + Assert(basic_test_32bit("6318.580322265625",6318.580322265625f)); + Assert(basic_test_32bit("2525.2840576171875",2525.2840576171875f)); + Assert(basic_test_32bit("1370.9265747070312",1370.9265747070312f)); + Assert(basic_test_32bit("936.3702087402344",936.3702087402344f)); + Assert(basic_test_32bit("411.88682556152344",411.88682556152344f)); + Assert(basic_test_32bit("206.50310516357422",206.50310516357422f)); + Assert(basic_test_32bit("124.16878890991211",124.16878890991211f)); + Assert(basic_test_32bit("50.811574935913086",50.811574935913086f)); + Assert(basic_test_32bit("17.486443519592285",17.486443519592285f)); + Assert(basic_test_32bit("13.91745138168335",13.91745138168335f)); + Assert(basic_test_32bit("7.5464513301849365",0x1.e2f90ep+2f)); + Assert(basic_test_32bit("2.687217116355896",2.687217116355896f)); + Assert(basic_test_32bit("1.1877630352973938",0x1.30113ep+0f)); + Assert(basic_test_32bit("0.7622503340244293",0.7622503340244293f)); + Assert(basic_test_32bit("0.30531780421733856",0x1.38a53ap-2f)); + Assert(basic_test_32bit("0.21791061013936996",0x1.be47eap-3f)); + Assert(basic_test_32bit("0.09289376810193062",0x1.7c7e2ep-4f)); + Assert(basic_test_32bit("0.03706067614257336",0.03706067614257336f)); + Assert(basic_test_32bit("0.028068351559340954",0.028068351559340954f)); + Assert(basic_test_32bit("0.012114629615098238",0x1.8cf8e2p-7f)); + Assert(basic_test_32bit("0.004221370676532388",0x1.14a6dap-8f)); + Assert(basic_test_32bit("0.002153817447833717",0.002153817447833717f)); + Assert(basic_test_32bit("0.0015924838953651488",0x1.a175cap-10f)); + Assert(basic_test_32bit("0.0008602388261351734",0.0008602388261351734f)); + Assert(basic_test_32bit("0.00036393293703440577",0x1.7d9c82p-12f)); + Assert(basic_test_32bit("0.00013746770127909258",0.00013746770127909258)); Assert(basic_test_32bit("16407.9462890625", 16407.9462890625f)); Assert(basic_test_32bit("1.1754947011469036e-38", 0x1.000006p-126f)); Assert(basic_test_32bit("7.0064923216240854e-46", 0x1p-149f));