From fce8610d2cb9e181a7e0ab2d4c4eed8c69c9c94c Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Wed, 20 May 2020 19:20:26 +0800 Subject: [PATCH 1/3] fix floating point parsing precision in some rare cases --- NEWS.md | 2 + inst/tests/tests.Rraw | 5 + src/fread.c | 8 +- src/freadLookups.h | 600 +++++++++++++++++++++--------------------- 4 files changed, 312 insertions(+), 303 deletions(-) diff --git a/NEWS.md b/NEWS.md index 026f06c86e..408544d9d0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -109,6 +109,8 @@ unit = "s") 13. A relatively rare case of segfault when combining non-equi joins with `by=.EACHI` is now fixed, closes [#4388](https://github.com/Rdatatable/data.table/issues/4388). +14. In some rare cases, `fread` parsed a very small difference in numeric input as compared to `read.table`, [#4461](https://github.com/Rdatatable/data.table/issues/4461). The latter is more accurate (in that it produces the double-precision representation that's closer to the base-10 value), so this is indeed an `fread` error. Thanks @gmbecker for the report. + ## NOTES 0. Retrospective license change permission was sought from and granted by 4 contributors who were missed in [PR#2456](https://github.com/Rdatatable/data.table/pull/2456), [#4140](https://github.com/Rdatatable/data.table/pull/4140). We had used [GitHub's contributor page](https://github.com/Rdatatable/data.table/graphs/contributors) which omits 3 of these due to invalid email addresses, unlike GitLab's contributor page which includes the ids. The 4th omission was a PR to a script which should not have been excluded; a script is code too. We are sorry these contributors were not properly credited before. They have now been added to the contributors list as displayed on CRAN. All the contributors of code to data.table hold its copyright jointly; your contributions belong to you. You contributed to data.table when it had a particular license at that time, and you contributed on that basis. This is why in the last license change, all contributors of code were consulted and each had a veto. diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index ed17470383..94f27789c7 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -16853,3 +16853,8 @@ A = data.table(A=c(complex(real = 1:3, imaginary=c(0, -1, 1)), NaN)) test(2138.3, rbind(A,B), data.table(A=c(as.character(A$A), B$A))) A = data.table(A=as.complex(rep(NA, 5))) test(2138.4, rbind(A,B), data.table(A=c(as.character(A$A), B$A))) + +# Rare precision loss owing to unrepresentability of powers of 10^(-n), #4461 +exchar = "0.8060667366" +exnum = 0.8060667366 +test(2139.1, identical(fread(text = c(exchar, exchar))$V1[1L], exnum)) diff --git a/src/fread.c b/src/fread.c index c94aeac069..a8af9f2ff8 100644 --- a/src/fread.c +++ b/src/fread.c @@ -649,7 +649,7 @@ static void StrtoI64(FieldParseContext *ctx) /* f = "~/data.table/src/freadLookups.h" cat("const long double pow10lookup[601] = {\n", file=f, append=FALSE) -for (i in (-300):(299)) cat("1.0E",i,"L,\n", sep="", file=f, append=TRUE) +for (i in (-300):(299)) cat("1.0E",abs(i),"L,\n", sep="", file=f, append=TRUE) cat("1.0E300L\n};\n", file=f, append=TRUE) */ @@ -777,12 +777,14 @@ static void parse_double_regular(FieldParseContext *ctx) // fail to be encoded by the compiler, even though the values can actually // be stored correctly. int_fast8_t extra = e < 0 ? e + 300 : e - 300; - r *= pow10lookup[extra + 300]; + r = extra < 0 ? r/pow10lookup[extra + 300] : r*pow10lookup[extra + 300]; e -= extra; } e += 300; // lookup table is arranged from -300 (0) to +300 (600) - r *= pow10lookup[e]; + // pow10lookup is always positive since sub-0 powers of 10 cannot + // be represented exactly, which can lead to (rare) precision errors, #4461 + r = e < 300 ? r/pow10lookup[e] : r*pow10lookup[e]; *target = (double)(neg? -r : r); *(ctx->ch) = ch; return; diff --git a/src/freadLookups.h b/src/freadLookups.h index bb736a60ac..f7b8b1d6ca 100644 --- a/src/freadLookups.h +++ b/src/freadLookups.h @@ -28,306 +28,306 @@ const uint8_t hexdigits[256] = { const long double pow10lookup[601] = { -1.0E-300L, -1.0E-299L, -1.0E-298L, -1.0E-297L, -1.0E-296L, -1.0E-295L, -1.0E-294L, -1.0E-293L, -1.0E-292L, -1.0E-291L, -1.0E-290L, -1.0E-289L, -1.0E-288L, -1.0E-287L, -1.0E-286L, -1.0E-285L, -1.0E-284L, -1.0E-283L, -1.0E-282L, -1.0E-281L, -1.0E-280L, -1.0E-279L, -1.0E-278L, -1.0E-277L, -1.0E-276L, -1.0E-275L, -1.0E-274L, -1.0E-273L, -1.0E-272L, -1.0E-271L, -1.0E-270L, -1.0E-269L, -1.0E-268L, -1.0E-267L, -1.0E-266L, -1.0E-265L, -1.0E-264L, -1.0E-263L, -1.0E-262L, -1.0E-261L, -1.0E-260L, -1.0E-259L, -1.0E-258L, -1.0E-257L, -1.0E-256L, -1.0E-255L, -1.0E-254L, -1.0E-253L, -1.0E-252L, -1.0E-251L, -1.0E-250L, -1.0E-249L, -1.0E-248L, -1.0E-247L, -1.0E-246L, -1.0E-245L, -1.0E-244L, -1.0E-243L, -1.0E-242L, -1.0E-241L, -1.0E-240L, -1.0E-239L, -1.0E-238L, -1.0E-237L, -1.0E-236L, -1.0E-235L, -1.0E-234L, -1.0E-233L, -1.0E-232L, -1.0E-231L, -1.0E-230L, -1.0E-229L, -1.0E-228L, -1.0E-227L, -1.0E-226L, -1.0E-225L, -1.0E-224L, -1.0E-223L, -1.0E-222L, -1.0E-221L, -1.0E-220L, -1.0E-219L, -1.0E-218L, -1.0E-217L, -1.0E-216L, -1.0E-215L, -1.0E-214L, -1.0E-213L, -1.0E-212L, -1.0E-211L, -1.0E-210L, -1.0E-209L, -1.0E-208L, -1.0E-207L, -1.0E-206L, -1.0E-205L, -1.0E-204L, -1.0E-203L, -1.0E-202L, -1.0E-201L, -1.0E-200L, -1.0E-199L, -1.0E-198L, -1.0E-197L, -1.0E-196L, -1.0E-195L, -1.0E-194L, -1.0E-193L, -1.0E-192L, -1.0E-191L, -1.0E-190L, -1.0E-189L, -1.0E-188L, -1.0E-187L, -1.0E-186L, -1.0E-185L, -1.0E-184L, -1.0E-183L, -1.0E-182L, -1.0E-181L, -1.0E-180L, -1.0E-179L, -1.0E-178L, -1.0E-177L, -1.0E-176L, -1.0E-175L, -1.0E-174L, -1.0E-173L, -1.0E-172L, -1.0E-171L, -1.0E-170L, -1.0E-169L, -1.0E-168L, -1.0E-167L, -1.0E-166L, -1.0E-165L, -1.0E-164L, -1.0E-163L, -1.0E-162L, -1.0E-161L, -1.0E-160L, -1.0E-159L, -1.0E-158L, -1.0E-157L, -1.0E-156L, -1.0E-155L, -1.0E-154L, -1.0E-153L, -1.0E-152L, -1.0E-151L, -1.0E-150L, -1.0E-149L, -1.0E-148L, -1.0E-147L, -1.0E-146L, -1.0E-145L, -1.0E-144L, -1.0E-143L, -1.0E-142L, -1.0E-141L, -1.0E-140L, -1.0E-139L, -1.0E-138L, -1.0E-137L, -1.0E-136L, -1.0E-135L, -1.0E-134L, -1.0E-133L, -1.0E-132L, -1.0E-131L, -1.0E-130L, -1.0E-129L, -1.0E-128L, -1.0E-127L, -1.0E-126L, -1.0E-125L, -1.0E-124L, -1.0E-123L, -1.0E-122L, -1.0E-121L, -1.0E-120L, -1.0E-119L, -1.0E-118L, -1.0E-117L, -1.0E-116L, -1.0E-115L, -1.0E-114L, -1.0E-113L, -1.0E-112L, -1.0E-111L, -1.0E-110L, -1.0E-109L, -1.0E-108L, -1.0E-107L, -1.0E-106L, -1.0E-105L, -1.0E-104L, -1.0E-103L, -1.0E-102L, -1.0E-101L, -1.0E-100L, -1.0E-99L, -1.0E-98L, -1.0E-97L, -1.0E-96L, -1.0E-95L, -1.0E-94L, -1.0E-93L, -1.0E-92L, -1.0E-91L, -1.0E-90L, -1.0E-89L, -1.0E-88L, -1.0E-87L, -1.0E-86L, -1.0E-85L, -1.0E-84L, -1.0E-83L, -1.0E-82L, -1.0E-81L, -1.0E-80L, -1.0E-79L, -1.0E-78L, -1.0E-77L, -1.0E-76L, -1.0E-75L, -1.0E-74L, -1.0E-73L, -1.0E-72L, -1.0E-71L, -1.0E-70L, -1.0E-69L, -1.0E-68L, -1.0E-67L, -1.0E-66L, -1.0E-65L, -1.0E-64L, -1.0E-63L, -1.0E-62L, -1.0E-61L, -1.0E-60L, -1.0E-59L, -1.0E-58L, -1.0E-57L, -1.0E-56L, -1.0E-55L, -1.0E-54L, -1.0E-53L, -1.0E-52L, -1.0E-51L, -1.0E-50L, -1.0E-49L, -1.0E-48L, -1.0E-47L, -1.0E-46L, -1.0E-45L, -1.0E-44L, -1.0E-43L, -1.0E-42L, -1.0E-41L, -1.0E-40L, -1.0E-39L, -1.0E-38L, -1.0E-37L, -1.0E-36L, -1.0E-35L, -1.0E-34L, -1.0E-33L, -1.0E-32L, -1.0E-31L, -1.0E-30L, -1.0E-29L, -1.0E-28L, -1.0E-27L, -1.0E-26L, -1.0E-25L, -1.0E-24L, -1.0E-23L, -1.0E-22L, -1.0E-21L, -1.0E-20L, -1.0E-19L, -1.0E-18L, -1.0E-17L, -1.0E-16L, -1.0E-15L, -1.0E-14L, -1.0E-13L, -1.0E-12L, -1.0E-11L, -1.0E-10L, -1.0E-9L, -1.0E-8L, -1.0E-7L, -1.0E-6L, -1.0E-5L, -1.0E-4L, -1.0E-3L, -1.0E-2L, -1.0E-1L, +1.0E300L, +1.0E299L, +1.0E298L, +1.0E297L, +1.0E296L, +1.0E295L, +1.0E294L, +1.0E293L, +1.0E292L, +1.0E291L, +1.0E290L, +1.0E289L, +1.0E288L, +1.0E287L, +1.0E286L, +1.0E285L, +1.0E284L, +1.0E283L, +1.0E282L, +1.0E281L, +1.0E280L, +1.0E279L, +1.0E278L, +1.0E277L, +1.0E276L, +1.0E275L, +1.0E274L, +1.0E273L, +1.0E272L, +1.0E271L, +1.0E270L, +1.0E269L, +1.0E268L, +1.0E267L, +1.0E266L, +1.0E265L, +1.0E264L, +1.0E263L, +1.0E262L, +1.0E261L, +1.0E260L, +1.0E259L, +1.0E258L, +1.0E257L, +1.0E256L, +1.0E255L, +1.0E254L, +1.0E253L, +1.0E252L, +1.0E251L, +1.0E250L, +1.0E249L, +1.0E248L, +1.0E247L, +1.0E246L, +1.0E245L, +1.0E244L, +1.0E243L, +1.0E242L, +1.0E241L, +1.0E240L, +1.0E239L, +1.0E238L, +1.0E237L, +1.0E236L, +1.0E235L, +1.0E234L, +1.0E233L, +1.0E232L, +1.0E231L, +1.0E230L, +1.0E229L, +1.0E228L, +1.0E227L, +1.0E226L, +1.0E225L, +1.0E224L, +1.0E223L, +1.0E222L, +1.0E221L, +1.0E220L, +1.0E219L, +1.0E218L, +1.0E217L, +1.0E216L, +1.0E215L, +1.0E214L, +1.0E213L, +1.0E212L, +1.0E211L, +1.0E210L, +1.0E209L, +1.0E208L, +1.0E207L, +1.0E206L, +1.0E205L, +1.0E204L, +1.0E203L, +1.0E202L, +1.0E201L, +1.0E200L, +1.0E199L, +1.0E198L, +1.0E197L, +1.0E196L, +1.0E195L, +1.0E194L, +1.0E193L, +1.0E192L, +1.0E191L, +1.0E190L, +1.0E189L, +1.0E188L, +1.0E187L, +1.0E186L, +1.0E185L, +1.0E184L, +1.0E183L, +1.0E182L, +1.0E181L, +1.0E180L, +1.0E179L, +1.0E178L, +1.0E177L, +1.0E176L, +1.0E175L, +1.0E174L, +1.0E173L, +1.0E172L, +1.0E171L, +1.0E170L, +1.0E169L, +1.0E168L, +1.0E167L, +1.0E166L, +1.0E165L, +1.0E164L, +1.0E163L, +1.0E162L, +1.0E161L, +1.0E160L, +1.0E159L, +1.0E158L, +1.0E157L, +1.0E156L, +1.0E155L, +1.0E154L, +1.0E153L, +1.0E152L, +1.0E151L, +1.0E150L, +1.0E149L, +1.0E148L, +1.0E147L, +1.0E146L, +1.0E145L, +1.0E144L, +1.0E143L, +1.0E142L, +1.0E141L, +1.0E140L, +1.0E139L, +1.0E138L, +1.0E137L, +1.0E136L, +1.0E135L, +1.0E134L, +1.0E133L, +1.0E132L, +1.0E131L, +1.0E130L, +1.0E129L, +1.0E128L, +1.0E127L, +1.0E126L, +1.0E125L, +1.0E124L, +1.0E123L, +1.0E122L, +1.0E121L, +1.0E120L, +1.0E119L, +1.0E118L, +1.0E117L, +1.0E116L, +1.0E115L, +1.0E114L, +1.0E113L, +1.0E112L, +1.0E111L, +1.0E110L, +1.0E109L, +1.0E108L, +1.0E107L, +1.0E106L, +1.0E105L, +1.0E104L, +1.0E103L, +1.0E102L, +1.0E101L, +1.0E100L, +1.0E99L, +1.0E98L, +1.0E97L, +1.0E96L, +1.0E95L, +1.0E94L, +1.0E93L, +1.0E92L, +1.0E91L, +1.0E90L, +1.0E89L, +1.0E88L, +1.0E87L, +1.0E86L, +1.0E85L, +1.0E84L, +1.0E83L, +1.0E82L, +1.0E81L, +1.0E80L, +1.0E79L, +1.0E78L, +1.0E77L, +1.0E76L, +1.0E75L, +1.0E74L, +1.0E73L, +1.0E72L, +1.0E71L, +1.0E70L, +1.0E69L, +1.0E68L, +1.0E67L, +1.0E66L, +1.0E65L, +1.0E64L, +1.0E63L, +1.0E62L, +1.0E61L, +1.0E60L, +1.0E59L, +1.0E58L, +1.0E57L, +1.0E56L, +1.0E55L, +1.0E54L, +1.0E53L, +1.0E52L, +1.0E51L, +1.0E50L, +1.0E49L, +1.0E48L, +1.0E47L, +1.0E46L, +1.0E45L, +1.0E44L, +1.0E43L, +1.0E42L, +1.0E41L, +1.0E40L, +1.0E39L, +1.0E38L, +1.0E37L, +1.0E36L, +1.0E35L, +1.0E34L, +1.0E33L, +1.0E32L, +1.0E31L, +1.0E30L, +1.0E29L, +1.0E28L, +1.0E27L, +1.0E26L, +1.0E25L, +1.0E24L, +1.0E23L, +1.0E22L, +1.0E21L, +1.0E20L, +1.0E19L, +1.0E18L, +1.0E17L, +1.0E16L, +1.0E15L, +1.0E14L, +1.0E13L, +1.0E12L, +1.0E11L, +1.0E10L, +1.0E9L, +1.0E8L, +1.0E7L, +1.0E6L, +1.0E5L, +1.0E4L, +1.0E3L, +1.0E2L, +1.0E1L, 1.0E0L, 1.0E1L, 1.0E2L, From d19629cef9c7dce3b243ba0c2e5c25d4225aaaf1 Mon Sep 17 00:00:00 2001 From: Matt Dowle Date: Fri, 27 Aug 2021 07:40:01 -0600 Subject: [PATCH 2/3] clearer news item for folk scanning news quickly, and simpler test as it was distracting to see the number as a column name too --- NEWS.md | 2 +- inst/tests/tests.Rraw | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/NEWS.md b/NEWS.md index b8836fe0b0..6a7c3ba948 100644 --- a/NEWS.md +++ b/NEWS.md @@ -295,7 +295,7 @@ 39. `DT[i, sum(b), by=grp]` (and other optimized-by-group aggregates: `mean`, `var`, `sd`, `median`, `prod`, `min`, `max`, `first`, `last`, `head` and `tail`) could segfault if `i` contained row numbers and one or more were NA, [#1994](https://github.com/Rdatatable/data.table/issues/1994). Thanks to Arun Srinivasan for reporting, and Benjamin Schwendinger for the PR. -40. In some rare cases, `fread` parsed a very small difference in numeric input as compared to `read.table`, [#4461](https://github.com/Rdatatable/data.table/issues/4461). The latter is more accurate (in that it produces the double-precision representation that's closer to the base-10 value), so this is indeed an `fread` error. Thanks @gmbecker for the report. +40. `identical(fread(text="A\n0.8060667366\n")$A, 0.8060667366)` is now TRUE, [#4461](https://github.com/Rdatatable/data.table/issues/4461). `fread` was using `*10^-n` rather than `/10^n` resulting in `0.80606673659999994` vs `0.80606673660000006`. `fread()` now matches R's parser and `read.table` identically in this respect. Thanks to Gabe Becker for requesting consistency, and Michael Chirico for the PR. ## NOTES diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index bf26241fc5..1d39b2d817 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -18107,8 +18107,6 @@ if (base::getRversion() >= "4.1.0") { test(2212.33, EVAL("iris |> DT('setosa', on='Species')"), {tt=droprn(iris[iris$Species=="setosa",]); tt$Species=as.character(tt$Species); tt}) } -# Rare precision loss owing to unrepresentability of powers of 10^(-n), #4461 -exchar = "0.8060667366" -exnum = 0.8060667366 -test(2213, identical(fread(text = c(exchar, exchar))$V1[1L], exnum)) +# precision powers of 10^(-n), #4461 +test(2213, identical(fread(text="A\n0.8060667366\n")$A, 0.8060667366)) From d1206196a64e9fc0367a93498406fa80d796bff6 Mon Sep 17 00:00:00 2001 From: Matt Dowle Date: Fri, 27 Aug 2021 08:16:14 -0600 Subject: [PATCH 3/3] drop lower half of lookup table as @QuLogic suggested --- src/fread.c | 13 +- src/fread.h | 2 +- src/freadLookups.h | 303 +-------------------------------------------- 3 files changed, 9 insertions(+), 309 deletions(-) diff --git a/src/fread.c b/src/fread.c index 317e20879e..e0a32d3e14 100644 --- a/src/fread.c +++ b/src/fread.c @@ -652,8 +652,8 @@ static void StrtoI64(FieldParseContext *ctx) // TODO: review ERANGE checks and tests; that range outside [1.7e-308,1.7e+308] coerces to [0.0,Inf] /* f = "~/data.table/src/freadLookups.h" -cat("const long double pow10lookup[601] = {\n", file=f, append=FALSE) -for (i in (-300):(299)) cat("1.0E",abs(i),"L,\n", sep="", file=f, append=TRUE) +cat("const long double pow10lookup[301] = {\n", file=f, append=FALSE) +for (i in 0:299) cat("1.0E",i,"L,\n", sep="", file=f, append=TRUE) cat("1.0E300L\n};\n", file=f, append=TRUE) */ @@ -780,14 +780,13 @@ static void parse_double_regular_core(const char **pch, double *target) // fail to be encoded by the compiler, even though the values can actually // be stored correctly. int_fast8_t extra = e < 0 ? e + 300 : e - 300; - r = extra < 0 ? r/pow10lookup[extra + 300] : r*pow10lookup[extra + 300]; + r = extra<0 ? r/pow10lookup[-extra] : r*pow10lookup[extra]; e -= extra; } - e += 300; // lookup table is arranged from -300 (0) to +300 (600) - // pow10lookup is always positive since sub-0 powers of 10 cannot - // be represented exactly, which can lead to (rare) precision errors, #4461 - r = e < 300 ? r/pow10lookup[e] : r*pow10lookup[e]; + // pow10lookup[301] contains 10^(0:300). Storing negative powers there too + // avoids this ternary but is slightly less accurate in some cases, #4461 + r = e < 0 ? r/pow10lookup[-e] : r*pow10lookup[e]; *target = (double)(neg? -r : r); *pch = ch; return; diff --git a/src/fread.h b/src/fread.h index c0e9669d01..446da18e4b 100644 --- a/src/fread.h +++ b/src/fread.h @@ -37,7 +37,7 @@ typedef enum { extern int8_t typeSize[NUMTYPE]; extern const char typeName[NUMTYPE][10]; -extern const long double pow10lookup[601]; +extern const long double pow10lookup[301]; extern const uint8_t hexdigits[256]; diff --git a/src/freadLookups.h b/src/freadLookups.h index 53c67bd1af..103d644da4 100644 --- a/src/freadLookups.h +++ b/src/freadLookups.h @@ -142,307 +142,8 @@ const int32_t cumDaysCycleYears[401] = { 9496, 9862, 10227, 10592, 146097// total days in 400 years }; -const long double pow10lookup[601] = { -1.0E300L, -1.0E299L, -1.0E298L, -1.0E297L, -1.0E296L, -1.0E295L, -1.0E294L, -1.0E293L, -1.0E292L, -1.0E291L, -1.0E290L, -1.0E289L, -1.0E288L, -1.0E287L, -1.0E286L, -1.0E285L, -1.0E284L, -1.0E283L, -1.0E282L, -1.0E281L, -1.0E280L, -1.0E279L, -1.0E278L, -1.0E277L, -1.0E276L, -1.0E275L, -1.0E274L, -1.0E273L, -1.0E272L, -1.0E271L, -1.0E270L, -1.0E269L, -1.0E268L, -1.0E267L, -1.0E266L, -1.0E265L, -1.0E264L, -1.0E263L, -1.0E262L, -1.0E261L, -1.0E260L, -1.0E259L, -1.0E258L, -1.0E257L, -1.0E256L, -1.0E255L, -1.0E254L, -1.0E253L, -1.0E252L, -1.0E251L, -1.0E250L, -1.0E249L, -1.0E248L, -1.0E247L, -1.0E246L, -1.0E245L, -1.0E244L, -1.0E243L, -1.0E242L, -1.0E241L, -1.0E240L, -1.0E239L, -1.0E238L, -1.0E237L, -1.0E236L, -1.0E235L, -1.0E234L, -1.0E233L, -1.0E232L, -1.0E231L, -1.0E230L, -1.0E229L, -1.0E228L, -1.0E227L, -1.0E226L, -1.0E225L, -1.0E224L, -1.0E223L, -1.0E222L, -1.0E221L, -1.0E220L, -1.0E219L, -1.0E218L, -1.0E217L, -1.0E216L, -1.0E215L, -1.0E214L, -1.0E213L, -1.0E212L, -1.0E211L, -1.0E210L, -1.0E209L, -1.0E208L, -1.0E207L, -1.0E206L, -1.0E205L, -1.0E204L, -1.0E203L, -1.0E202L, -1.0E201L, -1.0E200L, -1.0E199L, -1.0E198L, -1.0E197L, -1.0E196L, -1.0E195L, -1.0E194L, -1.0E193L, -1.0E192L, -1.0E191L, -1.0E190L, -1.0E189L, -1.0E188L, -1.0E187L, -1.0E186L, -1.0E185L, -1.0E184L, -1.0E183L, -1.0E182L, -1.0E181L, -1.0E180L, -1.0E179L, -1.0E178L, -1.0E177L, -1.0E176L, -1.0E175L, -1.0E174L, -1.0E173L, -1.0E172L, -1.0E171L, -1.0E170L, -1.0E169L, -1.0E168L, -1.0E167L, -1.0E166L, -1.0E165L, -1.0E164L, -1.0E163L, -1.0E162L, -1.0E161L, -1.0E160L, -1.0E159L, -1.0E158L, -1.0E157L, -1.0E156L, -1.0E155L, -1.0E154L, -1.0E153L, -1.0E152L, -1.0E151L, -1.0E150L, -1.0E149L, -1.0E148L, -1.0E147L, -1.0E146L, -1.0E145L, -1.0E144L, -1.0E143L, -1.0E142L, -1.0E141L, -1.0E140L, -1.0E139L, -1.0E138L, -1.0E137L, -1.0E136L, -1.0E135L, -1.0E134L, -1.0E133L, -1.0E132L, -1.0E131L, -1.0E130L, -1.0E129L, -1.0E128L, -1.0E127L, -1.0E126L, -1.0E125L, -1.0E124L, -1.0E123L, -1.0E122L, -1.0E121L, -1.0E120L, -1.0E119L, -1.0E118L, -1.0E117L, -1.0E116L, -1.0E115L, -1.0E114L, -1.0E113L, -1.0E112L, -1.0E111L, -1.0E110L, -1.0E109L, -1.0E108L, -1.0E107L, -1.0E106L, -1.0E105L, -1.0E104L, -1.0E103L, -1.0E102L, -1.0E101L, -1.0E100L, -1.0E99L, -1.0E98L, -1.0E97L, -1.0E96L, -1.0E95L, -1.0E94L, -1.0E93L, -1.0E92L, -1.0E91L, -1.0E90L, -1.0E89L, -1.0E88L, -1.0E87L, -1.0E86L, -1.0E85L, -1.0E84L, -1.0E83L, -1.0E82L, -1.0E81L, -1.0E80L, -1.0E79L, -1.0E78L, -1.0E77L, -1.0E76L, -1.0E75L, -1.0E74L, -1.0E73L, -1.0E72L, -1.0E71L, -1.0E70L, -1.0E69L, -1.0E68L, -1.0E67L, -1.0E66L, -1.0E65L, -1.0E64L, -1.0E63L, -1.0E62L, -1.0E61L, -1.0E60L, -1.0E59L, -1.0E58L, -1.0E57L, -1.0E56L, -1.0E55L, -1.0E54L, -1.0E53L, -1.0E52L, -1.0E51L, -1.0E50L, -1.0E49L, -1.0E48L, -1.0E47L, -1.0E46L, -1.0E45L, -1.0E44L, -1.0E43L, -1.0E42L, -1.0E41L, -1.0E40L, -1.0E39L, -1.0E38L, -1.0E37L, -1.0E36L, -1.0E35L, -1.0E34L, -1.0E33L, -1.0E32L, -1.0E31L, -1.0E30L, -1.0E29L, -1.0E28L, -1.0E27L, -1.0E26L, -1.0E25L, -1.0E24L, -1.0E23L, -1.0E22L, -1.0E21L, -1.0E20L, -1.0E19L, -1.0E18L, -1.0E17L, -1.0E16L, -1.0E15L, -1.0E14L, -1.0E13L, -1.0E12L, -1.0E11L, -1.0E10L, -1.0E9L, -1.0E8L, -1.0E7L, -1.0E6L, -1.0E5L, -1.0E4L, -1.0E3L, -1.0E2L, -1.0E1L, + +const long double pow10lookup[301] = { 1.0E0L, 1.0E1L, 1.0E2L,