00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <cfloat>
00028
00029 #include <iostream>
00030 #include <limits>
00031
00032 #include "Range.h"
00033 #include "lo-error.h"
00034 #include "lo-mappers.h"
00035 #include "lo-math.h"
00036 #include "lo-utils.h"
00037 #include "Array-util.h"
00038
00039 Range::Range (double b, double i, octave_idx_type n)
00040 : rng_base (b), rng_limit (b + (n-1) * i), rng_inc (i),
00041 rng_nelem (n), cache ()
00042 {
00043 if (! xfinite (b) || ! xfinite (i))
00044 rng_nelem = -2;
00045 }
00046
00047 bool
00048 Range::all_elements_are_ints (void) const
00049 {
00050
00051
00052
00053
00054 return (! (xisnan (rng_base) || xisnan (rng_inc))
00055 && (NINTbig (rng_base) == rng_base || rng_nelem < 1)
00056 && (NINTbig (rng_inc) == rng_inc || rng_nelem <= 1));
00057 }
00058
00059 Matrix
00060 Range::matrix_value (void) const
00061 {
00062 if (rng_nelem > 0 && cache.nelem () == 0)
00063 {
00064 cache.resize (1, rng_nelem);
00065 double b = rng_base;
00066 double increment = rng_inc;
00067 for (octave_idx_type i = 0; i < rng_nelem; i++)
00068 cache(i) = b + i * increment;
00069
00070
00071
00072
00073
00074
00075
00076 if ((rng_inc > 0 && cache(rng_nelem-1) > rng_limit)
00077 || (rng_inc < 0 && cache(rng_nelem-1) < rng_limit))
00078 cache(rng_nelem-1) = rng_limit;
00079 }
00080
00081 return cache;
00082 }
00083
00084 double
00085 Range::checkelem (octave_idx_type i) const
00086 {
00087 if (i < 0 || i >= rng_nelem)
00088 gripe_index_out_of_range (1, 1, i+1, rng_nelem);
00089
00090 return rng_base + rng_inc * i;
00091 }
00092
00093 struct _rangeidx_helper
00094 {
00095 double *array, base, inc;
00096 _rangeidx_helper (double *a, double b, double i)
00097 : array (a), base (b), inc (i) { }
00098 void operator () (octave_idx_type i)
00099 { *array++ = base + i * inc; }
00100 };
00101
00102 Array<double>
00103 Range::index (const idx_vector& i) const
00104 {
00105 Array<double> retval;
00106
00107 octave_idx_type n = rng_nelem;
00108
00109 if (i.is_colon ())
00110 {
00111 retval = matrix_value ().reshape (dim_vector (rng_nelem, 1));
00112 }
00113 else
00114 {
00115 if (i.extent (n) != n)
00116 gripe_index_out_of_range (1, 1, i.extent (n), n);
00117
00118 dim_vector rd = i.orig_dimensions ();
00119 octave_idx_type il = i.length (n);
00120
00121
00122
00123 if (n != 1 && rd.is_vector ())
00124 rd = dim_vector (1, il);
00125
00126 retval.clear (rd);
00127
00128 i.loop (n, _rangeidx_helper (retval.fortran_vec (), rng_base, rng_inc));
00129 }
00130
00131 return retval;
00132 }
00133
00134
00135
00136 double
00137 Range::min (void) const
00138 {
00139 double retval = 0.0;
00140 if (rng_nelem > 0)
00141 {
00142 if (rng_inc > 0)
00143 retval = rng_base;
00144 else
00145 {
00146 retval = rng_base + (rng_nelem - 1) * rng_inc;
00147
00148
00149
00150 if (retval < rng_limit)
00151 retval = rng_limit;
00152 }
00153
00154 }
00155 return retval;
00156 }
00157
00158 double
00159 Range::max (void) const
00160 {
00161 double retval = 0.0;
00162 if (rng_nelem > 0)
00163 {
00164 if (rng_inc > 0)
00165 {
00166 retval = rng_base + (rng_nelem - 1) * rng_inc;
00167
00168
00169
00170 if (retval > rng_limit)
00171 retval = rng_limit;
00172 }
00173 else
00174 retval = rng_base;
00175 }
00176 return retval;
00177 }
00178
00179 void
00180 Range::sort_internal (bool ascending)
00181 {
00182 if (ascending && rng_base > rng_limit && rng_inc < 0.0)
00183 {
00184 double tmp = rng_base;
00185 rng_base = min ();
00186 rng_limit = tmp;
00187 rng_inc = -rng_inc;
00188 clear_cache ();
00189 }
00190 else if (! ascending && rng_base < rng_limit && rng_inc > 0.0)
00191 {
00192 double tmp = rng_limit;
00193 rng_limit = min ();
00194 rng_base = tmp;
00195 rng_inc = -rng_inc;
00196 clear_cache ();
00197 }
00198 }
00199
00200 void
00201 Range::sort_internal (Array<octave_idx_type>& sidx, bool ascending)
00202 {
00203 octave_idx_type nel = nelem ();
00204
00205 sidx.resize (dim_vector (1, nel));
00206
00207 octave_idx_type *psidx = sidx.fortran_vec ();
00208
00209 bool reverse = false;
00210
00211 if (ascending && rng_base > rng_limit && rng_inc < 0.0)
00212 {
00213 double tmp = rng_base;
00214 rng_base = min ();
00215 rng_limit = tmp;
00216 rng_inc = -rng_inc;
00217 clear_cache ();
00218 reverse = true;
00219 }
00220 else if (! ascending && rng_base < rng_limit && rng_inc > 0.0)
00221 {
00222 double tmp = rng_limit;
00223 rng_limit = min ();
00224 rng_base = tmp;
00225 rng_inc = -rng_inc;
00226 clear_cache ();
00227 reverse = true;
00228 }
00229
00230 octave_idx_type tmp = reverse ? nel - 1 : 0;
00231 octave_idx_type stp = reverse ? -1 : 1;
00232
00233 for (octave_idx_type i = 0; i < nel; i++, tmp += stp)
00234 psidx[i] = tmp;
00235
00236 }
00237
00238 Matrix
00239 Range::diag (octave_idx_type k) const
00240 {
00241 return matrix_value ().diag (k);
00242 }
00243
00244 Range
00245 Range::sort (octave_idx_type dim, sortmode mode) const
00246 {
00247 Range retval = *this;
00248
00249 if (dim == 1)
00250 {
00251 if (mode == ASCENDING)
00252 retval.sort_internal (true);
00253 else if (mode == DESCENDING)
00254 retval.sort_internal (false);
00255 }
00256 else if (dim != 0)
00257 (*current_liboctave_error_handler) ("Range::sort: invalid dimension");
00258
00259 return retval;
00260 }
00261
00262 Range
00263 Range::sort (Array<octave_idx_type>& sidx, octave_idx_type dim,
00264 sortmode mode) const
00265 {
00266 Range retval = *this;
00267
00268 if (dim == 1)
00269 {
00270 if (mode == ASCENDING)
00271 retval.sort_internal (sidx, true);
00272 else if (mode == DESCENDING)
00273 retval.sort_internal (sidx, false);
00274 }
00275 else if (dim != 0)
00276 (*current_liboctave_error_handler) ("Range::sort: invalid dimension");
00277
00278 return retval;
00279 }
00280
00281 sortmode
00282 Range::is_sorted (sortmode mode) const
00283 {
00284 if (rng_nelem > 1 && rng_inc < 0)
00285 mode = (mode == ASCENDING) ? UNSORTED : DESCENDING;
00286 else if (rng_nelem > 1 && rng_inc > 0)
00287 mode = (mode == DESCENDING) ? UNSORTED : ASCENDING;
00288 else
00289 mode = mode ? mode : ASCENDING;
00290
00291 return mode;
00292 }
00293
00294 std::ostream&
00295 operator << (std::ostream& os, const Range& a)
00296 {
00297 double b = a.base ();
00298 double increment = a.inc ();
00299 octave_idx_type num_elem = a.nelem ();
00300
00301 for (octave_idx_type i = 0; i < num_elem-1; i++)
00302 os << b + i * increment << " ";
00303
00304
00305
00306
00307 os << (increment > 0 ? a.max () : a.min ()) << "\n";
00308
00309 return os;
00310 }
00311
00312 std::istream&
00313 operator >> (std::istream& is, Range& a)
00314 {
00315 is >> a.rng_base;
00316 if (is)
00317 {
00318 is >> a.rng_limit;
00319 if (is)
00320 {
00321 is >> a.rng_inc;
00322 a.rng_nelem = a.nelem_internal ();
00323 }
00324 }
00325
00326 return is;
00327 }
00328
00329 Range
00330 operator - (const Range& r)
00331 {
00332 return Range (-r.base (), -r.inc (), r.nelem ());
00333 }
00334
00335 Range operator + (double x, const Range& r)
00336 {
00337 Range result (x + r.base (), r.inc (), r.nelem ());
00338 if (result.rng_nelem < 0)
00339 result.cache = x + r.matrix_value ();
00340
00341 return result;
00342 }
00343
00344 Range operator + (const Range& r, double x)
00345 {
00346 Range result (r.base () + x, r.inc (), r.nelem ());
00347 if (result.rng_nelem < 0)
00348 result.cache = r.matrix_value () + x;
00349
00350 return result;
00351 }
00352
00353 Range operator - (double x, const Range& r)
00354 {
00355 Range result (x - r.base (), -r.inc (), r.nelem ());
00356 if (result.rng_nelem < 0)
00357 result.cache = x - r.matrix_value ();
00358
00359 return result;
00360 }
00361
00362 Range operator - (const Range& r, double x)
00363 {
00364 Range result (r.base () - x, r.inc (), r.nelem ());
00365 if (result.rng_nelem < 0)
00366 result.cache = r.matrix_value () - x;
00367
00368 return result;
00369 }
00370
00371 Range operator * (double x, const Range& r)
00372 {
00373 Range result (x * r.base (), x * r.inc (), r.nelem ());
00374 if (result.rng_nelem < 0)
00375 result.cache = x * r.matrix_value ();
00376
00377 return result;
00378 }
00379
00380 Range operator * (const Range& r, double x)
00381 {
00382 Range result (r.base () * x, r.inc () * x, r.nelem ());
00383 if (result.rng_nelem < 0)
00384 result.cache = r.matrix_value () * x;
00385
00386 return result;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 static inline double
00423 tfloor (double x, double ct)
00424 {
00425
00426
00427
00428
00429
00430
00431
00432
00433 double q = 1.0;
00434
00435 if (x < 0.0)
00436 q = 1.0 - ct;
00437
00438 double rmax = q / (2.0 - ct);
00439
00440 double t1 = 1.0 + gnulib::floor (x);
00441 t1 = (ct / q) * (t1 < 0.0 ? -t1 : t1);
00442 t1 = rmax < t1 ? rmax : t1;
00443 t1 = ct > t1 ? ct : t1;
00444 t1 = gnulib::floor (x + t1);
00445
00446 if (x <= 0.0 || (t1 - x) < rmax)
00447 return t1;
00448 else
00449 return t1 - 1.0;
00450 }
00451
00452 static inline double
00453 tceil (double x, double ct)
00454 {
00455 return -tfloor (-x, ct);
00456 }
00457
00458 static inline bool
00459 teq (double u, double v, double ct = 3.0 * DBL_EPSILON)
00460 {
00461 double tu = fabs (u);
00462 double tv = fabs (v);
00463
00464 return fabs (u - v) < ((tu > tv ? tu : tv) * ct);
00465 }
00466
00467 octave_idx_type
00468 Range::nelem_internal (void) const
00469 {
00470 octave_idx_type retval = -1;
00471
00472 if (rng_inc == 0
00473 || (rng_limit > rng_base && rng_inc < 0)
00474 || (rng_limit < rng_base && rng_inc > 0))
00475 {
00476 retval = 0;
00477 }
00478 else
00479 {
00480 double ct = 3.0 * DBL_EPSILON;
00481
00482 double tmp = tfloor ((rng_limit - rng_base + rng_inc) / rng_inc, ct);
00483
00484 octave_idx_type n_elt = (tmp > 0.0 ? static_cast<octave_idx_type> (tmp) : 0);
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 if (! teq (rng_base + (n_elt - 1) * rng_inc, rng_limit))
00498 {
00499 if (teq (rng_base + (n_elt - 2) * rng_inc, rng_limit))
00500 n_elt--;
00501 else if (teq (rng_base + n_elt * rng_inc, rng_limit))
00502 n_elt++;
00503 }
00504
00505 retval = (n_elt >= std::numeric_limits<octave_idx_type>::max () - 1) ? -1 : n_elt;
00506 }
00507
00508 return retval;
00509 }