Record Grotto half-ulp tables and comparison geneval, and factor shared beaver terms before the quotient.
Horner and window evaluation need those tables in the tree. Comparison geneval opens the same value words as a Doerner–Shelat key. A factor common to every polynomial term is multiplied first so that preprocessing stays smaller. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
3f10e05176
commit
875f09fec1
14 changed files with 42668 additions and 184 deletions
|
|
@ -169,3 +169,84 @@ TEST(PrincipalLut, RejectsBadPrecisionAndDomain)
|
|||
EXPECT_THROW(grotto::eval_principal(grotto::principal::exp, 8, -1), std::out_of_range);
|
||||
EXPECT_THROW(grotto::eval_principal(grotto::principal::sin, 8, 257), std::out_of_range);
|
||||
}
|
||||
|
||||
long double recip_reference(grotto::principal which, long double x)
|
||||
{
|
||||
switch (which)
|
||||
{
|
||||
case grotto::principal::inv:
|
||||
return 1.0L / x;
|
||||
case grotto::principal::rsqrt:
|
||||
return 1.0L / sqrtl(x);
|
||||
case grotto::principal::invsq:
|
||||
return 1.0L / (x * x);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void expect_recip(grotto::principal which, unsigned k, std::int64_t raw)
|
||||
{
|
||||
const auto y = grotto::eval_principal(which, k, raw);
|
||||
const long double x = ldexpl(static_cast<long double>(raw), -static_cast<int>(k));
|
||||
const long double truth = recip_reference(which, x) * ldexpl(1.0L, static_cast<int>(k));
|
||||
EXPECT_LE(fabsl(static_cast<long double>(y) - truth), 1.5L)
|
||||
<< static_cast<int>(which) << " k=" << k << " raw=" << raw << " y=" << y;
|
||||
}
|
||||
|
||||
TEST(PrincipalLut, ReciprocalPieceCounts)
|
||||
{
|
||||
const unsigned inv[] = {2u, 3u, 5u, 9u, 18u, 35u, 69u};
|
||||
const unsigned rsqrt[] = {1u, 2u, 3u, 6u, 12u, 24u, 48u};
|
||||
const unsigned invsq[] = {2u, 4u, 8u, 15u, 29u, 57u, 113u};
|
||||
unsigned slot = 0;
|
||||
for (unsigned k : grotto::principal_precisions)
|
||||
{
|
||||
EXPECT_EQ(grotto::principal_parts(grotto::principal::inv, k), inv[slot]);
|
||||
EXPECT_EQ(grotto::principal_parts(grotto::principal::rsqrt, k), rsqrt[slot]);
|
||||
EXPECT_EQ(grotto::principal_parts(grotto::principal::invsq, k), invsq[slot]);
|
||||
++slot;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PrincipalLut, ReciprocalWithinOneAndAHalfUlp)
|
||||
{
|
||||
const grotto::principal maps[] = {
|
||||
grotto::principal::inv,
|
||||
grotto::principal::rsqrt,
|
||||
grotto::principal::invsq,
|
||||
};
|
||||
for (const auto which : maps)
|
||||
{
|
||||
for (unsigned k : {8u, 12u, 16u})
|
||||
{
|
||||
const auto left = std::int64_t{1} << (k - 1);
|
||||
const auto right = std::int64_t{1} << k;
|
||||
for (std::int64_t raw = left; raw <= right; ++raw)
|
||||
expect_recip(which, k, raw);
|
||||
}
|
||||
for (unsigned k : {20u, 24u, 28u, 32u})
|
||||
{
|
||||
const auto left = std::int64_t{1} << (k - 1);
|
||||
const auto right = std::int64_t{1} << k;
|
||||
const std::int64_t step = std::max<std::int64_t>(1, (right - left) / 4096);
|
||||
expect_recip(which, k, left);
|
||||
expect_recip(which, k, right);
|
||||
for (std::int64_t raw = left; raw < right; raw += step)
|
||||
expect_recip(which, k, raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PrincipalLut, ReciprocalRejectsOutsidePrincipalInterval)
|
||||
{
|
||||
EXPECT_THROW(grotto::eval_principal(grotto::principal::inv, 7, 128), std::invalid_argument);
|
||||
EXPECT_THROW(grotto::eval_principal(grotto::principal::inv, 8, 127), std::out_of_range);
|
||||
EXPECT_THROW(grotto::eval_principal(grotto::principal::inv, 8, 257), std::out_of_range);
|
||||
EXPECT_THROW(grotto::eval_principal(grotto::principal::rsqrt, 12, 2047), std::out_of_range);
|
||||
EXPECT_THROW(grotto::eval_principal(grotto::principal::invsq, 16, (std::int64_t{1} << 16) + 1), std::out_of_range);
|
||||
EXPECT_THROW(grotto::eval_principal(grotto::principal::invsq, 8, -1), std::out_of_range);
|
||||
EXPECT_NO_THROW(grotto::eval_principal(grotto::principal::inv, 8, 128));
|
||||
EXPECT_NO_THROW(grotto::eval_principal(grotto::principal::rsqrt, 8, 256));
|
||||
EXPECT_NO_THROW(grotto::eval_principal(grotto::principal::invsq, 12, 4096));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue