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