From bug-octave-request at bevo dot che dot wisc dot edu Thu Nov 8 13:41:27 2001 Subject: index expression 1:-1 fails From: "John W. Eaton" To: Mats Jansson Cc: bug-octave at bevo dot che dot wisc dot edu Date: Thu, 8 Nov 2001 13:40:42 -0600 On 8-Nov-2001, Mats Jansson wrote: | | Bug report for Octave 2.1.35 configured for i686-pc-linux-gnu | | Description: | ----------- | | On my installations of octave 2.1.33 and 2.1.35, the index | expression | 1:-1 results in an error-message, while e.g. 0:-1, 2:-1 or 1:-2 | return | the empty matrix. I don't get the error-message on another machine | with | octave 2.1.31. Please try the following patch. Thanks, jwe 2001-11-08 John W. Eaton * Range.cc (Range::nelem_internal): Special case ranges that must have zero elements. Index: Range.cc =================================================================== RCS file: /usr/local/cvsroot/octave/liboctave/Range.cc,v retrieving revision 1.26 diff -c -r1.26 Range.cc *** Range.cc 14 Dec 2000 03:01:24 -0000 1.26 --- Range.cc 8 Nov 2001 19:32:46 -0000 *************** *** 242,272 **** int Range::nelem_internal (void) const { ! double ct = 3.0 * DBL_EPSILON; ! 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; } /* --- 242,286 ---- int Range::nelem_internal (void) const { ! int retval = -1; ! if (rng_inc == 0 ! || (rng_limit > rng_base && rng_inc < 0) ! || (rng_limit < rng_base && rng_inc > 0)) ! { ! retval = 0; ! } ! else ! { ! double ct = 3.0 * DBL_EPSILON; ! 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++; ! } ! ! retval = (n_elt >= INT_MAX - 1) ? -1 : n_elt; } ! return retval; } /* ------------------------------------------------------------- Octave is freely available under the terms of the GNU GPL. Octave's home on the web: http://www.octave.org How to fund new projects: http://www.octave.org/funding.html Subscription information: http://www.octave.org/archive.html -------------------------------------------------------------