# HG changeset patch # User jwe # Date 976762884 0 # Node ID f751e43de300bbfb4bba3fdf67ea0923f087a114 # Parent 719a44ff67c930e66c5c9b3df1fd98103fe0cd15 [project @ 2000-12-14 03:01:23 by jwe] diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog --- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,5 +1,8 @@ 2000-12-13 John W. Eaton + (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. diff --git a/liboctave/Range.cc b/liboctave/Range.cc --- a/liboctave/Range.cc +++ b/liboctave/Range.cc @@ -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 (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; }