ov-complex.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <iostream>
00028 
00029 #include "lo-ieee.h"
00030 #include "lo-specfun.h"
00031 #include "lo-mappers.h"
00032 
00033 #include "oct-obj.h"
00034 #include "oct-stream.h"
00035 #include "ops.h"
00036 #include "ov-complex.h"
00037 #include "ov-flt-complex.h"
00038 #include "ov-base.h"
00039 #include "ov-base-scalar.h"
00040 #include "ov-base-scalar.cc"
00041 #include "ov-cx-mat.h"
00042 #include "ov-scalar.h"
00043 #include "gripes.h"
00044 #include "pr-output.h"
00045 #include "ops.h"
00046 
00047 #include "ls-oct-ascii.h"
00048 #include "ls-hdf5.h"
00049 
00050 template class octave_base_scalar<Complex>;
00051 
00052 DEFINE_OCTAVE_ALLOCATOR (octave_complex);
00053 
00054 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_complex,
00055                                      "complex scalar", "double");
00056 
00057 static octave_base_value *
00058 default_numeric_demotion_function (const octave_base_value& a)
00059 {
00060   CAST_CONV_ARG (const octave_complex&);
00061 
00062   return new octave_float_complex (v.float_complex_value ());
00063 }
00064 
00065 octave_base_value::type_conv_info
00066 octave_complex::numeric_demotion_function (void) const
00067 {
00068   return octave_base_value::type_conv_info(default_numeric_demotion_function,
00069                                            octave_float_complex::static_type_id ());
00070 }
00071 
00072 octave_base_value *
00073 octave_complex::try_narrowing_conversion (void)
00074 {
00075   octave_base_value *retval = 0;
00076 
00077   double im = std::imag (scalar);
00078 
00079   if (im == 0.0)
00080     retval = new octave_scalar (std::real (scalar));
00081 
00082   return retval;
00083 }
00084 
00085 octave_value
00086 octave_complex::do_index_op (const octave_value_list& idx, bool resize_ok)
00087 {
00088   // FIXME -- this doesn't solve the problem of
00089   //
00090   //   a = i; a([1,1], [1,1], [1,1])
00091   //
00092   // and similar constructions.  Hmm...
00093 
00094   // FIXME -- using this constructor avoids narrowing the
00095   // 1x1 matrix back to a scalar value.  Need a better solution
00096   // to this problem.
00097 
00098   octave_value tmp (new octave_complex_matrix (complex_matrix_value ()));
00099 
00100   return tmp.do_index_op (idx, resize_ok);
00101 }
00102 
00103 double
00104 octave_complex::double_value (bool force_conversion) const
00105 {
00106   double retval = lo_ieee_nan_value ();
00107 
00108   if (! force_conversion)
00109     gripe_implicit_conversion ("Octave:imag-to-real",
00110                                "complex scalar", "real scalar");
00111 
00112   retval = std::real (scalar);
00113 
00114   return retval;
00115 }
00116 
00117 float
00118 octave_complex::float_value (bool force_conversion) const
00119 {
00120   float retval = lo_ieee_float_nan_value ();
00121 
00122   if (! force_conversion)
00123     gripe_implicit_conversion ("Octave:imag-to-real",
00124                                "complex scalar", "real scalar");
00125 
00126   retval = std::real (scalar);
00127 
00128   return retval;
00129 }
00130 
00131 Matrix
00132 octave_complex::matrix_value (bool force_conversion) const
00133 {
00134   Matrix retval;
00135 
00136   if (! force_conversion)
00137     gripe_implicit_conversion ("Octave:imag-to-real",
00138                                "complex scalar", "real matrix");
00139 
00140   retval = Matrix (1, 1, std::real (scalar));
00141 
00142   return retval;
00143 }
00144 
00145 FloatMatrix
00146 octave_complex::float_matrix_value (bool force_conversion) const
00147 {
00148   FloatMatrix retval;
00149 
00150   if (! force_conversion)
00151     gripe_implicit_conversion ("Octave:imag-to-real",
00152                                "complex scalar", "real matrix");
00153 
00154   retval = FloatMatrix (1, 1, std::real (scalar));
00155 
00156   return retval;
00157 }
00158 
00159 NDArray
00160 octave_complex::array_value (bool force_conversion) const
00161 {
00162   NDArray retval;
00163 
00164   if (! force_conversion)
00165     gripe_implicit_conversion ("Octave:imag-to-real",
00166                                "complex scalar", "real matrix");
00167 
00168   retval = NDArray (dim_vector (1, 1), std::real (scalar));
00169 
00170   return retval;
00171 }
00172 
00173 FloatNDArray
00174 octave_complex::float_array_value (bool force_conversion) const
00175 {
00176   FloatNDArray retval;
00177 
00178   if (! force_conversion)
00179     gripe_implicit_conversion ("Octave:imag-to-real",
00180                                "complex scalar", "real matrix");
00181 
00182   retval = FloatNDArray (dim_vector (1, 1), std::real (scalar));
00183 
00184   return retval;
00185 }
00186 
00187 Complex
00188 octave_complex::complex_value (bool) const
00189 {
00190   return scalar;
00191 }
00192 
00193 FloatComplex
00194 octave_complex::float_complex_value (bool) const
00195 {
00196   return static_cast<FloatComplex> (scalar);
00197 }
00198 
00199 ComplexMatrix
00200 octave_complex::complex_matrix_value (bool) const
00201 {
00202   return ComplexMatrix (1, 1, scalar);
00203 }
00204 
00205 FloatComplexMatrix
00206 octave_complex::float_complex_matrix_value (bool) const
00207 {
00208   return FloatComplexMatrix (1, 1, static_cast<FloatComplex> (scalar));
00209 }
00210 
00211 ComplexNDArray
00212 octave_complex::complex_array_value (bool /* force_conversion */) const
00213 {
00214   return ComplexNDArray (dim_vector (1, 1), scalar);
00215 }
00216 
00217 FloatComplexNDArray
00218 octave_complex::float_complex_array_value (bool /* force_conversion */) const
00219 {
00220   return FloatComplexNDArray (dim_vector (1, 1), static_cast<FloatComplex> (scalar));
00221 }
00222 
00223 octave_value
00224 octave_complex::resize (const dim_vector& dv, bool fill) const
00225 {
00226   if (fill)
00227     {
00228       ComplexNDArray retval (dv, ComplexNDArray::resize_fill_value ());
00229 
00230       if (dv.numel ())
00231         retval(0) = scalar;
00232 
00233       return retval;
00234     }
00235   else
00236     {
00237       ComplexNDArray retval (dv);
00238 
00239       if (dv.numel ())
00240         retval(0) = scalar;
00241 
00242       return retval;
00243     }
00244 }
00245 
00246 bool
00247 octave_complex::save_ascii (std::ostream& os)
00248 {
00249   Complex c = complex_value ();
00250 
00251   octave_write_complex (os, c);
00252 
00253   os << "\n";
00254 
00255   return true;
00256 }
00257 
00258 bool
00259 octave_complex::load_ascii (std::istream& is)
00260 {
00261   scalar = octave_read_value<Complex> (is);
00262 
00263   if (!is)
00264     {
00265       error ("load: failed to load complex scalar constant");
00266       return false;
00267     }
00268 
00269   return true;
00270 }
00271 
00272 
00273 bool
00274 octave_complex::save_binary (std::ostream& os, bool& /* save_as_floats */)
00275 {
00276   char tmp = static_cast<char> (LS_DOUBLE);
00277   os.write (reinterpret_cast<char *> (&tmp), 1);
00278   Complex ctmp = complex_value ();
00279   os.write (reinterpret_cast<char *> (&ctmp), 16);
00280 
00281   return true;
00282 }
00283 
00284 bool
00285 octave_complex::load_binary (std::istream& is, bool swap,
00286                              oct_mach_info::float_format fmt)
00287 {
00288   char tmp;
00289   if (! is.read (reinterpret_cast<char *> (&tmp), 1))
00290     return false;
00291 
00292   Complex ctmp;
00293   read_doubles (is, reinterpret_cast<double *> (&ctmp),
00294                 static_cast<save_type> (tmp), 2, swap, fmt);
00295   if (error_state || ! is)
00296     return false;
00297 
00298   scalar = ctmp;
00299   return true;
00300 }
00301 
00302 #if defined (HAVE_HDF5)
00303 
00304 bool
00305 octave_complex::save_hdf5 (hid_t loc_id, const char *name,
00306                            bool /* save_as_floats */)
00307 {
00308   hsize_t dimens[3];
00309   hid_t space_hid = -1, type_hid = -1, data_hid = -1;
00310   bool retval = true;
00311 
00312   space_hid = H5Screate_simple (0, dimens, 0);
00313   if (space_hid < 0)
00314     return false;
00315 
00316   type_hid = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
00317   if (type_hid < 0)
00318     {
00319       H5Sclose (space_hid);
00320       return false;
00321     }
00322 #if HAVE_HDF5_18
00323   data_hid = H5Dcreate (loc_id, name, type_hid, space_hid,
00324                         H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00325 #else
00326   data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, H5P_DEFAULT);
00327 #endif
00328   if (data_hid < 0)
00329     {
00330       H5Sclose (space_hid);
00331       H5Tclose (type_hid);
00332       return false;
00333     }
00334 
00335   Complex tmp = complex_value ();
00336   retval = H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL, H5P_DEFAULT,
00337                      &tmp) >= 0;
00338 
00339   H5Dclose (data_hid);
00340   H5Tclose (type_hid);
00341   H5Sclose (space_hid);
00342 
00343   return retval;
00344 }
00345 
00346 bool
00347 octave_complex::load_hdf5 (hid_t loc_id, const char *name)
00348 {
00349   bool retval = false;
00350 #if HAVE_HDF5_18
00351   hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
00352 #else
00353   hid_t data_hid = H5Dopen (loc_id, name);
00354 #endif
00355   hid_t type_hid = H5Dget_type (data_hid);
00356 
00357   hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
00358 
00359   if (! hdf5_types_compatible (type_hid, complex_type))
00360     {
00361       H5Tclose (complex_type);
00362       H5Dclose (data_hid);
00363       return false;
00364     }
00365 
00366   hid_t space_id = H5Dget_space (data_hid);
00367   hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00368 
00369   if (rank != 0)
00370     {
00371       H5Tclose (complex_type);
00372       H5Sclose (space_id);
00373       H5Dclose (data_hid);
00374       return false;
00375     }
00376 
00377   // complex scalar:
00378   Complex ctmp;
00379   if (H5Dread (data_hid, complex_type, H5S_ALL, H5S_ALL, H5P_DEFAULT,
00380                &ctmp) >= 0)
00381     {
00382       retval = true;
00383       scalar = ctmp;
00384     }
00385 
00386   H5Tclose (complex_type);
00387   H5Sclose (space_id);
00388   H5Dclose (data_hid);
00389 
00390   return retval;
00391 }
00392 
00393 #endif
00394 
00395 mxArray *
00396 octave_complex::as_mxArray (void) const
00397 {
00398   mxArray *retval = new mxArray (mxDOUBLE_CLASS, 1, 1, mxCOMPLEX);
00399 
00400   double *pr = static_cast<double *> (retval->get_data ());
00401   double *pi = static_cast<double *> (retval->get_imag_data ());
00402 
00403   pr[0] = std::real (scalar);
00404   pi[0] = std::imag (scalar);
00405 
00406   return retval;
00407 }
00408 
00409 octave_value
00410 octave_complex::map (unary_mapper_t umap) const
00411 {
00412   switch (umap)
00413     {
00414 #define SCALAR_MAPPER(UMAP, FCN) \
00415     case umap_ ## UMAP: \
00416       return octave_value (FCN (scalar))
00417 
00418       SCALAR_MAPPER (abs, std::abs);
00419       SCALAR_MAPPER (acos, ::acos);
00420       SCALAR_MAPPER (acosh, ::acosh);
00421       SCALAR_MAPPER (angle, std::arg);
00422       SCALAR_MAPPER (arg, std::arg);
00423       SCALAR_MAPPER (asin, ::asin);
00424       SCALAR_MAPPER (asinh, ::asinh);
00425       SCALAR_MAPPER (atan, ::atan);
00426       SCALAR_MAPPER (atanh, ::atanh);
00427       SCALAR_MAPPER (ceil, ::ceil);
00428       SCALAR_MAPPER (conj, std::conj);
00429       SCALAR_MAPPER (cos, std::cos);
00430       SCALAR_MAPPER (cosh, std::cosh);
00431       SCALAR_MAPPER (exp, std::exp);
00432       SCALAR_MAPPER (expm1, ::expm1);
00433       SCALAR_MAPPER (fix, ::fix);
00434       SCALAR_MAPPER (floor, ::floor);
00435       SCALAR_MAPPER (imag, std::imag);
00436       SCALAR_MAPPER (log, std::log);
00437       SCALAR_MAPPER (log2, xlog2);
00438       SCALAR_MAPPER (log10, std::log10);
00439       SCALAR_MAPPER (log1p, ::log1p);
00440       SCALAR_MAPPER (real, std::real);
00441       SCALAR_MAPPER (round, xround);
00442       SCALAR_MAPPER (roundb, xroundb);
00443       SCALAR_MAPPER (signum, ::signum);
00444       SCALAR_MAPPER (sin, std::sin);
00445       SCALAR_MAPPER (sinh, std::sinh);
00446       SCALAR_MAPPER (sqrt, std::sqrt);
00447       SCALAR_MAPPER (tan, std::tan);
00448       SCALAR_MAPPER (tanh, std::tanh);
00449       SCALAR_MAPPER (finite, xfinite);
00450       SCALAR_MAPPER (isinf, xisinf);
00451       SCALAR_MAPPER (isna, octave_is_NA);
00452       SCALAR_MAPPER (isnan, xisnan);
00453 
00454     default:
00455       return octave_base_value::map (umap);
00456     }
00457 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines