[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master cdeaeb09 4/4: Expunge a redundant local funct
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master cdeaeb09 4/4: Expunge a redundant local function |
Date: |
Fri, 27 May 2022 11:49:24 -0400 (EDT) |
branch: master
commit cdeaeb09079fc0cfe631b3fb8d0a6c18a5a82020
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
Expunge a redundant local function
---
math_functions_test.cpp | 84 +++++--------------------------------------------
1 file changed, 7 insertions(+), 77 deletions(-)
diff --git a/math_functions_test.cpp b/math_functions_test.cpp
index 60013009..554b0f52 100644
--- a/math_functions_test.cpp
+++ b/math_functions_test.cpp
@@ -132,72 +132,6 @@ struct i_upper_n_over_n_from_i_naive
return T(-1) + std::pow((T(1) + i), T(1) / n);
}
};
-
-// This implementation uses lmi::expm1() and lmi::log1p() for type T,
-// whereas production uses those functions for type 'double' only.
-
-template<typename T, int n>
-struct i_upper_n_over_n_from_i_T
-{
- static_assert(std::is_floating_point_v<T>);
- T operator()(T const& i) const
- {
- static T const reciprocal_n = T(1) / n;
- T const z = lmi::expm1(lmi::log1p(i) * reciprocal_n);
- // The production version should be substantially equivalent,
- // so it should probably be used instead of this function.
- // Before removing this, though, it's a good idea to test that
- // hypothesis, especially because this version stores and uses
- // the reciprocal of 'n'.
- T const y = i_upper_n_over_n_from_i<T,n>()(i);
- if(y != z)
- {
- std::cout
- << std::setprecision(23)
- << "DISCREPANCY:\n"
- << y << " i_upper_n_over_n_from_i\n"
- << z << " i_upper_n_over_n_from_i_T\n"
- << std::endl
- ;
- }
- // That message prints exactly once, in sample_results():
- //
- // 0.00327373978219886392598 long double prec, production template
- // 0.00327373978219886392598 long double prec, expm1 and log1p
- // 0.00327373978219886395923 long double prec, pow
- // 0.0032737397821988637 (correctly rounded binary64)
- // 0.00327373978219886374239 double prec, production template
- // DISCREPANCY:
- // 0.00327373978219886374239 i_upper_n_over_n_from_i
- // 0.00327373978219886330870 i_upper_n_over_n_from_i_T
- // 0.00327373978219886330870 double prec, expm1 and log1p
- //
- // Analysis: The correctly-rounded result is known from Wolfram.
- // It matches the i_upper_n_over_n_from_i() production function.
- // However, local i_upper_n_over_n_from_i_T() doesn't match.
- // The only difference that could plausibly account for this is
- // storing and using the reciprocal of 'n' in the local function.
- // Even though this is only one test case, it is fair to conclude
- // that using the reciprocal does not uniformly improve accuracy.
- //
- // Conclusion: local i_upper_n_over_n_from_i_T() should be expunged,
- // and production function i_upper_n_over_n_from_i() used instead.
- // This discussion provides concrete support for commit d7c5304dd12bf.
- //
- // Note that the 0.0032737397821988637 is correctly rounded for
- // double precision, not for long double. Thus, the long double
- // tests above (disregarding the less accurate pow() version)
- // give a different answer, which must be compared to the
- // verified answer taken to more decimal places:
- // 0.00327373978219886392598 long double prec, production template
- //
0.0032737397821988638592943204158789680534098426263396651605608434...
- // 0.0032737397821988637 = 3F6AD187A99AE58B (correctly rounded
double)
- // That extended-precision value is closer to the theoretical true
- // result than the double-precision touchstone.
-
- return z;
- }
-};
} // Unnamed namespace.
// These 'mete[01]' functions perform the same sets of operations
@@ -233,26 +167,26 @@ void mete1()
}
// These 'mete[23]' functions perform the same operation using
-// different implementations.
+// different types.
-// This implementation uses type 'double'.
+// This test uses type 'double'.
void mete2()
{
double volatile x;
for(int j = 0; j < 100000; ++j)
{
- x = i_upper_n_over_n_from_i_T<double,365>()(0.01);
+ x = i_upper_n_over_n_from_i<double,365>()(0.01);
}
stifle_unused_warning(x);
}
-// This implementation uses type 'long double'.
+// This test uses type 'long double'.
void mete3()
{
long double volatile x;
for(int j = 0; j < 100000; ++j)
{
- x = i_upper_n_over_n_from_i_T<long double,365>()(0.01);
+ x = i_upper_n_over_n_from_i<long double,365>()(0.01);
}
stifle_unused_warning(x);
}
@@ -745,14 +679,12 @@ void sample_results()
<< " 000000000111111111122\n"
<< " 123456789012345678901\n"
<< " " << i_upper_n_over_n_from_i <long double,12>()(intrate)
- << " long double prec, production template\n"
+ << " long double prec, expm1 and log1p (production)\n"
;
#if defined LMI_X87
fenv_precision(fe_ldblprec);
#endif // defined LMI_X87
std::cout
- << " " << i_upper_n_over_n_from_i_T <long double,12>()(intrate)
- << " long double prec, expm1 and log1p\n"
<< " " << i_upper_n_over_n_from_i_naive<long double,12>()(intrate)
<< " long double prec, pow\n"
;
@@ -763,9 +695,7 @@ void sample_results()
std::cout
<< " 0.0032737397821988637 (correctly rounded binary64)\n"
<< " " << i_upper_n_over_n_from_i <double,12>()(intrate)
- << " double prec, production template\n"
- << " " << i_upper_n_over_n_from_i_T <double,12>()(intrate)
- << " double prec, expm1 and log1p\n"
+ << " double prec, expm1 and log1p (production)\n"
<< " " << i_upper_n_over_n_from_i_naive<double,12>()(intrate)
<< " double prec, pow\n"
<< std::endl;