Mercurial > hg > octave-lyh
annotate liboctave/Range.cc @ 10493:2f8bacc2a57d
fix order of func defs in Sparse.cc
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 07 Apr 2010 12:07:06 +0200 |
parents | e5ae13b8b2c2 |
children | 5eb10763069f |
rev | line source |
---|---|
3 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2002, 2004, |
8920 | 4 2005, 2007, 2008, 2009 John W. Eaton |
3 | 5 |
6 This file is part of Octave. | |
7 | |
8 Octave is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
3 | 12 |
13 Octave is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
3 | 21 |
22 */ | |
23 | |
238 | 24 #ifdef HAVE_CONFIG_H |
1192 | 25 #include <config.h> |
3 | 26 #endif |
27 | |
1546 | 28 #include <cfloat> |
1367 | 29 |
3503 | 30 #include <iostream> |
6490 | 31 #include <limits> |
3 | 32 |
33 #include "Range.h" | |
7458 | 34 #include "lo-error.h" |
2383 | 35 #include "lo-mappers.h" |
7231 | 36 #include "lo-math.h" |
2383 | 37 #include "lo-utils.h" |
10366
e5ae13b8b2c2
improve Array indexing error messages
Jaroslav Hajek <highegg@gmail.com>
parents:
10314
diff
changeset
|
38 #include "Array-util.h" |
2383 | 39 |
8971 | 40 Range::Range (double b, double i, octave_idx_type n) |
41 : rng_base (b), rng_limit (b + n * i), rng_inc (i), | |
42 rng_nelem (n), cache () | |
43 { | |
44 if (! xfinite (b) || ! xfinite (i)) | |
45 rng_nelem = -2; | |
46 } | |
47 | |
2383 | 48 bool |
49 Range::all_elements_are_ints (void) const | |
50 { | |
51 // If the base and increment are ints, the final value in the range | |
6457 | 52 // will also be an integer, even if the limit is not. If there is one |
53 // or fewer elements only the base needs to be an integer | |
2383 | 54 |
55 return (! (xisnan (rng_base) || xisnan (rng_inc)) | |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
56 && (NINTbig (rng_base) == rng_base || rng_nelem < 1) |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
57 && (NINTbig (rng_inc) == rng_inc || rng_nelem <= 1)); |
2383 | 58 } |
645 | 59 |
60 Matrix | |
61 Range::matrix_value (void) const | |
62 { | |
8971 | 63 if (rng_nelem > 0 && cache.nelem () == 0) |
645 | 64 { |
4810 | 65 cache.resize (1, rng_nelem); |
645 | 66 double b = rng_base; |
67 double increment = rng_inc; | |
5275 | 68 for (octave_idx_type i = 0; i < rng_nelem; i++) |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
69 cache(i) = b + i * increment; |
4791 | 70 |
71 // On some machines (x86 with extended precision floating point | |
72 // arithmetic, for example) it is possible that we can overshoot | |
73 // the limit by approximately the machine precision even though | |
74 // we were very careful in our calculation of the number of | |
75 // elements. | |
76 | |
4810 | 77 if ((rng_inc > 0 && cache(rng_nelem-1) > rng_limit) |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
78 || (rng_inc < 0 && cache(rng_nelem-1) < rng_limit)) |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
79 cache(rng_nelem-1) = rng_limit; |
645 | 80 } |
81 | |
4810 | 82 return cache; |
645 | 83 } |
3 | 84 |
9986
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
85 double |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
86 Range::checkelem (octave_idx_type i) const |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
87 { |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
88 if (i < 0 || i >= rng_nelem) |
10366
e5ae13b8b2c2
improve Array indexing error messages
Jaroslav Hajek <highegg@gmail.com>
parents:
10314
diff
changeset
|
89 gripe_index_out_of_range (1, 1, i+1, rng_nelem); |
9986
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
90 |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
91 return rng_base + rng_inc * i; |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
92 } |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
93 |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
94 struct _rangeidx_helper |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
95 { |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
96 double *array, base, inc; |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
97 _rangeidx_helper (double *a, double b, double i) |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
98 : array (a), base (b), inc (i) { } |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
99 void operator () (octave_idx_type i) |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
100 { *array++ = base + i * inc; } |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
101 }; |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
102 |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
103 Array<double> |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
104 Range::index (const idx_vector& i) const |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
105 { |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
106 Array<double> retval; |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
107 |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
108 octave_idx_type n = rng_nelem; |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
109 |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
110 if (i.is_colon ()) |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
111 { |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
112 retval = matrix_value ().reshape (dim_vector (rng_nelem, 1)); |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
113 } |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
114 else |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
115 { |
10366
e5ae13b8b2c2
improve Array indexing error messages
Jaroslav Hajek <highegg@gmail.com>
parents:
10314
diff
changeset
|
116 if (i.extent (n) != n) |
e5ae13b8b2c2
improve Array indexing error messages
Jaroslav Hajek <highegg@gmail.com>
parents:
10314
diff
changeset
|
117 gripe_index_out_of_range (1, 1, i.extent (n), n); // throws |
e5ae13b8b2c2
improve Array indexing error messages
Jaroslav Hajek <highegg@gmail.com>
parents:
10314
diff
changeset
|
118 |
9986
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
119 dim_vector rd = i.orig_dimensions (); |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
120 octave_idx_type il = i.length (n); |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
121 |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
122 // taken from Array.cc. |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
123 |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
124 if (n != 1 && rd.is_vector ()) |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
125 rd = dim_vector (1, il); |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
126 |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
127 retval.clear (rd); |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
128 |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
129 i.loop (n, _rangeidx_helper (retval.fortran_vec (), rng_base, rng_inc)); |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
130 } |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
131 |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
132 return retval; |
672e1b49e01e
optimize indexing of ranges by single subscripts
Jaroslav Hajek <highegg@gmail.com>
parents:
8971
diff
changeset
|
133 } |
4810 | 134 |
208 | 135 // NOTE: max and min only return useful values if nelem > 0. |
136 | |
137 double | |
138 Range::min (void) const | |
139 { | |
140 double retval = 0.0; | |
141 if (rng_nelem > 0) | |
142 { | |
143 if (rng_inc > 0) | |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
144 retval = rng_base; |
208 | 145 else |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
146 { |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
147 retval = rng_base + (rng_nelem - 1) * rng_inc; |
4791 | 148 |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
149 // See the note in the matrix_value method above. |
4791 | 150 |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
151 if (retval < rng_limit) |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
152 retval = rng_limit; |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
153 } |
4791 | 154 |
208 | 155 } |
156 return retval; | |
157 } | |
158 | |
159 double | |
160 Range::max (void) const | |
161 { | |
162 double retval = 0.0; | |
163 if (rng_nelem > 0) | |
164 { | |
165 if (rng_inc > 0) | |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
166 { |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
167 retval = rng_base + (rng_nelem - 1) * rng_inc; |
4791 | 168 |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
169 // See the note in the matrix_value method above. |
4791 | 170 |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
171 if (retval > rng_limit) |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
172 retval = rng_limit; |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
173 } |
208 | 174 else |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
175 retval = rng_base; |
208 | 176 } |
177 return retval; | |
178 } | |
179 | |
180 void | |
7458 | 181 Range::sort_internal (bool ascending) |
208 | 182 { |
7458 | 183 if (ascending && rng_base > rng_limit && rng_inc < 0.0) |
208 | 184 { |
185 double tmp = rng_base; | |
186 rng_base = min (); | |
187 rng_limit = tmp; | |
188 rng_inc = -rng_inc; | |
4811 | 189 clear_cache (); |
208 | 190 } |
8565 | 191 else if (! ascending && rng_base < rng_limit && rng_inc > 0.0) |
7458 | 192 { |
193 double tmp = rng_limit; | |
194 rng_limit = min (); | |
195 rng_base = tmp; | |
196 rng_inc = -rng_inc; | |
197 clear_cache (); | |
198 } | |
199 } | |
200 | |
201 void | |
202 Range::sort_internal (Array<octave_idx_type>& sidx, bool ascending) | |
203 { | |
204 octave_idx_type nel = nelem (); | |
205 | |
206 sidx.resize (dim_vector (1, nel)); | |
207 | |
208 octave_idx_type *psidx = sidx.fortran_vec (); | |
209 | |
210 bool reverse = false; | |
211 | |
212 if (ascending && rng_base > rng_limit && rng_inc < 0.0) | |
213 { | |
214 double tmp = rng_base; | |
215 rng_base = min (); | |
216 rng_limit = tmp; | |
217 rng_inc = -rng_inc; | |
218 clear_cache (); | |
219 reverse = true; | |
220 } | |
221 else if (! ascending && rng_base < rng_limit && rng_inc > 0.0) | |
222 { | |
223 double tmp = rng_limit; | |
224 rng_limit = min (); | |
225 rng_base = tmp; | |
226 rng_inc = -rng_inc; | |
227 clear_cache (); | |
228 reverse = true; | |
229 } | |
230 | |
231 octave_idx_type tmp = reverse ? nel - 1 : 0; | |
7467 | 232 octave_idx_type stp = reverse ? -1 : 1; |
7458 | 233 |
7467 | 234 for (octave_idx_type i = 0; i < nel; i++, tmp += stp) |
7458 | 235 psidx[i] = tmp; |
236 | |
237 } | |
238 | |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7467
diff
changeset
|
239 Matrix |
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7467
diff
changeset
|
240 Range::diag (octave_idx_type k) const |
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7467
diff
changeset
|
241 { |
8971 | 242 return matrix_value ().diag (k); |
7620
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7467
diff
changeset
|
243 } |
36594d5bbe13
Move diag function into the octave_value class
David Bateman <dbateman@free.fr>
parents:
7467
diff
changeset
|
244 |
7458 | 245 Range |
246 Range::sort (octave_idx_type dim, sortmode mode) const | |
247 { | |
248 Range retval = *this; | |
249 | |
250 if (dim == 1) | |
251 { | |
7463
2467639bd8c0
eliminate UNDEFINED sort mode
John W. Eaton <jwe@octave.org>
parents:
7458
diff
changeset
|
252 if (mode == ASCENDING) |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
253 retval.sort_internal (true); |
7463
2467639bd8c0
eliminate UNDEFINED sort mode
John W. Eaton <jwe@octave.org>
parents:
7458
diff
changeset
|
254 else if (mode == DESCENDING) |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
255 retval.sort_internal (false); |
7458 | 256 } |
257 else if (dim != 0) | |
258 (*current_liboctave_error_handler) ("Range::sort: invalid dimension"); | |
259 | |
260 return retval; | |
261 } | |
262 | |
263 Range | |
264 Range::sort (Array<octave_idx_type>& sidx, octave_idx_type dim, | |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
265 sortmode mode) const |
7458 | 266 { |
267 Range retval = *this; | |
268 | |
269 if (dim == 1) | |
270 { | |
7463
2467639bd8c0
eliminate UNDEFINED sort mode
John W. Eaton <jwe@octave.org>
parents:
7458
diff
changeset
|
271 if (mode == ASCENDING) |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
272 retval.sort_internal (sidx, true); |
7463
2467639bd8c0
eliminate UNDEFINED sort mode
John W. Eaton <jwe@octave.org>
parents:
7458
diff
changeset
|
273 else if (mode == DESCENDING) |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
274 retval.sort_internal (sidx, false); |
7458 | 275 } |
276 else if (dim != 0) | |
277 (*current_liboctave_error_handler) ("Range::sort: invalid dimension"); | |
278 | |
279 return retval; | |
208 | 280 } |
281 | |
8721
e9cb742df9eb
imported patch sort3.diff
Jaroslav Hajek <highegg@gmail.com>
parents:
8589
diff
changeset
|
282 sortmode |
e9cb742df9eb
imported patch sort3.diff
Jaroslav Hajek <highegg@gmail.com>
parents:
8589
diff
changeset
|
283 Range::is_sorted (sortmode mode) const |
e9cb742df9eb
imported patch sort3.diff
Jaroslav Hajek <highegg@gmail.com>
parents:
8589
diff
changeset
|
284 { |
e9cb742df9eb
imported patch sort3.diff
Jaroslav Hajek <highegg@gmail.com>
parents:
8589
diff
changeset
|
285 if (rng_nelem > 1 && rng_inc < 0) |
e9cb742df9eb
imported patch sort3.diff
Jaroslav Hajek <highegg@gmail.com>
parents:
8589
diff
changeset
|
286 mode = (mode == ASCENDING) ? UNSORTED : DESCENDING; |
e9cb742df9eb
imported patch sort3.diff
Jaroslav Hajek <highegg@gmail.com>
parents:
8589
diff
changeset
|
287 else if (rng_nelem > 1 && rng_inc > 0) |
e9cb742df9eb
imported patch sort3.diff
Jaroslav Hajek <highegg@gmail.com>
parents:
8589
diff
changeset
|
288 mode = (mode == DESCENDING) ? UNSORTED : ASCENDING; |
e9cb742df9eb
imported patch sort3.diff
Jaroslav Hajek <highegg@gmail.com>
parents:
8589
diff
changeset
|
289 else |
e9cb742df9eb
imported patch sort3.diff
Jaroslav Hajek <highegg@gmail.com>
parents:
8589
diff
changeset
|
290 mode = mode ? mode : ASCENDING; |
8742
d2b06871afac
add missing return statement
Jaroslav Hajek <highegg@gmail.com>
parents:
8721
diff
changeset
|
291 |
d2b06871afac
add missing return statement
Jaroslav Hajek <highegg@gmail.com>
parents:
8721
diff
changeset
|
292 return mode; |
8721
e9cb742df9eb
imported patch sort3.diff
Jaroslav Hajek <highegg@gmail.com>
parents:
8589
diff
changeset
|
293 } |
e9cb742df9eb
imported patch sort3.diff
Jaroslav Hajek <highegg@gmail.com>
parents:
8589
diff
changeset
|
294 |
3504 | 295 std::ostream& |
296 operator << (std::ostream& os, const Range& a) | |
3 | 297 { |
298 double b = a.base (); | |
299 double increment = a.inc (); | |
5275 | 300 octave_idx_type num_elem = a.nelem (); |
3 | 301 |
5275 | 302 for (octave_idx_type i = 0; i < num_elem-1; i++) |
3 | 303 os << b + i * increment << " "; |
304 | |
4791 | 305 // Prevent overshoot. See comment in the matrix_value method |
306 // above. | |
307 | |
308 os << (increment > 0 ? a.max () : a.min ()) << "\n"; | |
3 | 309 |
310 return os; | |
311 } | |
312 | |
3504 | 313 std::istream& |
314 operator >> (std::istream& is, Range& a) | |
3 | 315 { |
208 | 316 is >> a.rng_base; |
3 | 317 if (is) |
318 { | |
208 | 319 is >> a.rng_limit; |
3 | 320 if (is) |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
321 { |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
322 is >> a.rng_inc; |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
323 a.rng_nelem = a.nelem_internal (); |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
324 } |
3 | 325 } |
326 | |
327 return is; | |
328 } | |
329 | |
2599 | 330 Range |
331 operator - (const Range& r) | |
332 { | |
8589
0131fa223dbc
make length invariant in range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
8565
diff
changeset
|
333 return Range (-r.base (), -r.inc (), r.nelem ()); |
2599 | 334 } |
335 | |
8553
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
336 Range operator + (double x, const Range& r) |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
337 { |
8971 | 338 Range result (x + r.base (), r.inc (), r.nelem ()); |
339 if (result.rng_nelem < 0) | |
340 result.cache = x + r.matrix_value (); | |
341 | |
342 return result; | |
8553
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
343 } |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
344 |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
345 Range operator + (const Range& r, double x) |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
346 { |
8971 | 347 Range result (r.base () + x, r.inc (), r.nelem ()); |
348 if (result.rng_nelem < 0) | |
349 result.cache = r.matrix_value () + x; | |
350 | |
351 return result; | |
8553
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
352 } |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
353 |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
354 Range operator - (double x, const Range& r) |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
355 { |
8971 | 356 Range result (x - r.base (), -r.inc (), r.nelem ()); |
357 if (result.rng_nelem < 0) | |
358 result.cache = x - r.matrix_value (); | |
359 | |
360 return result; | |
8553
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
361 } |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
362 |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
363 Range operator - (const Range& r, double x) |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
364 { |
8971 | 365 Range result (r.base () - x, r.inc (), r.nelem ()); |
366 if (result.rng_nelem < 0) | |
367 result.cache = r.matrix_value () - x; | |
368 | |
369 return result; | |
8553
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
370 } |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
371 |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
372 Range operator * (double x, const Range& r) |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
373 { |
8971 | 374 Range result (x * r.base (), x * r.inc (), r.nelem ()); |
375 if (result.rng_nelem < 0) | |
376 result.cache = x * r.matrix_value (); | |
377 | |
378 return result; | |
8553
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
379 } |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
380 |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
381 Range operator * (const Range& r, double x) |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
382 { |
8971 | 383 Range result (r.base () * x, r.inc () * x, r.nelem ()); |
384 if (result.rng_nelem < 0) | |
385 result.cache = r.matrix_value () * x; | |
386 | |
387 return result; | |
8553
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
388 } |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
389 |
c7ff200e45f5
optimize range-scalar ops
Jaroslav Hajek <highegg@gmail.com>
parents:
7620
diff
changeset
|
390 |
1546 | 391 // C See Knuth, Art Of Computer Programming, Vol. 1, Problem 1.2.4-5. |
392 // C | |
393 // C===Tolerant FLOOR function. | |
394 // C | |
395 // C X - is given as a Double Precision argument to be operated on. | |
396 // C It is assumed that X is represented with M mantissa bits. | |
397 // C CT - is given as a Comparison Tolerance such that | |
398 // C 0.LT.CT.LE.3-SQRT(5)/2. If the relative difference between | |
399 // C X and A whole number is less than CT, then TFLOOR is | |
400 // C returned as this whole number. By treating the | |
401 // C floating-point numbers as a finite ordered set note that | |
402 // C the heuristic EPS=2.**(-(M-1)) and CT=3*EPS causes | |
403 // C arguments of TFLOOR/TCEIL to be treated as whole numbers | |
404 // C if they are exactly whole numbers or are immediately | |
405 // C adjacent to whole number representations. Since EPS, the | |
406 // C "distance" between floating-point numbers on the unit | |
407 // C interval, and M, the number of bits in X'S mantissa, exist | |
408 // C on every floating-point computer, TFLOOR/TCEIL are | |
409 // C consistently definable on every floating-point computer. | |
410 // C | |
411 // C For more information see the following references: | |
412 // C (1) P. E. Hagerty, "More On Fuzzy Floor And Ceiling," APL QUOTE | |
413 // C QUAD 8(4):20-24, June 1978. Note that TFLOOR=FL5. | |
414 // C (2) L. M. Breed, "Definitions For Fuzzy Floor And Ceiling", APL | |
415 // C QUOTE QUAD 8(3):16-23, March 1978. This paper cites FL1 through | |
416 // C FL5, the history of five years of evolutionary development of | |
417 // C FL5 - the seven lines of code below - by open collaboration | |
418 // C and corroboration of the mathematical-computing community. | |
419 // C | |
420 // C Penn State University Center for Academic Computing | |
421 // C H. D. Knoble - August, 1978. | |
422 | |
423 static inline double | |
424 tfloor (double x, double ct) | |
425 { | |
426 // C---------FLOOR(X) is the largest integer algebraically less than | |
427 // C or equal to X; that is, the unfuzzy FLOOR function. | |
428 | |
429 // DINT (X) = X - DMOD (X, 1.0); | |
430 // FLOOR (X) = DINT (X) - DMOD (2.0 + DSIGN (1.0, X), 3.0); | |
431 | |
432 // C---------Hagerty's FL5 function follows... | |
433 | |
434 double q = 1.0; | |
435 | |
436 if (x < 0.0) | |
437 q = 1.0 - ct; | |
438 | |
439 double rmax = q / (2.0 - ct); | |
440 | |
441 double t1 = 1.0 + floor (x); | |
442 t1 = (ct / q) * (t1 < 0.0 ? -t1 : t1); | |
443 t1 = rmax < t1 ? rmax : t1; | |
444 t1 = ct > t1 ? ct : t1; | |
445 t1 = floor (x + t1); | |
446 | |
1555 | 447 if (x <= 0.0 || (t1 - x) < rmax) |
1546 | 448 return t1; |
449 else | |
450 return t1 - 1.0; | |
451 } | |
452 | |
453 static inline double | |
454 tceil (double x, double ct) | |
455 { | |
456 return -tfloor (-x, ct); | |
457 } | |
458 | |
3753 | 459 static inline bool |
460 teq (double u, double v, double ct = 3.0 * DBL_EPSILON) | |
461 { | |
462 double tu = fabs (u); | |
463 double tv = fabs (v); | |
464 | |
465 return fabs (u - v) < ((tu > tv ? tu : tv) * ct); | |
466 } | |
467 | |
5275 | 468 octave_idx_type |
1360 | 469 Range::nelem_internal (void) const |
470 { | |
5275 | 471 octave_idx_type retval = -1; |
3 | 472 |
3858 | 473 if (rng_inc == 0 |
474 || (rng_limit > rng_base && rng_inc < 0) | |
475 || (rng_limit < rng_base && rng_inc > 0)) | |
476 { | |
477 retval = 0; | |
478 } | |
479 else | |
480 { | |
481 double ct = 3.0 * DBL_EPSILON; | |
3 | 482 |
3858 | 483 double tmp = tfloor ((rng_limit - rng_base + rng_inc) / rng_inc, ct); |
484 | |
5275 | 485 octave_idx_type n_elt = (tmp > 0.0 ? static_cast<octave_idx_type> (tmp) : 0); |
398 | 486 |
3858 | 487 // If the final element that we would compute for the range is |
488 // equal to the limit of the range, or is an adjacent floating | |
489 // point number, accept it. Otherwise, try a range with one | |
490 // fewer element. If that fails, try again with one more | |
491 // element. | |
492 // | |
493 // I'm not sure this is very good, but it seems to work better than | |
494 // just using tfloor as above. For example, without it, the | |
495 // expression 1.8:0.05:1.9 fails to produce the expected result of | |
496 // [1.8, 1.85, 1.9]. | |
3753 | 497 |
3858 | 498 if (! teq (rng_base + (n_elt - 1) * rng_inc, rng_limit)) |
10314
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
499 { |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
500 if (teq (rng_base + (n_elt - 2) * rng_inc, rng_limit)) |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
501 n_elt--; |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
502 else if (teq (rng_base + n_elt * rng_inc, rng_limit)) |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
503 n_elt++; |
07ebe522dac2
untabify liboctave C++ sources
John W. Eaton <jwe@octave.org>
parents:
10158
diff
changeset
|
504 } |
3858 | 505 |
6490 | 506 retval = (n_elt >= std::numeric_limits<octave_idx_type>::max () - 1) ? -1 : n_elt; |
3753 | 507 } |
508 | |
3858 | 509 return retval; |
3 | 510 } |