[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master cf516cc 6/8: Remove code added in the last co
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master cf516cc 6/8: Remove code added in the last commit to support its conclusions |
Date: |
Fri, 30 Jul 2021 16:14:48 -0400 (EDT) |
branch: master
commit cf516cc117c80e477e20db70b05a10f461d68c9c
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
Remove code added in the last commit to support its conclusions
Alternative algorithms that failed to prove their worth needn't be
retained; they can always be checked out from git.
---
zero.hpp | 280 ----------------------------------------------------------
zero_test.cpp | 26 ++++--
2 files changed, 17 insertions(+), 289 deletions(-)
diff --git a/zero.hpp b/zero.hpp
index 6b85363..3d33e45 100644
--- a/zero.hpp
+++ b/zero.hpp
@@ -544,22 +544,6 @@ root_type lmi_root
}
s = e;
e = d;
-//#define USE_CHANDRUPATLA_IQI_CRITERION
-// evaluations max mean sample-std-dev
-// 7332 65 18.9 7.13 HEAD (brent)
-// 8545 66 22.0 12.90 this (IQI more stringent)
-#if defined USE_CHANDRUPATLA_IQI_CRITERION
- double xi = ( b - c) / ( a - c);
- double phi = (fb - fc) / (fa - fc);
- // Chandrupatla acceptance criterion
- bool const k0 =
- interpolate_inverse_quadratic != impetus
- || (
- (phi * phi) < xi
- && ((1.0 - phi) * (1.0 - phi)) < (1.0 - xi)
- )
- ;
-#else // !defined USE_CHANDRUPATLA_IQI_CRITERION
// Use the criteria in Brent's ALGOL, which differ
// slightly from their descriptions in his text.
//
@@ -567,7 +551,6 @@ root_type lmi_root
// "we reject i [i.e., b + p/q] if 2|p| ≥ 3|mq|"
// Difference: the ALGOL subtracts tol×|q| [i.e., δ|q|]
bool const k0 = 2.0 * p < 3.0 * m * q - std::fabs(tol * q);
-#endif // !defined USE_CHANDRUPATLA_IQI_CRITERION
// AfMWD says on page 50:
// "Let e be the value of p/q at the step before the
// last one."
@@ -660,20 +643,6 @@ root_type decimal_root
}
};
-//#define USE_CHANDRUPATLA_ALGORITHM
-#if defined USE_CHANDRUPATLA_ALGORITHM
-// evaluations max mean sample-std-dev
-// 7332 65 18.9 7.13 HEAD (brent)
-// 9149 59 23.6 11.13 this (chandrupatla)
- (void)&bias;
- (void)&sprauchling_limit;
- auto z = scherer_chandrupatla
- (fr
- ,round_dec(bound0)
- ,round_dec(bound1)
- ,3.14159 // disregarded
- );
-#else // !defined USE_CHANDRUPATLA_ALGORITHM
auto z = lmi_root
(fr
,round_dec(bound0)
@@ -683,7 +652,6 @@ root_type decimal_root
,os_trace
,bias
);
-#endif // !defined USE_CHANDRUPATLA_ALGORITHM
z.root = round_dec(z.root);
os_trace << " function evaluations: " << z.n_eval;
z.n_eval = lmi::ssize(m);
@@ -692,254 +660,6 @@ root_type decimal_root
return z;
}
-//#include <iostream>
-
-// The next two function templates are adapted from the pseudocode here:
-// Philipp O. J. Scherer
-// Computational Physics (2nd ed.)
-// ISBN 978-3-319-00400-6
-// with numerous corrections.
-
-template<typename FunctionalType>
-root_type scherer_brent
- (FunctionalType& f
- ,double a
- ,double b
- ,double t
- )
-{
- constexpr double epsilon {std::numeric_limits<double>::epsilon()};
- root_impetus impetus {evaluate_bounds};
- (void)&impetus;
-//std::cout.precision(21);
-
- double fa = f(a);
- double fb = f(b);
-#if 0 // RECTIFIED
- // Brent: at top of loop (not bottom, as here):
- // if fb and fc have the same sign, then swap a and c
- // this code seems to do something equivalent
- double fc = fa; // Brent: = fb
- double c = a; // likewise
-#endif // 0
-#if 1 // RECTIFIED
- double fc = fb;
- double c = b;
-#endif // 1
-
- double d = b - a;
- double e = d;
-
-//std::cout << " br " << ' ' << a << ' ' << b << ' ' << c << ' ' << fa << ' '
<< fb << ' ' << fc << std::endl;
-
-int j = 0;
- for(;; ++j)
- {
-#if 1 // RECTIFIED
- // Brent does this at the top
- if((0.0 < fb) == (0.0 < fc))
-// if(signum(fb) == signum(fc)) // should be equivalent
- {
- c = a;
- fc = fa;
- d = e = b - a;
- }
-#endif // 1
- // if c is a better approximant than b, then exchange
- // Brent does the same, but it's confusing:
- // it looks like a three-way shift
- // but it actually wipes out the old 'a'
- if(std::fabs(fc) < std::fabs(fb))
- {
- a = b; b = c; c = a;
- fa = fb; fb = fc; fc = fa;
- }
- // Brent: set 'tol' carefully--not just epsilon
-// double tol = epsilon; // RECTIFIED
- double tol = 2.0 * epsilon * std::fabs(b) + t;
- double m = 0.5 * (c - b);
- // Brent: '<=' rather than '<'
-// if(0.0 == fb || std::fabs(m) < tol) // RECTIFIED
- if(0.0 == fb || std::fabs(m) <= tol)
- {
- return {b, root_is_valid, j, 2 + j};
- }
- // bisect if previous iteration took too small a step or
- // produced no improvement
- // Brent: '<=' rather than '<' in second condition
-// if(std::fabs(e) < tol || std::fabs(fa) < std::fabs(fb)) // RECTIFIED
- if(std::fabs(e) < tol || std::fabs(fa) <= std::fabs(fb))
- {
- impetus = pis_aller;
- d = e = m;
- }
- // else try interpolating
- else
- {
- double p, q;
- // Brent: store fb/fa for later use--avoid numerical problems?
- if(a == c)
- // linear
- {
- impetus = interpolate_linear;
- p = 2.0 * m * fb / fa;
- // Brent: opposite sign
-// q = (fb - fa) / fa; // PARTLY RECTIFIED
- q = (fa - fb) / fa;
- }
- else
- // inverse quadratic
- {
- impetus = interpolate_inverse_quadratic;
- // Brent: arrange differently--avoid numerical problems?
- p = 2.0 * m * fb * (fa - fb) / (fc * fc) - (b - a) * fb * (fb
- fc) / (fa * fc);
- q = (fa / fc - 1.0) * (fb / fc - 1.0) * (fb / fa - 1.0);
- }
- // force 'p' to be positive
- // Brent: '<' rather than '<='
- if(0.0 <= p)
- {q = -q;}
- else
- {p = -p;}
- // store previous step
- double s = e;
- e = d;
- if
- // Brent: absolute value |tol * q|
- ( 2.0 * p < 3.0 * m * q - tol * q
- && p < std::fabs(0.5 * s * q)
- )
- {
- d = p / q;
- }
- else
- {
- d = e = m;
- }
- } // closing brace not evident in textbook
-
- a = b;
- fa = fb;
- if(tol < std::fabs(d))
- {
- b += d;
- }
- else
- {
- // Brent: adds 'tol' if 0==m
- b += tol * signum(m);
- }
- fb = f(b);
-//std::cout << j << " br " << ' ' << a << ' ' << b << ' ' << c << ' ' <<
impetus << std::endl;
-//std::cout << j << " br " << impetus << ' ' << b << std::endl;
-#if 0 // RECTIFIED
- // Brent does this at the top
- if((0.0 < fb) == (0.0 < fc))
-// if(signum(fb) == signum(fc)) // should be equivalent
- {
- c = a;
- fc = fa;
- e = d = b - a;
- }
-#endif // 0
- }
-}
-
-template<typename FunctionalType>
-root_type scherer_chandrupatla
- (FunctionalType& f
- ,double a
- ,double b
- ,double // t
- )
-{
- constexpr double epsilon {std::numeric_limits<double>::epsilon()};
- root_impetus impetus {evaluate_bounds};
- (void)&impetus;
-//std::cout.precision(21);
-
- // textbook swaps 'a' and 'b' here compared to its "brent" routine
- // but that probably doesn't matter
- double fa = f(a);
- double fb = f(b);
- double c = a;
- double fc = fa;
- double t = 0.5;
-
-int j = 0;
- for(;; ++j)
- {
- // 't' is coefficient for interpolating (linearly) by any technique
- double x = a + t * (b - a);
- double fx = f(x);
-//std::cout << j << " ch " << impetus << ' ' << x << std::endl;
-//std::cout << j << " ch " << impetus << ' ' << t << ' ' << x << ' ' << fx <<
' ' << a << ' ' << b << ' ' << c << std::endl;
- if(signum(fx) == signum(fa))
- {
- c = a;
- fc = fa;
- a = x;
- fa = fx; // textbook has weird capitalization on RHS
- }
- else
- {
- c = b;
- b = a;
- a = x;
- fc = fb;
- fb = fa;
- fa = fx;
- }
- double xm = a;
- double fm = fa;
- if(std::fabs(fb) < std::fabs(fa))
- {
- xm = b;
- fm = fb;
- }
- // textbook: 'epsM' and 'epsA' not defined
- double epsM = epsilon;
- double epsA = epsilon;
- double tol = 2.0 * epsM * std::fabs(xm) + epsA;
-// Brent uses this:
-// double tol = 2.0 * epsilon * std::fabs(b) + t;
- double tl = tol / std::fabs(b - c);
- if(0.5 < tl || 0.0 == fm)
- {
- return {xm, root_is_valid, j, 2 + j};
- }
-// specimen observed values:
-// 0.0659374999999999961142 a
-// 0.0406250000000000013878 b this is one end of the bracket
-// 0.0912499999999999977796 c so this is the other end of the bracket
-// 0.0447250871687336973292 true value
- double xi = (a - b) / (c - b);
- double phi = (fa - fb) / (fc - fb);
- if
- ( 1.0 - std::sqrt(1.0 - xi) < phi
- && phi < std::sqrt(xi)
- )
- {
- impetus = interpolate_inverse_quadratic;
- // textbook: really use 't'?
- t =
- (fa / (fb - fa)) * (fc / (fb - fc))
- + ((c - a) / (b - a)) * (fa / (fc - fa)) * (fb / (fc - fb))
- ;
- }
- else
- {
- impetus = pis_aller;
- t = 0.5;
- }
- // constrain t to (tl, 1-tl)
- if(t < tl)
- {t = tl;}
- if(1.0 - tl < t)
- {t = 1.0 - tl;}
- }
-}
-
/// An instrumented translation of Brent's reference implementation.
///
/// Deviation from the original ALGOL:
diff --git a/zero_test.cpp b/zero_test.cpp
index f9be645..3220e5d 100644
--- a/zero_test.cpp
+++ b/zero_test.cpp
@@ -887,7 +887,9 @@ void test_various_functions()
// plus apparent number of iterations, to account for required
// evaluation of both initial bounds; and separately measured
// by writing functions based on Scherer's pseudocode (with
- // numerous corrections for his faulty Brent algorithm).
+ // numerous corrections for his faulty Brent algorithm; use
+ // git switch --detach ac5731f52
+ // to reproduce the tests with that code).
//
// (The LMI_* conditionals for evaluation counts may seem
// haphazard; by design, they're just adequate to prevent error
@@ -907,14 +909,16 @@ void test_various_functions()
auto root_04 = std::sqrt(2.0);
test_a_decimal_function (f04, root_04, -1.0, 2.0, 17 , __LINE__, 11);
test_a_function (f04, root_04, -1.0, 2.0, 0.0 , __LINE__);
+#if defined ac5731f52
r = scherer_chandrupatla(f04, -1.0, 2.0, 0.0 );
LMI_TEST_EQUAL(10, r.n_eval);
r = scherer_brent (f04, -1.0, 2.0, 0.0 );
-#if !defined LMI_X87
+# if !defined LMI_X87
LMI_TEST_EQUAL(11, r.n_eval);
-#else // defined LMI_X87
+# else // defined LMI_X87
LMI_TEST_EQUAL(22, r.n_eval);
-#endif // defined LMI_X87
+# endif // defined LMI_X87
+#endif // defined ac5731f52
r = lmi_root (f04, -1.0, 2.0, 0.0 );
LMI_TEST_EQUAL(11, r.n_eval);
r = lmi_root (f04, -1.0, 2.0, 0.0, 0 );
@@ -931,10 +935,12 @@ void test_various_functions()
auto root_05 = 1.0;
test_a_decimal_function (f05, root_05, 0.0, 1.8, 17 , __LINE__, 130);
test_a_function (f05, root_05, 0.0, 1.8, 0.0 , __LINE__);
+#if defined ac5731f52
r = scherer_chandrupatla(f05, 0.0, 1.8, 0.0 );
LMI_TEST_EQUAL(62, r.n_eval);
r = scherer_brent (f05, 0.0, 1.8, 0.0 );
LMI_TEST_EQUAL(130, r.n_eval);
+#endif // defined ac5731f52
r = lmi_root (f05, 0.0, 1.8, 0.0 );
LMI_TEST_EQUAL(130, r.n_eval);
r = lmi_root (f05, 0.0, 1.8, 0.0, 0 );
@@ -952,16 +958,18 @@ void test_various_functions()
auto root_06 = 0.0;
test_a_decimal_function (f06, root_06, -1.0, 2.0, 12 , __LINE__, 107);
test_a_function (f06, root_06, -1.0, 2.0, 5.0e-13, __LINE__);
+#if defined ac5731f52
r = scherer_chandrupatla(f06, -1.0, 2.0, 5.0e-13 );
-#if !defined LMI_X87
+# if !defined LMI_X87
LMI_TEST_EQUAL(44, r.n_eval);
-#else // defined LMI_X87
+# else // defined LMI_X87
LMI_TEST_EQUAL(45, r.n_eval);
-#endif // defined LMI_X87
+# endif // defined LMI_X87
r = scherer_brent (f06, -1.0, 2.0, 5.0e-13 );
-#if defined LMI_X86_64 && defined LMI_POSIX
+# if defined LMI_X86_64 && defined LMI_POSIX
LMI_TEST_EQUAL(105, r.n_eval);
-#endif // defined LMI_X86_64 && defined LMI_POSIX
+# endif // defined LMI_X86_64 && defined LMI_POSIX
+#endif // defined ac5731f52
r = lmi_root (f06, -1.0, 2.0, 5.0e-13 );
#if defined LMI_X86_64 && defined LMI_POSIX
LMI_TEST_EQUAL(117, r.n_eval);
- [lmi-commits] [lmi] master updated (028b454 -> 5d4f506), Greg Chicares, 2021/07/30
- [lmi-commits] [lmi] master 828ff21 1/8: Renumber some unit tests, Greg Chicares, 2021/07/30
- [lmi-commits] [lmi] master 0113a5d 3/8: Test three examples from a textbook, Greg Chicares, 2021/07/30
- [lmi-commits] [lmi] master 4bc5b1f 4/8: Make bounds and tolerance match textbook examples better, Greg Chicares, 2021/07/30
- [lmi-commits] [lmi] master b954393 2/8: Don't hard-code sqrt(2), Greg Chicares, 2021/07/30
- [lmi-commits] [lmi] master de32b80 7/8: Add an all-platform unit-test script, Greg Chicares, 2021/07/30
- [lmi-commits] [lmi] master 5d4f506 8/8: Record speed measurements, Greg Chicares, 2021/07/30
- [lmi-commits] [lmi] master cf516cc 6/8: Remove code added in the last commit to support its conclusions,
Greg Chicares <=
- [lmi-commits] [lmi] master ac5731f 5/8: Controvert a published claim, Greg Chicares, 2021/07/30