00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include <iostream>
00029 #include <vector>
00030
00031 #include "data-conv.h"
00032 #include "lo-ieee.h"
00033 #include "lo-specfun.h"
00034 #include "lo-mappers.h"
00035 #include "mx-base.h"
00036 #include "mach-info.h"
00037 #include "oct-locbuf.h"
00038
00039 #include "gripes.h"
00040 #include "oct-obj.h"
00041 #include "oct-stream.h"
00042 #include "ops.h"
00043 #include "ov-base.h"
00044 #include "ov-base-mat.h"
00045 #include "ov-base-mat.cc"
00046 #include "ov-complex.h"
00047 #include "ov-flt-complex.h"
00048 #include "ov-cx-mat.h"
00049 #include "ov-flt-cx-mat.h"
00050 #include "ov-re-mat.h"
00051 #include "ov-flt-re-mat.h"
00052 #include "ov-scalar.h"
00053 #include "ov-float.h"
00054 #include "pr-output.h"
00055 #include "ops.h"
00056
00057 #include "byte-swap.h"
00058 #include "ls-oct-ascii.h"
00059 #include "ls-hdf5.h"
00060 #include "ls-utils.h"
00061
00062 template class octave_base_matrix<FloatComplexNDArray>;
00063
00064 DEFINE_OCTAVE_ALLOCATOR (octave_float_complex_matrix);
00065
00066 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_complex_matrix,
00067 "float complex matrix", "single");
00068
00069 octave_base_value *
00070 octave_float_complex_matrix::try_narrowing_conversion (void)
00071 {
00072 octave_base_value *retval = 0;
00073
00074 if (matrix.numel () == 1)
00075 {
00076 FloatComplex c = matrix (0);
00077
00078 if (std::imag (c) == 0.0)
00079 retval = new octave_float_scalar (std::real (c));
00080 else
00081 retval = new octave_float_complex (c);
00082 }
00083 else if (matrix.all_elements_are_real ())
00084 retval = new octave_float_matrix (::real (matrix));
00085
00086 return retval;
00087 }
00088
00089 double
00090 octave_float_complex_matrix::double_value (bool force_conversion) const
00091 {
00092 double retval = lo_ieee_nan_value ();
00093
00094 if (! force_conversion)
00095 gripe_implicit_conversion ("Octave:imag-to-real",
00096 "complex matrix", "real scalar");
00097
00098 if (rows () > 0 && columns () > 0)
00099 {
00100 gripe_implicit_conversion ("Octave:array-as-scalar",
00101 "complex matrix", "real scalar");
00102
00103 retval = std::real (matrix (0, 0));
00104 }
00105 else
00106 gripe_invalid_conversion ("complex matrix", "real scalar");
00107
00108 return retval;
00109 }
00110
00111 float
00112 octave_float_complex_matrix::float_value (bool force_conversion) const
00113 {
00114 float retval = lo_ieee_float_nan_value ();
00115
00116 if (! force_conversion)
00117 gripe_implicit_conversion ("Octave:imag-to-real",
00118 "complex matrix", "real scalar");
00119
00120 if (rows () > 0 && columns () > 0)
00121 {
00122 gripe_implicit_conversion ("Octave:array-as-scalar",
00123 "complex matrix", "real scalar");
00124
00125 retval = std::real (matrix (0, 0));
00126 }
00127 else
00128 gripe_invalid_conversion ("complex matrix", "real scalar");
00129
00130 return retval;
00131 }
00132
00133 Matrix
00134 octave_float_complex_matrix::matrix_value (bool force_conversion) const
00135 {
00136 Matrix retval;
00137
00138 if (! force_conversion)
00139 gripe_implicit_conversion ("Octave:imag-to-real",
00140 "complex matrix", "real matrix");
00141
00142 retval = ::real (matrix.matrix_value ());
00143
00144 return retval;
00145 }
00146
00147 FloatMatrix
00148 octave_float_complex_matrix::float_matrix_value (bool force_conversion) const
00149 {
00150 FloatMatrix retval;
00151
00152 if (! force_conversion)
00153 gripe_implicit_conversion ("Octave:imag-to-real",
00154 "complex matrix", "real matrix");
00155
00156 retval = ::real (matrix.matrix_value ());
00157
00158 return retval;
00159 }
00160
00161 Complex
00162 octave_float_complex_matrix::complex_value (bool) const
00163 {
00164 double tmp = lo_ieee_nan_value ();
00165
00166 Complex retval (tmp, tmp);
00167
00168 if (rows () > 0 && columns () > 0)
00169 {
00170 gripe_implicit_conversion ("Octave:array-as-scalar",
00171 "complex matrix", "complex scalar");
00172
00173 retval = matrix (0, 0);
00174 }
00175 else
00176 gripe_invalid_conversion ("complex matrix", "complex scalar");
00177
00178 return retval;
00179 }
00180
00181 FloatComplex
00182 octave_float_complex_matrix::float_complex_value (bool) const
00183 {
00184 float tmp = lo_ieee_float_nan_value ();
00185
00186 FloatComplex retval (tmp, tmp);
00187
00188 if (rows () > 0 && columns () > 0)
00189 {
00190 gripe_implicit_conversion ("Octave:array-as-scalar",
00191 "complex matrix", "complex scalar");
00192
00193 retval = matrix (0, 0);
00194 }
00195 else
00196 gripe_invalid_conversion ("complex matrix", "complex scalar");
00197
00198 return retval;
00199 }
00200
00201 ComplexMatrix
00202 octave_float_complex_matrix::complex_matrix_value (bool) const
00203 {
00204 return matrix.matrix_value ();
00205 }
00206
00207 FloatComplexMatrix
00208 octave_float_complex_matrix::float_complex_matrix_value (bool) const
00209 {
00210 return FloatComplexMatrix (matrix.matrix_value ());
00211 }
00212
00213 boolNDArray
00214 octave_float_complex_matrix::bool_array_value (bool warn) const
00215 {
00216 if (matrix.any_element_is_nan ())
00217 gripe_nan_to_logical_conversion ();
00218 else if (warn && (! matrix.all_elements_are_real ()
00219 || real (matrix).any_element_not_one_or_zero ()))
00220 gripe_logical_conversion ();
00221
00222 return mx_el_ne (matrix, FloatComplex (0.0));
00223 }
00224
00225 charNDArray
00226 octave_float_complex_matrix::char_array_value (bool frc_str_conv) const
00227 {
00228 charNDArray retval;
00229
00230 if (! frc_str_conv)
00231 gripe_implicit_conversion ("Octave:num-to-str",
00232 "complex matrix", "string");
00233 else
00234 {
00235 retval = charNDArray (dims ());
00236 octave_idx_type nel = numel ();
00237
00238 for (octave_idx_type i = 0; i < nel; i++)
00239 retval.elem (i) = static_cast<char>(std::real (matrix.elem (i)));
00240 }
00241
00242 return retval;
00243 }
00244
00245 FloatComplexNDArray
00246 octave_float_complex_matrix::float_complex_array_value (bool) const
00247 {
00248 return FloatComplexNDArray (matrix);
00249 }
00250
00251 SparseMatrix
00252 octave_float_complex_matrix::sparse_matrix_value (bool force_conversion) const
00253 {
00254 SparseMatrix retval;
00255
00256 if (! force_conversion)
00257 gripe_implicit_conversion ("Octave:imag-to-real",
00258 "complex matrix", "real matrix");
00259
00260 retval = SparseMatrix (::real (complex_matrix_value ()));
00261
00262 return retval;
00263 }
00264
00265 SparseComplexMatrix
00266 octave_float_complex_matrix::sparse_complex_matrix_value (bool) const
00267 {
00268 return SparseComplexMatrix (complex_matrix_value ());
00269 }
00270
00271 octave_value
00272 octave_float_complex_matrix::diag (octave_idx_type k) const
00273 {
00274 octave_value retval;
00275 if (k == 0 && matrix.ndims () == 2
00276 && (matrix.rows () == 1 || matrix.columns () == 1))
00277 retval = FloatComplexDiagMatrix (DiagArray2<FloatComplex> (matrix));
00278 else
00279 retval = octave_base_matrix<FloatComplexNDArray>::diag (k);
00280
00281 return retval;
00282 }
00283
00284 bool
00285 octave_float_complex_matrix::save_ascii (std::ostream& os)
00286 {
00287 dim_vector d = dims ();
00288 if (d.length () > 2)
00289 {
00290 FloatComplexNDArray tmp = complex_array_value ();
00291
00292 os << "# ndims: " << d.length () << "\n";
00293
00294 for (int i = 0; i < d.length (); i++)
00295 os << " " << d (i);
00296
00297 os << "\n" << tmp;
00298 }
00299 else
00300 {
00301
00302
00303 os << "# rows: " << rows () << "\n"
00304 << "# columns: " << columns () << "\n";
00305
00306 os << complex_matrix_value ();
00307 }
00308
00309 return true;
00310 }
00311
00312 bool
00313 octave_float_complex_matrix::load_ascii (std::istream& is)
00314 {
00315 bool success = true;
00316
00317 string_vector keywords(2);
00318
00319 keywords[0] = "ndims";
00320 keywords[1] = "rows";
00321
00322 std::string kw;
00323 octave_idx_type val = 0;
00324
00325 if (extract_keyword (is, keywords, kw, val, true))
00326 {
00327 if (kw == "ndims")
00328 {
00329 int mdims = static_cast<int> (val);
00330
00331 if (mdims >= 0)
00332 {
00333 dim_vector dv;
00334 dv.resize (mdims);
00335
00336 for (int i = 0; i < mdims; i++)
00337 is >> dv(i);
00338
00339 if (is)
00340 {
00341 FloatComplexNDArray tmp(dv);
00342
00343 is >> tmp;
00344
00345 if (is)
00346 matrix = tmp;
00347 else
00348 {
00349 error ("load: failed to load matrix constant");
00350 success = false;
00351 }
00352 }
00353 else
00354 {
00355 error ("load: failed to read dimensions");
00356 success = false;
00357 }
00358 }
00359 else
00360 {
00361 error ("load: failed to extract number of dimensions");
00362 success = false;
00363 }
00364 }
00365 else if (kw == "rows")
00366 {
00367 octave_idx_type nr = val;
00368 octave_idx_type nc = 0;
00369
00370 if (nr >= 0 && extract_keyword (is, "columns", nc) && nc >= 0)
00371 {
00372 if (nr > 0 && nc > 0)
00373 {
00374 FloatComplexMatrix tmp (nr, nc);
00375 is >> tmp;
00376 if (is)
00377 matrix = tmp;
00378 else
00379 {
00380 error ("load: failed to load matrix constant");
00381 success = false;
00382 }
00383 }
00384 else if (nr == 0 || nc == 0)
00385 matrix = FloatComplexMatrix (nr, nc);
00386 else
00387 panic_impossible ();
00388 }
00389 else
00390 {
00391 error ("load: failed to extract number of rows and columns");
00392 success = false;
00393 }
00394 }
00395 else
00396 panic_impossible ();
00397 }
00398 else
00399 {
00400 error ("load: failed to extract number of rows and columns");
00401 success = false;
00402 }
00403
00404 return success;
00405 }
00406
00407 bool
00408 octave_float_complex_matrix::save_binary (std::ostream& os, bool&)
00409 {
00410 dim_vector d = dims ();
00411 if (d.length() < 1)
00412 return false;
00413
00414
00415 int32_t tmp = - d.length();
00416 os.write (reinterpret_cast<char *> (&tmp), 4);
00417 for (int i = 0; i < d.length (); i++)
00418 {
00419 tmp = d(i);
00420 os.write (reinterpret_cast<char *> (&tmp), 4);
00421 }
00422
00423 FloatComplexNDArray m = complex_array_value ();
00424 save_type st = LS_FLOAT;
00425 if (d.numel () > 4096)
00426 {
00427 float max_val, min_val;
00428 if (m.all_integers (max_val, min_val))
00429 st = get_save_type (max_val, min_val);
00430 }
00431
00432 const FloatComplex *mtmp = m.data ();
00433 write_floats (os, reinterpret_cast<const float *> (mtmp), st, 2 * d.numel ());
00434
00435 return true;
00436 }
00437
00438 bool
00439 octave_float_complex_matrix::load_binary (std::istream& is, bool swap,
00440 oct_mach_info::float_format fmt)
00441 {
00442 char tmp;
00443 int32_t mdims;
00444 if (! is.read (reinterpret_cast<char *> (&mdims), 4))
00445 return false;
00446 if (swap)
00447 swap_bytes<4> (&mdims);
00448 if (mdims < 0)
00449 {
00450 mdims = - mdims;
00451 int32_t di;
00452 dim_vector dv;
00453 dv.resize (mdims);
00454
00455 for (int i = 0; i < mdims; i++)
00456 {
00457 if (! is.read (reinterpret_cast<char *> (&di), 4))
00458 return false;
00459 if (swap)
00460 swap_bytes<4> (&di);
00461 dv(i) = di;
00462 }
00463
00464
00465
00466
00467
00468 if (mdims == 1)
00469 {
00470 mdims = 2;
00471 dv.resize (mdims);
00472 dv(1) = dv(0);
00473 dv(0) = 1;
00474 }
00475
00476 if (! is.read (reinterpret_cast<char *> (&tmp), 1))
00477 return false;
00478
00479 FloatComplexNDArray m(dv);
00480 FloatComplex *im = m.fortran_vec ();
00481 read_floats (is, reinterpret_cast<float *> (im),
00482 static_cast<save_type> (tmp), 2 * dv.numel (), swap, fmt);
00483 if (error_state || ! is)
00484 return false;
00485 matrix = m;
00486 }
00487 else
00488 {
00489 int32_t nr, nc;
00490 nr = mdims;
00491 if (! is.read (reinterpret_cast<char *> (&nc), 4))
00492 return false;
00493 if (swap)
00494 swap_bytes<4> (&nc);
00495 if (! is.read (reinterpret_cast<char *> (&tmp), 1))
00496 return false;
00497 FloatComplexMatrix m (nr, nc);
00498 FloatComplex *im = m.fortran_vec ();
00499 octave_idx_type len = nr * nc;
00500 read_floats (is, reinterpret_cast<float *> (im),
00501 static_cast<save_type> (tmp), 2*len, swap, fmt);
00502 if (error_state || ! is)
00503 return false;
00504 matrix = m;
00505 }
00506 return true;
00507 }
00508
00509 #if defined (HAVE_HDF5)
00510
00511 bool
00512 octave_float_complex_matrix::save_hdf5 (hid_t loc_id, const char *name, bool)
00513 {
00514 dim_vector dv = dims ();
00515 int empty = save_hdf5_empty (loc_id, name, dv);
00516 if (empty)
00517 return (empty > 0);
00518
00519 int rank = dv.length ();
00520 hid_t space_hid = -1, data_hid = -1, type_hid = -1;
00521 bool retval = true;
00522 FloatComplexNDArray m = complex_array_value ();
00523
00524 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
00525
00526
00527 for (int i = 0; i < rank; i++)
00528 hdims[i] = dv (rank-i-1);
00529
00530 space_hid = H5Screate_simple (rank, hdims, 0);
00531 if (space_hid < 0) return false;
00532
00533 hid_t save_type_hid = H5T_NATIVE_FLOAT;
00534
00535 #if HAVE_HDF5_INT2FLOAT_CONVERSIONS
00536
00537 else
00538 {
00539 float max_val, min_val;
00540
00541 if (m.all_integers (max_val, min_val))
00542 save_type_hid
00543 = save_type_to_hdf5 (get_save_type (max_val, min_val));
00544 }
00545 #endif
00546
00547 type_hid = hdf5_make_complex_type (save_type_hid);
00548 if (type_hid < 0)
00549 {
00550 H5Sclose (space_hid);
00551 return false;
00552 }
00553 #if HAVE_HDF5_18
00554 data_hid = H5Dcreate (loc_id, name, type_hid, space_hid,
00555 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00556 #else
00557 data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, H5P_DEFAULT);
00558 #endif
00559 if (data_hid < 0)
00560 {
00561 H5Sclose (space_hid);
00562 H5Tclose (type_hid);
00563 return false;
00564 }
00565
00566 hid_t complex_type_hid = hdf5_make_complex_type (H5T_NATIVE_FLOAT);
00567 if (complex_type_hid < 0) retval = false;
00568
00569 if (retval)
00570 {
00571 FloatComplex *mtmp = m.fortran_vec ();
00572 if (H5Dwrite (data_hid, complex_type_hid, H5S_ALL, H5S_ALL, H5P_DEFAULT,
00573 mtmp) < 0)
00574 {
00575 H5Tclose (complex_type_hid);
00576 retval = false;
00577 }
00578 }
00579
00580 H5Tclose (complex_type_hid);
00581 H5Dclose (data_hid);
00582 H5Tclose (type_hid);
00583 H5Sclose (space_hid);
00584
00585 return retval;
00586 }
00587
00588 bool
00589 octave_float_complex_matrix::load_hdf5 (hid_t loc_id, const char *name)
00590 {
00591 bool retval = false;
00592
00593 dim_vector dv;
00594 int empty = load_hdf5_empty (loc_id, name, dv);
00595 if (empty > 0)
00596 matrix.resize(dv);
00597 if (empty)
00598 return (empty > 0);
00599
00600 #if HAVE_HDF5_18
00601 hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
00602 #else
00603 hid_t data_hid = H5Dopen (loc_id, name);
00604 #endif
00605 hid_t type_hid = H5Dget_type (data_hid);
00606
00607 hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_FLOAT);
00608
00609 if (! hdf5_types_compatible (type_hid, complex_type))
00610 {
00611 H5Tclose (complex_type);
00612 H5Dclose (data_hid);
00613 return false;
00614 }
00615
00616 hid_t space_id = H5Dget_space (data_hid);
00617
00618 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00619
00620 if (rank < 1)
00621 {
00622 H5Tclose (complex_type);
00623 H5Sclose (space_id);
00624 H5Dclose (data_hid);
00625 return false;
00626 }
00627
00628 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
00629 OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
00630
00631 H5Sget_simple_extent_dims (space_id, hdims, maxdims);
00632
00633
00634 if (rank == 1)
00635 {
00636 dv.resize (2);
00637 dv(0) = 1;
00638 dv(1) = hdims[0];
00639 }
00640 else
00641 {
00642 dv.resize (rank);
00643 for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)
00644 dv(j) = hdims[i];
00645 }
00646
00647 FloatComplexNDArray m (dv);
00648 FloatComplex *reim = m.fortran_vec ();
00649 if (H5Dread (data_hid, complex_type, H5S_ALL, H5S_ALL, H5P_DEFAULT,
00650 reim) >= 0)
00651 {
00652 retval = true;
00653 matrix = m;
00654 }
00655
00656 H5Tclose (complex_type);
00657 H5Sclose (space_id);
00658 H5Dclose (data_hid);
00659
00660 return retval;
00661 }
00662
00663 #endif
00664
00665 void
00666 octave_float_complex_matrix::print_raw (std::ostream& os,
00667 bool pr_as_read_syntax) const
00668 {
00669 octave_print_internal (os, matrix, pr_as_read_syntax,
00670 current_print_indent_level ());
00671 }
00672
00673 mxArray *
00674 octave_float_complex_matrix::as_mxArray (void) const
00675 {
00676 mxArray *retval = new mxArray (mxSINGLE_CLASS, dims (), mxCOMPLEX);
00677
00678 float *pr = static_cast<float *> (retval->get_data ());
00679 float *pi = static_cast<float *> (retval->get_imag_data ());
00680
00681 mwSize nel = numel ();
00682
00683 const FloatComplex *p = matrix.data ();
00684
00685 for (mwIndex i = 0; i < nel; i++)
00686 {
00687 pr[i] = std::real (p[i]);
00688 pi[i] = std::imag (p[i]);
00689 }
00690
00691 return retval;
00692 }
00693
00694 octave_value
00695 octave_float_complex_matrix::map (unary_mapper_t umap) const
00696 {
00697 switch (umap)
00698 {
00699
00700 case umap_real:
00701 return ::real (matrix);
00702 case umap_imag:
00703 return ::imag (matrix);
00704 case umap_conj:
00705 return ::conj (matrix);
00706
00707 #define ARRAY_METHOD_MAPPER(UMAP, FCN) \
00708 case umap_ ## UMAP: \
00709 return octave_value (matrix.FCN ())
00710
00711 ARRAY_METHOD_MAPPER (abs, abs);
00712 ARRAY_METHOD_MAPPER (isnan, isnan);
00713 ARRAY_METHOD_MAPPER (isinf, isinf);
00714 ARRAY_METHOD_MAPPER (finite, isfinite);
00715
00716 #define ARRAY_MAPPER(UMAP, TYPE, FCN) \
00717 case umap_ ## UMAP: \
00718 return octave_value (matrix.map<TYPE> (FCN))
00719
00720 ARRAY_MAPPER (acos, FloatComplex, ::acos);
00721 ARRAY_MAPPER (acosh, FloatComplex, ::acosh);
00722 ARRAY_MAPPER (angle, float, std::arg);
00723 ARRAY_MAPPER (arg, float, std::arg);
00724 ARRAY_MAPPER (asin, FloatComplex, ::asin);
00725 ARRAY_MAPPER (asinh, FloatComplex, ::asinh);
00726 ARRAY_MAPPER (atan, FloatComplex, ::atan);
00727 ARRAY_MAPPER (atanh, FloatComplex, ::atanh);
00728 ARRAY_MAPPER (ceil, FloatComplex, ::ceil);
00729 ARRAY_MAPPER (cos, FloatComplex, std::cos);
00730 ARRAY_MAPPER (cosh, FloatComplex, std::cosh);
00731 ARRAY_MAPPER (exp, FloatComplex, std::exp);
00732 ARRAY_MAPPER (expm1, FloatComplex, ::expm1);
00733 ARRAY_MAPPER (fix, FloatComplex, ::fix);
00734 ARRAY_MAPPER (floor, FloatComplex, ::floor);
00735 ARRAY_MAPPER (log, FloatComplex, std::log);
00736 ARRAY_MAPPER (log2, FloatComplex, xlog2);
00737 ARRAY_MAPPER (log10, FloatComplex, std::log10);
00738 ARRAY_MAPPER (log1p, FloatComplex, ::log1p);
00739 ARRAY_MAPPER (round, FloatComplex, xround);
00740 ARRAY_MAPPER (roundb, FloatComplex, xroundb);
00741 ARRAY_MAPPER (signum, FloatComplex, ::signum);
00742 ARRAY_MAPPER (sin, FloatComplex, std::sin);
00743 ARRAY_MAPPER (sinh, FloatComplex, std::sinh);
00744 ARRAY_MAPPER (sqrt, FloatComplex, std::sqrt);
00745 ARRAY_MAPPER (tan, FloatComplex, std::tan);
00746 ARRAY_MAPPER (tanh, FloatComplex, std::tanh);
00747 ARRAY_MAPPER (isna, bool, octave_is_NA);
00748
00749 default:
00750 return octave_base_value::map (umap);
00751 }
00752 }