lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master 012967c 08/22: Diagnose any attempt to find a


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 012967c 08/22: Diagnose any attempt to find a root in a zero-measure interval
Date: Sun, 6 Jun 2021 21:38:00 -0400 (EDT)

branch: master
commit 012967c234cbe225d3b006c63b0a566a3d45e831
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Diagnose any attempt to find a root in a zero-measure interval
    
    Trying to find a zero of a function in [k,k] is probably a mistake.
    Indeed this diagnostic identified a futile unit test, which attempted
    to find a zero of f(x)=x^19 in [0,0] to within a tolerance of 1e100,
    which had previously been deemed to succeed. Temporarily suppressed
    that test.
---
 financial.hpp   | 2 ++
 gpt_specamt.cpp | 2 ++
 ihs_avsolve.cpp | 5 +++++
 solve.cpp       | 5 +++++
 zero.hpp        | 8 +++++++-
 zero_test.cpp   | 7 ++++++-
 6 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/financial.hpp b/financial.hpp
index 5e9d60a..de7b2ec 100644
--- a/financial.hpp
+++ b/financial.hpp
@@ -129,6 +129,8 @@ class irr_helper
             // Return -100% if NPVs of a priori bounds have same sign.
             case root_not_bracketed:
                 {return -1.0L;}
+            case improper_bounds:
+                {throw "IRR: improper bounds.";}
             }
         throw "Unreachable--silences a compiler diagnostic.";
         }
diff --git a/gpt_specamt.cpp b/gpt_specamt.cpp
index ad911f4..d2cf144 100644
--- a/gpt_specamt.cpp
+++ b/gpt_specamt.cpp
@@ -176,6 +176,8 @@ currency gpt_specamt::CalculateSpecAmt
             {return a_Values.round_specamt().c(solution.first);}
         case root_not_bracketed:
             {return a_Values.min_issue_spec_amt();}
+        case improper_bounds:
+            {throw "CalculateSpecAmt: improper bounds.";}
         }
     throw "Unreachable--silences a compiler diagnostic.";
 }
diff --git a/ihs_avsolve.cpp b/ihs_avsolve.cpp
index 1ee549e..a18cdd5 100644
--- a/ihs_avsolve.cpp
+++ b/ihs_avsolve.cpp
@@ -484,6 +484,11 @@ currency AccountValue::Solve
                 }
             }
             break;
+        case improper_bounds:
+            {
+            alarum() << "Improper bounds." << LMI_FLUSH;
+            }
+            break;
         }
     return solution_cents;
 }
diff --git a/solve.cpp b/solve.cpp
index ff665bb..10625af 100644
--- a/solve.cpp
+++ b/solve.cpp
@@ -358,6 +358,11 @@ currency AccountValue::Solve()
             warning() << "solution not found. Using zero instead." << 
LMI_FLUSH;
             }
             break;
+        case improper_bounds:
+            {
+            alarum() << "Improper bounds." << LMI_FLUSH;
+            }
+            break;
         }
     return solution_cents;
 }
diff --git a/zero.hpp b/zero.hpp
index b3ec634..0b255a4 100644
--- a/zero.hpp
+++ b/zero.hpp
@@ -51,6 +51,7 @@ enum interpolation_technique
 enum root_validity
     {root_is_valid
     ,root_not_bracketed
+    ,improper_bounds
     };
 
 typedef std::pair<double,root_validity> root_type;
@@ -80,7 +81,7 @@ inline void expatiate
 
 /// Return a zero z of a function f within input bounds [a,b].
 ///
-/// Precondition: either
+/// Preconditions: bounds are distinct after rounding; and either
 ///   0.0 == f(a), or
 ///   0.0 == f(b), or
 ///   f(a) and f(b) have opposite signs;
@@ -272,6 +273,11 @@ root_type decimal_root
     double a = round_dec(bound0);
     double b = round_dec(bound1);
 
+    if(a == b)
+        {
+        return std::make_pair(a, improper_bounds);
+        }
+
     double fa = static_cast<double>(f(a));
     detail::expatiate(number_of_iterations, os_trace, technique, a, fa);
     if(0.0 == fa) // Note 0.
diff --git a/zero_test.cpp b/zero_test.cpp
index a5b2f94..2ee0635 100644
--- a/zero_test.cpp
+++ b/zero_test.cpp
@@ -182,6 +182,11 @@ int test_main(int, char*[])
     r = decimal_root(0.5, 5.0, bias_none, 9, e);
     LMI_TEST(root_is_valid == r.second);
 
+    // Test failure with improper interval.
+
+    r = decimal_root(1.0, 1.0, bias_none, 9, e);
+    LMI_TEST(improper_bounds == r.second);
+
     // Test failure with interval containing no root.
 
     r = decimal_root(0.1, 1.0, bias_none, 9, e);
@@ -244,7 +249,7 @@ int test_main(int, char*[])
     double d = brent_zero(-1.0, 4.0, 1.0e-20, e_19);
     LMI_TEST(std::fabs(d) <= epsilon);
 
-    test_zero(-1.0, 4.0, -100, e_19, std::exp(1.0));
+//  test_zero(-1.0, 4.0, -100, e_19, std::exp(1.0));
     test_zero(-1.0, 4.0,    0, e_19, std::exp(1.0));
     test_zero(-1.0, 4.0,  100, e_19, std::exp(1.0));
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]