changeset 3753:f751e43de300

[project @ 2000-12-14 03:01:23 by jwe]
author jwe
date Thu, 14 Dec 2000 03:01:24 +0000
parents 719a44ff67c9
children e63a3a6d7797
files liboctave/ChangeLog liboctave/Range.cc
diffstat 2 files changed, 31 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/ChangeLog	Wed Dec 13 19:02:43 2000 +0000
+++ b/liboctave/ChangeLog	Thu Dec 14 03:01:24 2000 +0000
@@ -1,5 +1,8 @@
 2000-12-13  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
+	(Range::nelem_internal): Call tfloor, not round, but then try
+	harder to compute correct number of elements.
+
 	* dMatrix.cc (Matrix::lssolve): Ask DGELSS for size of work vector.
 	* CMatrix.cc (ComplexMatrix::lssolve): Likewise, for ZGELSS.
 
--- a/liboctave/Range.cc	Wed Dec 13 19:02:43 2000 +0000
+++ b/liboctave/Range.cc	Thu Dec 14 03:01:24 2000 +0000
@@ -230,15 +230,42 @@
   return tfloor (x+0.5, ct);
 }
 
+static inline bool
+teq (double u, double v, double ct = 3.0 * DBL_EPSILON)
+{
+  double tu = fabs (u);
+  double tv = fabs (v);
+
+  return fabs (u - v) < ((tu > tv ? tu : tv) * ct);
+}
+
 int
 Range::nelem_internal (void) const
 {
   double ct = 3.0 * DBL_EPSILON;
 
-  double tmp = round ((rng_limit - rng_base + rng_inc) / rng_inc, ct);
+  double tmp = tfloor ((rng_limit - rng_base + rng_inc) / rng_inc, ct);
 
   int n_elt = (tmp > 0.0 ? static_cast<int> (tmp) : 0);
 
+  // If the final element that we would compute for the range is equal
+  // to the limit of the range, or is an adjacent floating point
+  // number, accept it.  Otherwise, try a range with one fewer
+  // element.  If that fails, try again with one more element.
+  //
+  // I'm not sure this is very good, but it seems to work better than
+  // just using tfloor as above.  For example, without it, the
+  // expression 1.8:0.05:1.9 fails to produce the expected result of
+  // [1.8, 1.85, 1.9].
+
+  if (! teq (rng_base + (n_elt - 1) * rng_inc, rng_limit))
+    {
+      if (teq (rng_base + (n_elt - 2) * rng_inc, rng_limit))
+	n_elt--;
+      else if (teq (rng_base + n_elt * rng_inc, rng_limit))
+	n_elt++;
+    }
+
   return (n_elt >= INT_MAX - 1) ? -1 : n_elt;
 }