Mercurial > octave-nkf
comparison src/ov-flt-re-mat.cc @ 7789:82be108cc558
First attempt at single precision tyeps
* * *
corrections to qrupdate single precision routines
* * *
prefer demotion to single over promotion to double
* * *
Add single precision support to log2 function
* * *
Trivial PROJECT file update
* * *
Cache optimized hermitian/transpose methods
* * *
Add tests for tranpose/hermitian and ChangeLog entry for new transpose code
author | David Bateman <dbateman@free.fr> |
---|---|
date | Sun, 27 Apr 2008 22:34:17 +0200 |
parents | |
children | a41df65f3f00 |
comparison
equal
deleted
inserted
replaced
7788:45f5faba05a2 | 7789:82be108cc558 |
---|---|
1 /* | |
2 | |
3 Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, | |
4 2006, 2007 John W. Eaton | |
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 | |
10 Free Software Foundation; either version 3 of the License, or (at your | |
11 option) any later version. | |
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 | |
19 along with Octave; see the file COPYING. If not, see | |
20 <http://www.gnu.org/licenses/>. | |
21 | |
22 */ | |
23 | |
24 #ifdef HAVE_CONFIG_H | |
25 #include <config.h> | |
26 #endif | |
27 | |
28 #include <climits> | |
29 | |
30 #include <iostream> | |
31 #include <vector> | |
32 | |
33 #include "data-conv.h" | |
34 #include "lo-ieee.h" | |
35 #include "lo-utils.h" | |
36 #include "lo-specfun.h" | |
37 #include "lo-mappers.h" | |
38 #include "mach-info.h" | |
39 #include "mx-base.h" | |
40 #include "quit.h" | |
41 | |
42 #include "defun.h" | |
43 #include "gripes.h" | |
44 #include "oct-obj.h" | |
45 #include "oct-lvalue.h" | |
46 #include "oct-stream.h" | |
47 #include "ops.h" | |
48 #include "ov-base.h" | |
49 #include "ov-base-mat.h" | |
50 #include "ov-base-mat.cc" | |
51 #include "ov-scalar.h" | |
52 #include "ov-float.h" | |
53 #include "ov-flt-complex.h" | |
54 #include "ov-re-mat.h" | |
55 #include "ov-flt-re-mat.h" | |
56 #include "ov-flt-cx-mat.h" | |
57 #include "ov-re-sparse.h" | |
58 #include "ov-type-conv.h" | |
59 #include "pr-output.h" | |
60 #include "variables.h" | |
61 #include "ops.h" | |
62 | |
63 #include "byte-swap.h" | |
64 #include "ls-oct-ascii.h" | |
65 #include "ls-utils.h" | |
66 #include "ls-hdf5.h" | |
67 | |
68 #if ! defined (UCHAR_MAX) | |
69 #define UCHAR_MAX 255 | |
70 #endif | |
71 | |
72 template class octave_base_matrix<FloatNDArray>; | |
73 | |
74 DEFINE_OCTAVE_ALLOCATOR (octave_float_matrix); | |
75 | |
76 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_matrix, "float matrix", "single"); | |
77 | |
78 octave_base_value * | |
79 octave_float_matrix::try_narrowing_conversion (void) | |
80 { | |
81 octave_base_value *retval = 0; | |
82 | |
83 if (matrix.nelem () == 1) | |
84 retval = new octave_float_scalar (matrix (0)); | |
85 | |
86 return retval; | |
87 } | |
88 | |
89 bool | |
90 octave_float_matrix::valid_as_scalar_index (void) const | |
91 { | |
92 // FIXME | |
93 return false; | |
94 } | |
95 | |
96 double | |
97 octave_float_matrix::double_value (bool) const | |
98 { | |
99 double retval = lo_ieee_nan_value (); | |
100 | |
101 if (numel () > 0) | |
102 { | |
103 gripe_implicit_conversion ("Octave:array-as-scalar", | |
104 "real matrix", "real scalar"); | |
105 | |
106 retval = matrix (0, 0); | |
107 } | |
108 else | |
109 gripe_invalid_conversion ("real matrix", "real scalar"); | |
110 | |
111 return retval; | |
112 } | |
113 | |
114 float | |
115 octave_float_matrix::float_value (bool) const | |
116 { | |
117 float retval = lo_ieee_float_nan_value (); | |
118 | |
119 if (numel () > 0) | |
120 { | |
121 gripe_implicit_conversion ("Octave:array-as-scalar", | |
122 "real matrix", "real scalar"); | |
123 | |
124 retval = matrix (0, 0); | |
125 } | |
126 else | |
127 gripe_invalid_conversion ("real matrix", "real scalar"); | |
128 | |
129 return retval; | |
130 } | |
131 | |
132 // FIXME | |
133 | |
134 Matrix | |
135 octave_float_matrix::matrix_value (bool) const | |
136 { | |
137 return Matrix (matrix.matrix_value ()); | |
138 } | |
139 | |
140 FloatMatrix | |
141 octave_float_matrix::float_matrix_value (bool) const | |
142 { | |
143 return matrix.matrix_value (); | |
144 } | |
145 | |
146 Complex | |
147 octave_float_matrix::complex_value (bool) const | |
148 { | |
149 double tmp = lo_ieee_nan_value (); | |
150 | |
151 Complex retval (tmp, tmp); | |
152 | |
153 if (rows () > 0 && columns () > 0) | |
154 { | |
155 gripe_implicit_conversion ("Octave:array-as-scalar", | |
156 "real matrix", "complex scalar"); | |
157 | |
158 retval = matrix (0, 0); | |
159 } | |
160 else | |
161 gripe_invalid_conversion ("real matrix", "complex scalar"); | |
162 | |
163 return retval; | |
164 } | |
165 | |
166 FloatComplex | |
167 octave_float_matrix::float_complex_value (bool) const | |
168 { | |
169 double tmp = lo_ieee_float_nan_value (); | |
170 | |
171 FloatComplex retval (tmp, tmp); | |
172 | |
173 if (rows () > 0 && columns () > 0) | |
174 { | |
175 gripe_implicit_conversion ("Octave:array-as-scalar", | |
176 "real matrix", "complex scalar"); | |
177 | |
178 retval = matrix (0, 0); | |
179 } | |
180 else | |
181 gripe_invalid_conversion ("real matrix", "complex scalar"); | |
182 | |
183 return retval; | |
184 } | |
185 | |
186 // FIXME | |
187 | |
188 ComplexMatrix | |
189 octave_float_matrix::complex_matrix_value (bool) const | |
190 { | |
191 return ComplexMatrix (matrix.matrix_value ()); | |
192 } | |
193 | |
194 FloatComplexMatrix | |
195 octave_float_matrix::float_complex_matrix_value (bool) const | |
196 { | |
197 return FloatComplexMatrix (matrix.matrix_value ()); | |
198 } | |
199 | |
200 ComplexNDArray | |
201 octave_float_matrix::complex_array_value (bool) const | |
202 { | |
203 return ComplexNDArray (matrix); | |
204 } | |
205 | |
206 FloatComplexNDArray | |
207 octave_float_matrix::float_complex_array_value (bool) const | |
208 { | |
209 return FloatComplexNDArray (matrix); | |
210 } | |
211 | |
212 NDArray | |
213 octave_float_matrix::array_value (bool) const | |
214 { | |
215 return NDArray (matrix); | |
216 } | |
217 | |
218 boolNDArray | |
219 octave_float_matrix::bool_array_value (bool warn) const | |
220 { | |
221 if (warn && matrix.any_element_not_one_or_zero ()) | |
222 gripe_logical_conversion (); | |
223 | |
224 return boolNDArray (matrix); | |
225 } | |
226 | |
227 charNDArray | |
228 octave_float_matrix::char_array_value (bool) const | |
229 { | |
230 charNDArray retval (dims ()); | |
231 | |
232 octave_idx_type nel = numel (); | |
233 | |
234 for (octave_idx_type i = 0; i < nel; i++) | |
235 retval.elem (i) = static_cast<char>(matrix.elem (i)); | |
236 | |
237 return retval; | |
238 } | |
239 | |
240 SparseMatrix | |
241 octave_float_matrix::sparse_matrix_value (bool) const | |
242 { | |
243 return SparseMatrix (matrix.matrix_value ()); | |
244 } | |
245 | |
246 SparseComplexMatrix | |
247 octave_float_matrix::sparse_complex_matrix_value (bool) const | |
248 { | |
249 // FIXME Need a SparseComplexMatrix (Matrix) constructor to make | |
250 // this function more efficient. Then this should become | |
251 // return SparseComplexMatrix (matrix.matrix_value ()); | |
252 return SparseComplexMatrix (sparse_matrix_value ()); | |
253 } | |
254 | |
255 streamoff_array | |
256 octave_float_matrix::streamoff_array_value (void) const | |
257 { | |
258 streamoff_array retval (dims ()); | |
259 | |
260 octave_idx_type nel = numel (); | |
261 | |
262 for (octave_idx_type i = 0; i < nel; i++) | |
263 { | |
264 float d = matrix(i); | |
265 | |
266 if (F_NINT (d) == d) | |
267 retval(i) = std::streamoff (static_cast<long> (d)); | |
268 else | |
269 { | |
270 error ("conversion to streamoff_array value failed"); | |
271 break; | |
272 } | |
273 } | |
274 | |
275 return retval; | |
276 } | |
277 | |
278 octave_value | |
279 octave_float_matrix::convert_to_str_internal (bool, bool, char type) const | |
280 { | |
281 octave_value retval; | |
282 dim_vector dv = dims (); | |
283 octave_idx_type nel = dv.numel (); | |
284 | |
285 charNDArray chm (dv); | |
286 | |
287 bool warned = false; | |
288 | |
289 for (octave_idx_type i = 0; i < nel; i++) | |
290 { | |
291 OCTAVE_QUIT; | |
292 | |
293 float d = matrix (i); | |
294 | |
295 if (xisnan (d)) | |
296 { | |
297 ::error ("invalid conversion from NaN to character"); | |
298 return retval; | |
299 } | |
300 else | |
301 { | |
302 int ival = NINT (d); | |
303 | |
304 if (ival < 0 || ival > UCHAR_MAX) | |
305 { | |
306 // FIXME -- is there something | |
307 // better we could do? | |
308 | |
309 ival = 0; | |
310 | |
311 if (! warned) | |
312 { | |
313 ::warning ("range error for conversion to character value"); | |
314 warned = true; | |
315 } | |
316 } | |
317 | |
318 chm (i) = static_cast<char> (ival); | |
319 } | |
320 } | |
321 | |
322 retval = octave_value (chm, true, type); | |
323 | |
324 return retval; | |
325 } | |
326 | |
327 bool | |
328 octave_float_matrix::save_ascii (std::ostream& os) | |
329 { | |
330 dim_vector d = dims (); | |
331 | |
332 if (d.length () > 2) | |
333 { | |
334 FloatNDArray tmp = float_array_value (); | |
335 | |
336 os << "# ndims: " << d.length () << "\n"; | |
337 | |
338 for (int i=0; i < d.length (); i++) | |
339 os << " " << d (i); | |
340 | |
341 os << "\n" << tmp; | |
342 } | |
343 else | |
344 { | |
345 // Keep this case, rather than use generic code above for backward | |
346 // compatiability. Makes load_ascii much more complex!! | |
347 os << "# rows: " << rows () << "\n" | |
348 << "# columns: " << columns () << "\n"; | |
349 | |
350 os << float_matrix_value (); | |
351 } | |
352 | |
353 return true; | |
354 } | |
355 | |
356 bool | |
357 octave_float_matrix::load_ascii (std::istream& is) | |
358 { | |
359 bool success = true; | |
360 | |
361 string_vector keywords(2); | |
362 | |
363 keywords[0] = "ndims"; | |
364 keywords[1] = "rows"; | |
365 | |
366 std::string kw; | |
367 octave_idx_type val = 0; | |
368 | |
369 if (extract_keyword (is, keywords, kw, val, true)) | |
370 { | |
371 if (kw == "ndims") | |
372 { | |
373 int mdims = static_cast<int> (val); | |
374 | |
375 if (mdims >= 0) | |
376 { | |
377 dim_vector dv; | |
378 dv.resize (mdims); | |
379 | |
380 for (int i = 0; i < mdims; i++) | |
381 is >> dv(i); | |
382 | |
383 if (is) | |
384 { | |
385 FloatNDArray tmp(dv); | |
386 | |
387 if (tmp.is_empty ()) | |
388 matrix = tmp; | |
389 else | |
390 { | |
391 is >> tmp; | |
392 | |
393 if (is) | |
394 matrix = tmp; | |
395 else | |
396 { | |
397 error ("load: failed to load matrix constant"); | |
398 success = false; | |
399 } | |
400 } | |
401 } | |
402 else | |
403 { | |
404 error ("load: failed to read dimensions"); | |
405 success = false; | |
406 } | |
407 } | |
408 else | |
409 { | |
410 error ("load: failed to extract number of dimensions"); | |
411 success = false; | |
412 } | |
413 } | |
414 else if (kw == "rows") | |
415 { | |
416 octave_idx_type nr = val; | |
417 octave_idx_type nc = 0; | |
418 | |
419 if (nr >= 0 && extract_keyword (is, "columns", nc) && nc >= 0) | |
420 { | |
421 if (nr > 0 && nc > 0) | |
422 { | |
423 FloatMatrix tmp (nr, nc); | |
424 is >> tmp; | |
425 if (is) | |
426 matrix = tmp; | |
427 else | |
428 { | |
429 error ("load: failed to load matrix constant"); | |
430 success = false; | |
431 } | |
432 } | |
433 else if (nr == 0 || nc == 0) | |
434 matrix = FloatMatrix (nr, nc); | |
435 else | |
436 panic_impossible (); | |
437 } | |
438 else | |
439 { | |
440 error ("load: failed to extract number of rows and columns"); | |
441 success = false; | |
442 } | |
443 } | |
444 else | |
445 panic_impossible (); | |
446 } | |
447 else | |
448 { | |
449 error ("load: failed to extract number of rows and columns"); | |
450 success = false; | |
451 } | |
452 | |
453 return success; | |
454 } | |
455 | |
456 bool | |
457 octave_float_matrix::save_binary (std::ostream& os, bool&) | |
458 { | |
459 | |
460 dim_vector d = dims (); | |
461 if (d.length() < 1) | |
462 return false; | |
463 | |
464 // Use negative value for ndims to differentiate with old format!! | |
465 int32_t tmp = - d.length(); | |
466 os.write (reinterpret_cast<char *> (&tmp), 4); | |
467 for (int i = 0; i < d.length (); i++) | |
468 { | |
469 tmp = d(i); | |
470 os.write (reinterpret_cast<char *> (&tmp), 4); | |
471 } | |
472 | |
473 FloatNDArray m = float_array_value (); | |
474 save_type st = LS_FLOAT; | |
475 if (d.numel () > 8192) // FIXME -- make this configurable. | |
476 { | |
477 float max_val, min_val; | |
478 if (m.all_integers (max_val, min_val)) | |
479 st = get_save_type (max_val, min_val); | |
480 } | |
481 | |
482 const float *mtmp = m.data (); | |
483 write_floats (os, mtmp, st, d.numel ()); | |
484 | |
485 return true; | |
486 } | |
487 | |
488 bool | |
489 octave_float_matrix::load_binary (std::istream& is, bool swap, | |
490 oct_mach_info::float_format fmt) | |
491 { | |
492 char tmp; | |
493 int32_t mdims; | |
494 if (! is.read (reinterpret_cast<char *> (&mdims), 4)) | |
495 return false; | |
496 if (swap) | |
497 swap_bytes<4> (&mdims); | |
498 if (mdims < 0) | |
499 { | |
500 mdims = - mdims; | |
501 int32_t di; | |
502 dim_vector dv; | |
503 dv.resize (mdims); | |
504 | |
505 for (int i = 0; i < mdims; i++) | |
506 { | |
507 if (! is.read (reinterpret_cast<char *> (&di), 4)) | |
508 return false; | |
509 if (swap) | |
510 swap_bytes<4> (&di); | |
511 dv(i) = di; | |
512 } | |
513 | |
514 // Convert an array with a single dimension to be a row vector. | |
515 // Octave should never write files like this, other software | |
516 // might. | |
517 | |
518 if (mdims == 1) | |
519 { | |
520 mdims = 2; | |
521 dv.resize (mdims); | |
522 dv(1) = dv(0); | |
523 dv(0) = 1; | |
524 } | |
525 | |
526 if (! is.read (reinterpret_cast<char *> (&tmp), 1)) | |
527 return false; | |
528 | |
529 FloatNDArray m(dv); | |
530 float *re = m.fortran_vec (); | |
531 read_floats (is, re, static_cast<save_type> (tmp), dv.numel (), swap, fmt); | |
532 if (error_state || ! is) | |
533 return false; | |
534 matrix = m; | |
535 } | |
536 else | |
537 { | |
538 int32_t nr, nc; | |
539 nr = mdims; | |
540 if (! is.read (reinterpret_cast<char *> (&nc), 4)) | |
541 return false; | |
542 if (swap) | |
543 swap_bytes<4> (&nc); | |
544 if (! is.read (reinterpret_cast<char *> (&tmp), 1)) | |
545 return false; | |
546 FloatMatrix m (nr, nc); | |
547 float *re = m.fortran_vec (); | |
548 octave_idx_type len = nr * nc; | |
549 read_floats (is, re, static_cast<save_type> (tmp), len, swap, fmt); | |
550 if (error_state || ! is) | |
551 return false; | |
552 matrix = m; | |
553 } | |
554 return true; | |
555 } | |
556 | |
557 #if defined (HAVE_HDF5) | |
558 | |
559 bool | |
560 octave_float_matrix::save_hdf5 (hid_t loc_id, const char *name, bool) | |
561 { | |
562 dim_vector dv = dims (); | |
563 int empty = save_hdf5_empty (loc_id, name, dv); | |
564 if (empty) | |
565 return (empty > 0); | |
566 | |
567 int rank = dv.length (); | |
568 hid_t space_hid = -1, data_hid = -1; | |
569 bool retval = true; | |
570 FloatNDArray m = array_value (); | |
571 | |
572 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank); | |
573 | |
574 // Octave uses column-major, while HDF5 uses row-major ordering | |
575 for (int i = 0; i < rank; i++) | |
576 hdims[i] = dv (rank-i-1); | |
577 | |
578 space_hid = H5Screate_simple (rank, hdims, 0); | |
579 | |
580 if (space_hid < 0) return false; | |
581 | |
582 hid_t save_type_hid = H5T_NATIVE_FLOAT; | |
583 | |
584 #if HAVE_HDF5_INT2FLOAT_CONVERSIONS | |
585 // hdf5 currently doesn't support float/integer conversions | |
586 else | |
587 { | |
588 float max_val, min_val; | |
589 | |
590 if (m.all_integers (max_val, min_val)) | |
591 save_type_hid | |
592 = save_type_to_hdf5 (get_save_type (max_val, min_val)); | |
593 } | |
594 #endif /* HAVE_HDF5_INT2FLOAT_CONVERSIONS */ | |
595 | |
596 data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid, | |
597 H5P_DEFAULT); | |
598 if (data_hid < 0) | |
599 { | |
600 H5Sclose (space_hid); | |
601 return false; | |
602 } | |
603 | |
604 float *mtmp = m.fortran_vec (); | |
605 retval = H5Dwrite (data_hid, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, | |
606 H5P_DEFAULT, mtmp) >= 0; | |
607 | |
608 H5Dclose (data_hid); | |
609 H5Sclose (space_hid); | |
610 | |
611 return retval; | |
612 } | |
613 | |
614 bool | |
615 octave_float_matrix::load_hdf5 (hid_t loc_id, const char *name, | |
616 bool /* have_h5giterate_bug */) | |
617 { | |
618 bool retval = false; | |
619 | |
620 dim_vector dv; | |
621 int empty = load_hdf5_empty (loc_id, name, dv); | |
622 if (empty > 0) | |
623 matrix.resize(dv); | |
624 if (empty) | |
625 return (empty > 0); | |
626 | |
627 hid_t data_hid = H5Dopen (loc_id, name); | |
628 hid_t space_id = H5Dget_space (data_hid); | |
629 | |
630 hsize_t rank = H5Sget_simple_extent_ndims (space_id); | |
631 | |
632 if (rank < 1) | |
633 { | |
634 H5Sclose (space_id); | |
635 H5Dclose (data_hid); | |
636 return false; | |
637 } | |
638 | |
639 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank); | |
640 OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank); | |
641 | |
642 H5Sget_simple_extent_dims (space_id, hdims, maxdims); | |
643 | |
644 // Octave uses column-major, while HDF5 uses row-major ordering | |
645 if (rank == 1) | |
646 { | |
647 dv.resize (2); | |
648 dv(0) = 1; | |
649 dv(1) = hdims[0]; | |
650 } | |
651 else | |
652 { | |
653 dv.resize (rank); | |
654 for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--) | |
655 dv(j) = hdims[i]; | |
656 } | |
657 | |
658 FloatNDArray m (dv); | |
659 float *re = m.fortran_vec (); | |
660 if (H5Dread (data_hid, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, | |
661 H5P_DEFAULT, re) >= 0) | |
662 { | |
663 retval = true; | |
664 matrix = m; | |
665 } | |
666 | |
667 H5Sclose (space_id); | |
668 H5Dclose (data_hid); | |
669 | |
670 return retval; | |
671 } | |
672 | |
673 #endif | |
674 | |
675 void | |
676 octave_float_matrix::print_raw (std::ostream& os, | |
677 bool pr_as_read_syntax) const | |
678 { | |
679 octave_print_internal (os, matrix, pr_as_read_syntax, | |
680 current_print_indent_level ()); | |
681 } | |
682 | |
683 mxArray * | |
684 octave_float_matrix::as_mxArray (void) const | |
685 { | |
686 mxArray *retval = new mxArray (mxSINGLE_CLASS, dims (), mxREAL); | |
687 | |
688 float *pr = static_cast<float *> (retval->get_data ()); | |
689 | |
690 mwSize nel = numel (); | |
691 | |
692 const float *p = matrix.data (); | |
693 | |
694 for (mwIndex i = 0; i < nel; i++) | |
695 pr[i] = p[i]; | |
696 | |
697 return retval; | |
698 } | |
699 | |
700 static bool | |
701 any_element_less_than (const FloatNDArray& a, float val) | |
702 { | |
703 octave_idx_type len = a.length (); | |
704 const float *m = a.fortran_vec (); | |
705 | |
706 for (octave_idx_type i = 0; i < len; i++) | |
707 { | |
708 OCTAVE_QUIT; | |
709 | |
710 if (m[i] < val) | |
711 return true; | |
712 } | |
713 | |
714 return false; | |
715 } | |
716 | |
717 static bool | |
718 any_element_greater_than (const FloatNDArray& a, float val) | |
719 { | |
720 octave_idx_type len = a.length (); | |
721 const float *m = a.fortran_vec (); | |
722 | |
723 for (octave_idx_type i = 0; i < len; i++) | |
724 { | |
725 OCTAVE_QUIT; | |
726 | |
727 if (m[i] > val) | |
728 return true; | |
729 } | |
730 | |
731 return false; | |
732 } | |
733 | |
734 #define ARRAY_MAPPER(MAP, AMAP, FCN) \ | |
735 octave_value \ | |
736 octave_float_matrix::MAP (void) const \ | |
737 { \ | |
738 static AMAP dmap = FCN; \ | |
739 return matrix.map (dmap); \ | |
740 } | |
741 | |
742 #define CD_ARRAY_MAPPER(MAP, RFCN, CFCN, L1, L2) \ | |
743 octave_value \ | |
744 octave_float_matrix::MAP (void) const \ | |
745 { \ | |
746 static FloatNDArray::dmapper dmap = RFCN; \ | |
747 static FloatNDArray::cmapper cmap = CFCN; \ | |
748 \ | |
749 return (any_element_less_than (matrix, L1) \ | |
750 ? octave_value (matrix.map (cmap)) \ | |
751 : (any_element_greater_than (matrix, L2) \ | |
752 ? octave_value (matrix.map (cmap)) \ | |
753 : octave_value (matrix.map (dmap)))); \ | |
754 } | |
755 | |
756 static float | |
757 xconj (float x) | |
758 { | |
759 return x; | |
760 } | |
761 | |
762 ARRAY_MAPPER (erf, FloatNDArray::dmapper, ::erff) | |
763 ARRAY_MAPPER (erfc, FloatNDArray::dmapper, ::erfcf) | |
764 ARRAY_MAPPER (gamma, FloatNDArray::dmapper, xgamma) | |
765 CD_ARRAY_MAPPER (lgamma, xlgamma, xlgamma, 0.0, octave_Inf) | |
766 ARRAY_MAPPER (abs, FloatNDArray::dmapper, ::fabsf) | |
767 ARRAY_MAPPER (acos, FloatNDArray::dmapper, ::acosf) | |
768 CD_ARRAY_MAPPER (acosh, ::acoshf, ::acosh, 1.0, octave_Inf) | |
769 ARRAY_MAPPER (angle, FloatNDArray::dmapper, ::arg) | |
770 ARRAY_MAPPER (arg, FloatNDArray::dmapper, ::arg) | |
771 CD_ARRAY_MAPPER (asin, ::asinf, ::asin, -1.0, 1.0) | |
772 ARRAY_MAPPER (asinh, FloatNDArray::dmapper,::asinhf) | |
773 ARRAY_MAPPER (atan, FloatNDArray::dmapper, ::atanf) | |
774 CD_ARRAY_MAPPER (atanh, ::atanhf, ::atanh, -1.0, 1.0) | |
775 ARRAY_MAPPER (ceil, FloatNDArray::dmapper, ::ceilf) | |
776 ARRAY_MAPPER (conj, FloatNDArray::dmapper, xconj) | |
777 ARRAY_MAPPER (cos, FloatNDArray::dmapper, ::cosf) | |
778 ARRAY_MAPPER (cosh, FloatNDArray::dmapper, ::coshf) | |
779 ARRAY_MAPPER (exp, FloatNDArray::dmapper, ::expf) | |
780 ARRAY_MAPPER (expm1, FloatNDArray::dmapper, ::expm1f) | |
781 ARRAY_MAPPER (fix, FloatNDArray::dmapper, ::fix) | |
782 ARRAY_MAPPER (floor, FloatNDArray::dmapper, ::floorf) | |
783 ARRAY_MAPPER (imag, FloatNDArray::dmapper, ::imag) | |
784 CD_ARRAY_MAPPER (log, ::logf, std::log, 0.0, octave_Inf) | |
785 CD_ARRAY_MAPPER (log2, xlog2, xlog2, 0.0, octave_Inf) | |
786 CD_ARRAY_MAPPER (log10, ::log10f, std::log10, 0.0, octave_Inf) | |
787 CD_ARRAY_MAPPER (log1p, ::log1pf, ::log1pf, -1.0, octave_Inf) | |
788 ARRAY_MAPPER (real, FloatNDArray::dmapper, ::real) | |
789 ARRAY_MAPPER (round, FloatNDArray::dmapper, xround) | |
790 ARRAY_MAPPER (roundb, FloatNDArray::dmapper, xroundb) | |
791 ARRAY_MAPPER (signum, FloatNDArray::dmapper, ::signum) | |
792 ARRAY_MAPPER (sin, FloatNDArray::dmapper, ::sinf) | |
793 ARRAY_MAPPER (sinh, FloatNDArray::dmapper, ::sinhf) | |
794 CD_ARRAY_MAPPER (sqrt, ::sqrtf, std::sqrt, 0.0, octave_Inf) | |
795 ARRAY_MAPPER (tan, FloatNDArray::dmapper, ::tanf) | |
796 ARRAY_MAPPER (tanh, FloatNDArray::dmapper, ::tanhf) | |
797 ARRAY_MAPPER (finite, FloatNDArray::bmapper, xfinite) | |
798 ARRAY_MAPPER (isinf, FloatNDArray::bmapper, xisinf) | |
799 ARRAY_MAPPER (isna, FloatNDArray::bmapper, octave_is_NA) | |
800 ARRAY_MAPPER (isnan, FloatNDArray::bmapper, xisnan) | |
801 | |
802 DEFUN (single, args, , | |
803 "-*- texinfo -*-\n\ | |
804 @deftypefn {Built-in Function} {} double (@var{x})\n\ | |
805 Convert @var{x} to single precision type.\n\ | |
806 @end deftypefn") | |
807 { | |
808 // The OCTAVE_TYPE_CONV_BODY3 macro declares retval, so they go | |
809 // inside their own scopes, and we don't declare retval here to | |
810 // avoid a shadowed declaration warning. | |
811 | |
812 if (args.length () == 1) | |
813 { | |
814 if (args(0).is_sparse_type ()) | |
815 { | |
816 error ("single: sparse type do not support single precision"); | |
817 } | |
818 else if (args(0).is_complex_type ()) | |
819 { | |
820 OCTAVE_TYPE_CONV_BODY3 (single, octave_float_complex_matrix, octave_float_complex); | |
821 } | |
822 else | |
823 { | |
824 OCTAVE_TYPE_CONV_BODY3 (single, octave_float_matrix, octave_float_scalar); | |
825 } | |
826 } | |
827 else | |
828 print_usage (); | |
829 | |
830 return octave_value (); | |
831 } | |
832 | |
833 /* | |
834 ;;; Local Variables: *** | |
835 ;;; mode: C++ *** | |
836 ;;; End: *** | |
837 */ |