Mercurial > hg > octave-nkf
annotate src/ov-range.cc @ 7923:c3d21b9b94b6
eliminate octave_call_stack member functions caller_user_script and caller_user_function, and unused difference_type args
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 11 Jul 2008 15:43:10 -0400 |
parents | 82be108cc558 |
children | c777f3ce02d8 |
rev | line source |
---|---|
2376 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2006, |
4 2007 John W. Eaton | |
2376 | 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. | |
2376 | 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/>. | |
2376 | 21 |
22 */ | |
23 | |
24 #ifdef HAVE_CONFIG_H | |
25 #include <config.h> | |
26 #endif | |
27 | |
3503 | 28 #include <iostream> |
2901 | 29 |
2376 | 30 #include "lo-ieee.h" |
31 #include "lo-utils.h" | |
32 | |
33 #include "gripes.h" | |
34 #include "ops.h" | |
3933 | 35 #include "oct-obj.h" |
2376 | 36 #include "ov-range.h" |
37 #include "ov-re-mat.h" | |
2410 | 38 #include "ov-scalar.h" |
2376 | 39 #include "pr-output.h" |
40 | |
4687 | 41 #include "byte-swap.h" |
42 #include "ls-hdf5.h" | |
43 #include "ls-utils.h" | |
44 | |
3219 | 45 DEFINE_OCTAVE_ALLOCATOR (octave_range); |
2376 | 46 |
4612 | 47 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_range, "range", "double"); |
2376 | 48 |
5759 | 49 static octave_base_value * |
50 default_numeric_conversion_function (const octave_base_value& a) | |
2376 | 51 { |
52 CAST_CONV_ARG (const octave_range&); | |
53 | |
54 return new octave_matrix (v.matrix_value ()); | |
55 } | |
56 | |
5759 | 57 octave_base_value::type_conv_fcn |
2376 | 58 octave_range::numeric_conversion_function (void) const |
59 { | |
60 return default_numeric_conversion_function; | |
61 } | |
62 | |
5759 | 63 octave_base_value * |
2410 | 64 octave_range::try_narrowing_conversion (void) |
65 { | |
5759 | 66 octave_base_value *retval = 0; |
2410 | 67 |
68 switch (range.nelem ()) | |
69 { | |
70 case 1: | |
71 retval = new octave_scalar (range.base ()); | |
72 break; | |
73 | |
74 case 0: | |
4417 | 75 retval = new octave_matrix (Matrix (1, 0)); |
2410 | 76 break; |
77 | |
78 default: | |
79 break; | |
80 } | |
81 | |
82 return retval; | |
83 } | |
84 | |
2436 | 85 octave_value |
4247 | 86 octave_range::subsref (const std::string& type, |
4219 | 87 const std::list<octave_value_list>& idx) |
3933 | 88 { |
89 octave_value retval; | |
90 | |
91 switch (type[0]) | |
92 { | |
93 case '(': | |
94 retval = do_index_op (idx.front ()); | |
95 break; | |
96 | |
97 case '{': | |
98 case '.': | |
99 { | |
100 std::string nm = type_name (); | |
101 error ("%s cannot be indexed with %c", nm.c_str (), type[0]); | |
102 } | |
103 break; | |
104 | |
105 default: | |
106 panic_impossible (); | |
107 } | |
108 | |
109 return retval.next_subsref (type, idx); | |
110 } | |
111 | |
112 octave_value | |
5885 | 113 octave_range::do_index_op (const octave_value_list& idx, bool resize_ok) |
2436 | 114 { |
5775 | 115 // FIXME -- this doesn't solve the problem of |
2436 | 116 // |
117 // a = 1:5; a(1, 1, 1) | |
118 // | |
119 // and similar constructions. Hmm... | |
120 | |
5775 | 121 // FIXME -- using this constructor avoids possibly narrowing |
2436 | 122 // the range to a scalar value. Need a better solution to this |
123 // problem. | |
124 | |
125 octave_value tmp (new octave_matrix (range.matrix_value ())); | |
126 | |
3933 | 127 return tmp.do_index_op (idx, resize_ok); |
2436 | 128 } |
129 | |
2376 | 130 double |
131 octave_range::double_value (bool) const | |
132 { | |
4102 | 133 double retval = lo_ieee_nan_value (); |
2376 | 134 |
5275 | 135 octave_idx_type nel = range.nelem (); |
2376 | 136 |
4455 | 137 if (nel > 0) |
138 { | |
5781 | 139 gripe_implicit_conversion ("Octave:array-as-scalar", |
140 "range", "real scalar"); | |
4455 | 141 |
142 retval = range.base (); | |
143 } | |
2376 | 144 else |
145 gripe_invalid_conversion ("range", "real scalar"); | |
146 | |
147 return retval; | |
148 } | |
149 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
150 float |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
151 octave_range::float_value (bool) const |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
152 { |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
153 float retval = lo_ieee_float_nan_value (); |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
154 |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
155 octave_idx_type nel = range.nelem (); |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
156 |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
157 if (nel > 0) |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
158 { |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
159 gripe_implicit_conversion ("Octave:array-as-scalar", |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
160 "range", "real scalar"); |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
161 |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
162 retval = range.base (); |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
163 } |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
164 else |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
165 gripe_invalid_conversion ("range", "real scalar"); |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
166 |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
167 return retval; |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
168 } |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
169 |
2376 | 170 octave_value |
4017 | 171 octave_range::all (int dim) const |
2376 | 172 { |
5775 | 173 // FIXME -- this is a potential waste of memory. |
2436 | 174 |
175 Matrix m = range.matrix_value (); | |
176 | |
4017 | 177 return m.all (dim); |
2376 | 178 } |
179 | |
180 octave_value | |
4017 | 181 octave_range::any (int dim) const |
2376 | 182 { |
5775 | 183 // FIXME -- this is a potential waste of memory. |
4017 | 184 |
185 Matrix m = range.matrix_value (); | |
186 | |
187 return m.any (dim); | |
2376 | 188 } |
189 | |
190 bool | |
191 octave_range::is_true (void) const | |
192 { | |
193 bool retval = false; | |
2436 | 194 |
4478 | 195 if (range.nelem () != 0) |
2436 | 196 { |
5775 | 197 // FIXME -- this is a potential waste of memory. |
2436 | 198 |
199 Matrix m ((range.matrix_value () . all ()) . all ()); | |
200 | |
201 retval = (m.rows () == 1 && m.columns () == 1 && m (0, 0) != 0.0); | |
202 } | |
203 | |
2376 | 204 return retval; |
205 } | |
206 | |
207 Complex | |
208 octave_range::complex_value (bool) const | |
209 { | |
4102 | 210 double tmp = lo_ieee_nan_value (); |
211 | |
212 Complex retval (tmp, tmp); | |
2376 | 213 |
5275 | 214 octave_idx_type nel = range.nelem (); |
2376 | 215 |
4455 | 216 if (nel > 0) |
217 { | |
5781 | 218 gripe_implicit_conversion ("Octave:array-as-scalar", |
219 "range", "complex scalar"); | |
4455 | 220 |
221 retval = range.base (); | |
222 } | |
2376 | 223 else |
224 gripe_invalid_conversion ("range", "complex scalar"); | |
225 | |
226 return retval; | |
227 } | |
228 | |
7789
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
229 FloatComplex |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
230 octave_range::float_complex_value (bool) const |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
231 { |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
232 float tmp = lo_ieee_float_nan_value (); |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
233 |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
234 FloatComplex retval (tmp, tmp); |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
235 |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
236 octave_idx_type nel = range.nelem (); |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
237 |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
238 if (nel > 0) |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
239 { |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
240 gripe_implicit_conversion ("Octave:array-as-scalar", |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
241 "range", "complex scalar"); |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
242 |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
243 retval = range.base (); |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
244 } |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
245 else |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
246 gripe_invalid_conversion ("range", "complex scalar"); |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
247 |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
248 return retval; |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
249 } |
82be108cc558
First attempt at single precision tyeps
David Bateman <dbateman@free.fr>
parents:
7017
diff
changeset
|
250 |
5731 | 251 octave_value |
252 octave_range::resize (const dim_vector& dv, bool fill) const | |
253 { | |
254 NDArray retval = array_value (); | |
255 if (fill) | |
256 retval.resize (dv, NDArray::resize_fill_value()); | |
257 else | |
258 retval.resize (dv); | |
259 return retval; | |
260 } | |
261 | |
2376 | 262 octave_value |
5279 | 263 octave_range::convert_to_str_internal (bool pad, bool force, char type) const |
2449 | 264 { |
265 octave_value tmp (range.matrix_value ()); | |
5279 | 266 return tmp.convert_to_str (pad, force, type); |
2449 | 267 } |
268 | |
2376 | 269 void |
3523 | 270 octave_range::print (std::ostream& os, bool pr_as_read_syntax) const |
2901 | 271 { |
272 print_raw (os, pr_as_read_syntax); | |
273 newline (os); | |
274 } | |
275 | |
276 void | |
3523 | 277 octave_range::print_raw (std::ostream& os, bool pr_as_read_syntax) const |
2901 | 278 { |
279 octave_print_internal (os, range, pr_as_read_syntax, | |
280 current_print_indent_level ()); | |
281 } | |
282 | |
283 bool | |
3523 | 284 octave_range::print_name_tag (std::ostream& os, const std::string& name) const |
2376 | 285 { |
2901 | 286 bool retval = false; |
287 | |
5275 | 288 octave_idx_type n = range.nelem (); |
2901 | 289 |
290 indent (os); | |
291 | |
292 if (n == 0 || n == 1) | |
293 os << name << " = "; | |
294 else | |
295 { | |
296 os << name << " ="; | |
297 newline (os); | |
298 newline (os); | |
299 retval = true; | |
300 } | |
301 | |
302 return retval; | |
2376 | 303 } |
304 | |
4687 | 305 // Skip white space and comments on stream IS. |
306 | |
307 static void | |
308 skip_comments (std::istream& is) | |
309 { | |
310 char c = '\0'; | |
311 while (is.get (c)) | |
312 { | |
313 if (c == ' ' || c == '\t' || c == '\n') | |
314 ; // Skip whitespace on way to beginning of next line. | |
315 else | |
316 break; | |
317 } | |
318 | |
319 for (;;) | |
320 { | |
321 if (is && (c == '%' || c == '#')) | |
322 while (is.get (c) && c != '\n') | |
323 ; // Skip to beginning of next line, ignoring everything. | |
324 else | |
325 break; | |
326 } | |
327 } | |
328 | |
329 bool | |
6974 | 330 octave_range::save_ascii (std::ostream& os) |
4687 | 331 { |
332 Range r = range_value (); | |
333 double base = r.base (); | |
334 double limit = r.limit (); | |
335 double inc = r.inc (); | |
336 | |
337 os << "# base, limit, increment\n"; | |
338 octave_write_double (os, base); | |
339 os << " "; | |
340 octave_write_double (os, limit); | |
341 os << " "; | |
342 octave_write_double (os, inc); | |
343 os << "\n"; | |
344 | |
345 return true; | |
346 } | |
347 | |
348 bool | |
349 octave_range::load_ascii (std::istream& is) | |
350 { | |
351 // # base, limit, range comment added by save (). | |
352 skip_comments (is); | |
353 | |
354 is >> range; | |
355 | |
356 if (!is) | |
357 { | |
358 error ("load: failed to load range constant"); | |
359 return false; | |
360 } | |
361 | |
362 return true; | |
363 } | |
364 | |
365 bool | |
366 octave_range::save_binary (std::ostream& os, bool& /* save_as_floats */) | |
367 { | |
5760 | 368 char tmp = LS_DOUBLE; |
369 os.write (reinterpret_cast<char *> (&tmp), 1); | |
4687 | 370 Range r = range_value (); |
371 double bas = r.base (); | |
372 double lim = r.limit (); | |
373 double inc = r.inc (); | |
5760 | 374 os.write (reinterpret_cast<char *> (&bas), 8); |
375 os.write (reinterpret_cast<char *> (&lim), 8); | |
376 os.write (reinterpret_cast<char *> (&inc), 8); | |
4687 | 377 |
378 return true; | |
379 } | |
380 | |
381 bool | |
382 octave_range::load_binary (std::istream& is, bool swap, | |
383 oct_mach_info::float_format /* fmt */) | |
384 { | |
385 char tmp; | |
5760 | 386 if (! is.read (reinterpret_cast<char *> (&tmp), 1)) |
4687 | 387 return false; |
388 double bas, lim, inc; | |
5760 | 389 if (! is.read (reinterpret_cast<char *> (&bas), 8)) |
4687 | 390 return false; |
391 if (swap) | |
4944 | 392 swap_bytes<8> (&bas); |
5760 | 393 if (! is.read (reinterpret_cast<char *> (&lim), 8)) |
4687 | 394 return false; |
395 if (swap) | |
4944 | 396 swap_bytes<8> (&lim); |
5760 | 397 if (! is.read (reinterpret_cast<char *> (&inc), 8)) |
4687 | 398 return false; |
399 if (swap) | |
4944 | 400 swap_bytes<8> (&inc); |
4687 | 401 Range r (bas, lim, inc); |
402 range = r; | |
403 return true; | |
404 } | |
405 | |
406 #if defined (HAVE_HDF5) | |
4944 | 407 |
4687 | 408 // The following subroutines creates an HDF5 representation of the way |
409 // we will store Octave range types (triplets of floating-point numbers). | |
410 // NUM_TYPE is the HDF5 numeric type to use for storage (e.g. | |
411 // H5T_NATIVE_DOUBLE to save as 'double'). Note that any necessary | |
412 // conversions are handled automatically by HDF5. | |
413 | |
414 static hid_t | |
415 hdf5_make_range_type (hid_t num_type) | |
416 { | |
417 hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 3); | |
418 | |
419 H5Tinsert (type_id, "base", 0 * sizeof (double), num_type); | |
420 H5Tinsert (type_id, "limit", 1 * sizeof (double), num_type); | |
421 H5Tinsert (type_id, "increment", 2 * sizeof (double), num_type); | |
422 | |
423 return type_id; | |
424 } | |
425 | |
426 bool | |
427 octave_range::save_hdf5 (hid_t loc_id, const char *name, | |
428 bool /* save_as_floats */) | |
429 { | |
4792 | 430 hsize_t dimens[3]; |
4687 | 431 hid_t space_hid = -1, type_hid = -1, data_hid = -1; |
432 bool retval = true; | |
433 | |
4815 | 434 space_hid = H5Screate_simple (0, dimens, 0); |
4687 | 435 if (space_hid < 0) return false; |
436 | |
437 type_hid = hdf5_make_range_type (H5T_NATIVE_DOUBLE); | |
438 if (type_hid < 0) | |
439 { | |
440 H5Sclose (space_hid); | |
441 return false; | |
442 } | |
443 | |
444 data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, H5P_DEFAULT); | |
445 if (data_hid < 0) | |
446 { | |
447 H5Sclose (space_hid); | |
448 H5Tclose (type_hid); | |
449 return false; | |
450 } | |
451 | |
452 Range r = range_value (); | |
453 double range_vals[3]; | |
454 range_vals[0] = r.base (); | |
455 range_vals[1] = r.limit (); | |
456 range_vals[2] = r.inc (); | |
457 | |
458 retval = H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL, H5P_DEFAULT, | |
4815 | 459 range_vals) >= 0; |
4687 | 460 |
461 H5Dclose (data_hid); | |
462 H5Tclose (type_hid); | |
463 H5Sclose (space_hid); | |
4837 | 464 |
4687 | 465 return retval; |
466 } | |
467 | |
468 bool | |
469 octave_range::load_hdf5 (hid_t loc_id, const char *name, | |
470 bool /* have_h5giterate_bug */) | |
471 { | |
472 bool retval = false; | |
4837 | 473 |
4687 | 474 hid_t data_hid = H5Dopen (loc_id, name); |
475 hid_t type_hid = H5Dget_type (data_hid); | |
476 | |
477 hid_t range_type = hdf5_make_range_type (H5T_NATIVE_DOUBLE); | |
478 | |
479 if (! hdf5_types_compatible (type_hid, range_type)) | |
480 { | |
4837 | 481 H5Tclose (range_type); |
4687 | 482 H5Dclose (data_hid); |
483 return false; | |
484 } | |
485 | |
486 hid_t space_hid = H5Dget_space (data_hid); | |
487 hsize_t rank = H5Sget_simple_extent_ndims (space_hid); | |
488 | |
489 if (rank != 0) | |
490 { | |
4837 | 491 H5Tclose (range_type); |
4687 | 492 H5Sclose (space_hid); |
493 H5Dclose (data_hid); | |
494 return false; | |
495 } | |
496 | |
497 double rangevals[3]; | |
498 if (H5Dread (data_hid, range_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, | |
4815 | 499 rangevals) >= 0) |
4687 | 500 { |
501 retval = true; | |
502 Range r (rangevals[0], rangevals[1], rangevals[2]); | |
503 range = r; | |
504 } | |
505 | |
4837 | 506 H5Tclose (range_type); |
4687 | 507 H5Sclose (space_hid); |
508 H5Dclose (data_hid); | |
4837 | 509 |
4687 | 510 return retval; |
511 } | |
4944 | 512 |
4687 | 513 #endif |
514 | |
5900 | 515 mxArray * |
516 octave_range::as_mxArray (void) const | |
517 { | |
518 mxArray *retval = new mxArray (mxDOUBLE_CLASS, dims (), mxREAL); | |
519 | |
520 double *pr = static_cast<double *> (retval->get_data ()); | |
521 | |
6686 | 522 mwSize nel = numel (); |
5900 | 523 |
524 Matrix m = matrix_value (); | |
525 | |
526 const double *p = m.data (); | |
527 | |
6686 | 528 for (mwSize i = 0; i < nel; i++) |
5900 | 529 pr[i] = p[i]; |
530 | |
531 return retval; | |
532 } | |
533 | |
2376 | 534 /* |
535 ;;; Local Variables: *** | |
536 ;;; mode: C++ *** | |
537 ;;; End: *** | |
538 */ |