changeset 18886:47d4b680d0e0

improve accuracy of range/scalar arithmetic (bug #42589) * Range.h, Range.cc (Range::Range (double, double, double, octave_idx_type): New protected constructor. (operator -, operator +, operator *): Use new constructor. (Range::Range (double, double, octave_idx_type): Also check that the limit remains finite.
author John W. Eaton <jwe@octave.org>
date Fri, 20 Jun 2014 18:55:38 -0400
parents 479d1d3cb5c3
children de8c67ba7ac4
files liboctave/array/Range.cc liboctave/array/Range.h
diffstat 2 files changed, 18 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/array/Range.cc	Thu Jun 19 18:08:00 2014 -0400
+++ b/liboctave/array/Range.cc	Fri Jun 20 18:55:38 2014 -0400
@@ -387,12 +387,12 @@
 Range
 operator - (const Range& r)
 {
-  return Range (-r.base (), -r.inc (), r.nelem ());
+  return Range (-r.base (), -r.limit (), -r.inc (), r.nelem ());
 }
 
 Range operator + (double x, const Range& r)
 {
-  Range result (x + r.base (), r.inc (), r.nelem ());
+  Range result (x + r.base (), x + r.limit (), r.inc (), r.nelem ());
   if (result.rng_nelem < 0)
     result.cache = x + r.matrix_value ();
 
@@ -401,7 +401,7 @@
 
 Range operator + (const Range& r, double x)
 {
-  Range result (r.base () + x, r.inc (), r.nelem ());
+  Range result (r.base () + x, r.limit () + x, r.inc (), r.nelem ());
   if (result.rng_nelem < 0)
     result.cache = r.matrix_value () + x;
 
@@ -410,7 +410,7 @@
 
 Range operator - (double x, const Range& r)
 {
-  Range result (x - r.base (), -r.inc (), r.nelem ());
+  Range result (x - r.base (), x - r.limit (), -r.inc (), r.nelem ());
   if (result.rng_nelem < 0)
     result.cache = x - r.matrix_value ();
 
@@ -419,7 +419,7 @@
 
 Range operator - (const Range& r, double x)
 {
-  Range result (r.base () - x, r.inc (), r.nelem ());
+  Range result (r.base () - x, r.limit () - x, r.inc (), r.nelem ());
   if (result.rng_nelem < 0)
     result.cache = r.matrix_value () - x;
 
@@ -428,7 +428,7 @@
 
 Range operator * (double x, const Range& r)
 {
-  Range result (x * r.base (), x * r.inc (), r.nelem ());
+  Range result (x * r.base (), x * r.limit (), x * r.inc (), r.nelem ());
   if (result.rng_nelem < 0)
     result.cache = x * r.matrix_value ();
 
@@ -437,7 +437,7 @@
 
 Range operator * (const Range& r, double x)
 {
-  Range result (r.base () * x, r.inc () * x, r.nelem ());
+  Range result (r.base () * x, r.limit () * x, r.inc () * x, r.nelem ());
   if (result.rng_nelem < 0)
     result.cache = r.matrix_value () * x;
 
--- a/liboctave/array/Range.h	Thu Jun 19 18:08:00 2014 -0400
+++ b/liboctave/array/Range.h	Fri Jun 20 18:55:38 2014 -0400
@@ -54,7 +54,7 @@
     : rng_base (b), rng_limit (b + (n-1) * i), rng_inc (i),
       rng_nelem (n), cache ()
   {
-    if (! xfinite (b) || ! xfinite (i))
+    if (! xfinite (b) || ! xfinite (i) | ! xfinite (rng_limit))
       rng_nelem = -2;
   }
 
@@ -145,6 +145,16 @@
 
   void clear_cache (void) const { cache.resize (0, 0); }
 
+protected:
+
+  // For operators' usage (to allow all values to be set directly).
+  Range (double b, double l, double i, octave_idx_type n)
+    : rng_base (b), rng_limit (l), rng_inc (i),
+      rng_nelem (n), cache ()
+  {
+    if (! xfinite (b) || ! xfinite (i) || ! xfinite (l))
+      rng_nelem = -2;
+  }
 };
 
 extern OCTAVE_API Range operator - (const Range& r);