GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov-complex.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2018 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <iostream>
28 #include <sstream>
29 
30 #include "lo-ieee.h"
31 #include "lo-specfun.h"
32 #include "lo-mappers.h"
33 
34 #include "mxarray.h"
35 #include "ovl.h"
36 #include "oct-hdf5.h"
37 #include "oct-stream.h"
38 #include "ops.h"
39 #include "ov-complex.h"
40 #include "ov-flt-complex.h"
41 #include "ov-base.h"
42 #include "ov-base-scalar.h"
43 #include "ov-base-scalar.cc"
44 #include "ov-cx-mat.h"
45 #include "ov-scalar.h"
46 #include "errwarn.h"
47 #include "pr-output.h"
48 #include "ops.h"
49 
50 #include "ls-oct-text.h"
51 #include "ls-hdf5.h"
52 
53 // Prevent implicit instantiations on some systems (Windows, others?)
54 // that can lead to duplicate definitions of static data members.
55 
56 extern template class OCTINTERP_API octave_base_scalar<double>;
57 extern template class OCTINTERP_API octave_base_scalar<FloatComplex>;
58 
59 template class octave_base_scalar<Complex>;
60 
62  "complex scalar", "double");
63 
64 namespace octave
65 {
66  // Complain if a complex value is used as a subscript.
67 
69  {
70  public:
71 
73  : index_exception (value) { }
74 
75  ~complex_index_exception (void) = default;
76 
77  std::string details (void) const
78  {
79  return "subscripts must be real (forgot to initialize i or j?)";
80  }
81 
82  // ID of error to throw.
83  const char * err_id (void) const
84  {
85  return "Octave:invalid-index";
86  }
87  };
88 }
89 
90 static octave_base_value *
92 {
93  const octave_complex& v = dynamic_cast<const octave_complex&> (a);
94 
95  return new octave_float_complex (v.float_complex_value ());
96 }
97 
100 {
101  return
104 }
105 
108 {
109  octave_base_value *retval = nullptr;
110 
111  double im = scalar.imag ();
112 
113  if (im == 0.0)
114  retval = new octave_scalar (scalar.real ());
115 
116  return retval;
117 }
118 
120 octave_complex::do_index_op (const octave_value_list& idx, bool resize_ok)
121 {
122  // FIXME: this doesn't solve the problem of
123  //
124  // a = i; a([1,1], [1,1], [1,1])
125  //
126  // and similar constructions. Hmm...
127 
128  // FIXME: using this constructor avoids narrowing the
129  // 1x1 matrix back to a scalar value. Need a better solution
130  // to this problem.
131 
133 
134  return tmp.do_index_op (idx, resize_ok);
135 }
136 
137 // Can't make an index_vector from a complex number. Throw an error.
140 {
141  std::ostringstream buf;
142  buf << scalar.real () << std::showpos << scalar.imag () << 'i';
143  octave::complex_index_exception e (buf.str ());
144 
145  throw e;
146 }
147 
148 double
149 octave_complex::double_value (bool force_conversion) const
150 {
151  if (! force_conversion)
152  warn_implicit_conversion ("Octave:imag-to-real",
153  "complex scalar", "real scalar");
154 
155  return scalar.real ();
156 }
157 
158 float
159 octave_complex::float_value (bool force_conversion) const
160 {
161  if (! force_conversion)
162  warn_implicit_conversion ("Octave:imag-to-real",
163  "complex scalar", "real scalar");
164 
165  return scalar.real ();
166 }
167 
168 Matrix
169 octave_complex::matrix_value (bool force_conversion) const
170 {
171  Matrix retval;
172 
173  if (! force_conversion)
174  warn_implicit_conversion ("Octave:imag-to-real",
175  "complex scalar", "real matrix");
176 
177  retval = Matrix (1, 1, scalar.real ());
178 
179  return retval;
180 }
181 
183 octave_complex::float_matrix_value (bool force_conversion) const
184 {
186 
187  if (! force_conversion)
188  warn_implicit_conversion ("Octave:imag-to-real",
189  "complex scalar", "real matrix");
190 
191  retval = FloatMatrix (1, 1, scalar.real ());
192 
193  return retval;
194 }
195 
196 NDArray
197 octave_complex::array_value (bool force_conversion) const
198 {
199  NDArray retval;
200 
201  if (! force_conversion)
202  warn_implicit_conversion ("Octave:imag-to-real",
203  "complex scalar", "real matrix");
204 
205  retval = NDArray (dim_vector (1, 1), scalar.real ());
206 
207  return retval;
208 }
209 
211 octave_complex::float_array_value (bool force_conversion) const
212 {
214 
215  if (! force_conversion)
216  warn_implicit_conversion ("Octave:imag-to-real",
217  "complex scalar", "real matrix");
218 
219  retval = FloatNDArray (dim_vector (1, 1), scalar.real ());
220 
221  return retval;
222 }
223 
224 Complex
226 {
227  return scalar;
228 }
229 
232 {
233  return static_cast<FloatComplex> (scalar);
234 }
235 
238 {
239  return ComplexMatrix (1, 1, scalar);
240 }
241 
244 {
245  return FloatComplexMatrix (1, 1, static_cast<FloatComplex> (scalar));
246 }
247 
249 octave_complex::complex_array_value (bool /* force_conversion */) const
250 {
251  return ComplexNDArray (dim_vector (1, 1), scalar);
252 }
253 
255 octave_complex::float_complex_array_value (bool /* force_conversion */) const
256 {
257  return FloatComplexNDArray (dim_vector (1, 1),
258  static_cast<FloatComplex> (scalar));
259 }
260 
262 octave_complex::resize (const dim_vector& dv, bool fill) const
263 {
264  if (fill)
265  {
267 
268  if (dv.numel ())
269  retval(0) = scalar;
270 
271  return retval;
272  }
273  else
274  {
276 
277  if (dv.numel ())
278  retval(0) = scalar;
279 
280  return retval;
281  }
282 }
283 
286 {
287  return scalar;
288 }
289 
292 {
293  return FloatComplex (scalar);
294 }
295 
298 {
299  return ComplexDiagMatrix (Array<Complex> (dim_vector (1, 1), scalar), m, n);
300 }
301 
302 bool
304 {
305  Complex c = complex_value ();
306 
308 
309  os << "\n";
310 
311  return true;
312 }
313 
314 bool
316 {
317  scalar = octave_read_value<Complex> (is);
318 
319  if (! is)
320  error ("load: failed to load complex scalar constant");
321 
322  return true;
323 }
324 
325 bool
326 octave_complex::save_binary (std::ostream& os, bool& /* save_as_floats */)
327 {
328  char tmp = static_cast<char> (LS_DOUBLE);
329  os.write (reinterpret_cast<char *> (&tmp), 1);
330  Complex ctmp = complex_value ();
331  os.write (reinterpret_cast<char *> (&ctmp), 16);
332 
333  return true;
334 }
335 
336 bool
337 octave_complex::load_binary (std::istream& is, bool swap,
339 {
340  char tmp;
341  if (! is.read (reinterpret_cast<char *> (&tmp), 1))
342  return false;
343 
344  Complex ctmp;
345  read_doubles (is, reinterpret_cast<double *> (&ctmp),
346  static_cast<save_type> (tmp), 2, swap, fmt);
347 
348  if (! is)
349  return false;
350 
351  scalar = ctmp;
352  return true;
353 }
354 
355 bool
357  bool /* save_as_floats */)
358 {
359  bool retval = false;
360 
361 #if defined (HAVE_HDF5)
362 
363  hsize_t dimens[3];
364  hid_t space_hid, type_hid, data_hid;
365  space_hid = type_hid = data_hid = -1;
366 
367  space_hid = H5Screate_simple (0, dimens, nullptr);
368  if (space_hid < 0)
369  return false;
370 
371  type_hid = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
372  if (type_hid < 0)
373  {
374  H5Sclose (space_hid);
375  return false;
376  }
377 #if defined (HAVE_HDF5_18)
378  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid,
380 #else
381  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, octave_H5P_DEFAULT);
382 #endif
383  if (data_hid < 0)
384  {
385  H5Sclose (space_hid);
386  H5Tclose (type_hid);
387  return false;
388  }
389 
391  retval = H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,
392  octave_H5P_DEFAULT, &tmp) >= 0;
393 
394  H5Dclose (data_hid);
395  H5Tclose (type_hid);
396  H5Sclose (space_hid);
397 
398 #else
399  octave_unused_parameter (loc_id);
400  octave_unused_parameter (name);
401 
402  warn_save ("hdf5");
403 #endif
404 
405  return retval;
406 }
407 
408 bool
410 {
411  bool retval = false;
412 
413 #if defined (HAVE_HDF5)
414 
415 #if defined (HAVE_HDF5_18)
416  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);
417 #else
418  hid_t data_hid = H5Dopen (loc_id, name);
419 #endif
420  hid_t type_hid = H5Dget_type (data_hid);
421 
422  hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
423 
424  if (! hdf5_types_compatible (type_hid, complex_type))
425  {
426  H5Tclose (complex_type);
427  H5Dclose (data_hid);
428  return false;
429  }
430 
431  hid_t space_id = H5Dget_space (data_hid);
432  hsize_t rank = H5Sget_simple_extent_ndims (space_id);
433 
434  if (rank != 0)
435  {
436  H5Tclose (complex_type);
437  H5Sclose (space_id);
438  H5Dclose (data_hid);
439  return false;
440  }
441 
442  // complex scalar:
443  Complex ctmp;
444  if (H5Dread (data_hid, complex_type, octave_H5S_ALL, octave_H5S_ALL,
445  octave_H5P_DEFAULT, &ctmp) >= 0)
446  {
447  retval = true;
448  scalar = ctmp;
449  }
450 
451  H5Tclose (complex_type);
452  H5Sclose (space_id);
453  H5Dclose (data_hid);
454 
455 #else
456  octave_unused_parameter (loc_id);
457  octave_unused_parameter (name);
458 
459  warn_load ("hdf5");
460 #endif
461 
462  return retval;
463 }
464 
465 mxArray *
467 {
469 
470  double *pr = static_cast<double *> (retval->get_data ());
471  double *pi = static_cast<double *> (retval->get_imag_data ());
472 
473  pr[0] = scalar.real ();
474  pi[0] = scalar.imag ();
475 
476  return retval;
477 }
478 
481 {
482  switch (umap)
483  {
484 #define SCALAR_MAPPER(UMAP, FCN) \
485  case umap_ ## UMAP: \
486  return octave_value (FCN (scalar))
487 
491  SCALAR_MAPPER (angle, std::arg);
504  SCALAR_MAPPER (cos, std::cos);
505  SCALAR_MAPPER (cosh, std::cosh);
506  SCALAR_MAPPER (exp, std::exp);
513  SCALAR_MAPPER (log10, std::log10);
519  SCALAR_MAPPER (sin, std::sin);
520  SCALAR_MAPPER (sinh, std::sinh);
521  SCALAR_MAPPER (sqrt, std::sqrt);
522  SCALAR_MAPPER (tan, std::tan);
523  SCALAR_MAPPER (tanh, std::tanh);
528 
529  // Special cases for Matlab compatibility.
530  case umap_xtolower:
531  case umap_xtoupper:
532  return scalar;
533 
534  default:
535  return octave_base_value::map (umap);
536  }
537 }
octave_idx_type write(const octave_value &data, octave_idx_type block_size, oct_data_conv::data_type output_type, octave_idx_type skip, mach_info::float_format flt_fmt)
Definition: oct-stream.cc:6704
double erfcx(double x)
Definition: lo-specfun.cc:1756
const char * err_id(void) const
Definition: ov-complex.cc:83
octave_value as_single(void) const
Definition: ov-complex.cc:291
ComplexMatrix complex_matrix_value(bool=false) const
Definition: ov-complex.cc:237
bool save_binary(std::ostream &os, bool &save_as_floats)
Definition: ov-complex.cc:326
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov-complex.cc:120
FloatNDArray float_array_value(bool=false) const
Definition: ov-complex.cc:211
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
Definition: ov-complex.cc:356
NDArray array_value(bool=false) const
Definition: ov-complex.cc:197
static octave_base_value * default_numeric_demotion_function(const octave_base_value &a)
Definition: ov-complex.cc:91
std::complex< double > erfi(std::complex< double > z, double relerr=0)
const octave_hdf5_id octave_H5S_ALL
static int static_type_id(void)
double erfi(double x)
Definition: lo-specfun.cc:1775
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition: ov-complex.cc:409
double asinh(double x)
Definition: lo-specfun.h:67
bool save_ascii(std::ostream &os)
Definition: ov-complex.cc:303
bool isna(double x)
Definition: lo-mappers.cc:45
OCTAVE_EXPORT octave_value_list or N dimensional array whose elements are all equal to the base of natural logarithms The constant ex $e satisfies the equation log(e)
bool isnan(bool)
Definition: lo-mappers.h:187
void octave_write_complex(std::ostream &os, const Complex &c)
Definition: lo-utils.cc:408
std::complex< T > ceil(const std::complex< T > &x)
Definition: lo-mappers.h:112
idx_vector index_vector(bool=false) const
Definition: ov-complex.cc:139
void error(const char *fmt,...)
Definition: error.cc:578
bool isinf(double x)
Definition: lo-mappers.h:225
std::complex< T > floor(const std::complex< T > &x)
Definition: lo-mappers.h:139
static T abs(T x)
Definition: pr-output.cc:1696
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
Definition: ov-complex.cc:337
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:180
FloatMatrix float_matrix_value(bool=false) const
Definition: ov-complex.cc:183
Complex acos(const Complex &x)
Definition: lo-mappers.cc:83
FloatComplex float_complex_value(bool=false) const
Definition: ov-complex.cc:231
Complex atan(const Complex &x)
Definition: lo-mappers.h:80
#define SCALAR_MAPPER(UMAP, FCN)
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
double fix(double x)
Definition: lo-mappers.h:127
Complex asin(const Complex &x)
Definition: lo-mappers.cc:105
i e
Definition: data.cc:2591
Complex log2(const Complex &x)
Definition: lo-mappers.cc:137
Complex erfc(const Complex &x)
Definition: lo-specfun.cc:1653
std::complex< double > erf(std::complex< double > z, double relerr=0)
virtual octave_value map(unary_mapper_t) const
Definition: ov-base.cc:1121
octave_value arg
Definition: pr-output.cc:3244
FloatComplexNDArray float_complex_array_value(bool=false) const
Definition: ov-complex.cc:255
void warn_load(const char *type) const
Definition: ov-base.cc:1097
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
bool swap
Definition: load-save.cc:738
Complex expm1(const Complex &x)
Definition: lo-specfun.cc:1875
double double_value(bool=false) const
Definition: ov-complex.cc:149
ComplexColumnVector conj(const ComplexColumnVector &a)
Definition: CColVector.cc:215
nd deftypefn *std::string name
Definition: sysdep.cc:647
double acosh(double x)
Definition: lo-specfun.h:49
float float_value(bool=false) const
Definition: ov-complex.cc:159
octave_value as_double(void) const
Definition: ov-complex.cc:285
void read_doubles(std::istream &is, double *data, save_type type, octave_idx_type len, bool swap, octave::mach_info::float_format fmt)
Definition: data-conv.cc:772
octave_base_value * try_narrowing_conversion(void)
Definition: ov-complex.cc:107
Complex log1p(const Complex &x)
Definition: lo-specfun.cc:1959
bool hdf5_types_compatible(octave_hdf5_id t1, octave_hdf5_id t2)
Definition: ls-hdf5.cc:190
double signum(double x)
Definition: lo-mappers.h:244
double dawson(double x)
Definition: lo-specfun.cc:1518
double tmp
Definition: data.cc:6252
octave_value retval
Definition: data.cc:6246
mxArray * as_mxArray(void) const
Definition: ov-complex.cc:466
std::complex< double > erfcx(std::complex< double > z, double relerr=0)
int64_t octave_hdf5_id
double atanh(double x)
Definition: lo-specfun.h:72
void warn_save(const char *type) const
Definition: ov-base.cc:1106
Definition: dMatrix.h:36
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov-complex.cc:262
ComplexNDArray complex_array_value(bool=false) const
Definition: ov-complex.cc:249
Complex erf(const Complex &x)
Definition: lo-specfun.cc:1638
void mxArray
Definition: mex.h:55
octave_value map(unary_mapper_t umap) const
Definition: ov-complex.cc:480
complex_index_exception(const std::string &value)
Definition: ov-complex.cc:72
octave_value diag(octave_idx_type m, octave_idx_type n) const
Definition: ov-complex.cc:297
Complex complex_value(bool=false) const
Definition: ov-complex.cc:225
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:362
void warn_implicit_conversion(const char *id, const char *from, const char *to)
Definition: errwarn.cc:338
bool isfinite(double x)
Definition: lo-mappers.h:201
double roundb(double x)
Definition: lo-mappers.h:156
std::string details(void) const
Definition: ov-complex.cc:77
type_conv_info numeric_demotion_function(void) const
Definition: ov-complex.cc:99
double round(double x)
Definition: lo-mappers.h:145
Matrix matrix_value(bool=false) const
Definition: ov-complex.cc:169
bool load_ascii(std::istream &is)
Definition: ov-complex.cc:315
FloatComplexMatrix float_complex_matrix_value(bool=false) const
Definition: ov-complex.cc:243
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:141
const octave_hdf5_id octave_H5P_DEFAULT
std::complex< float > FloatComplex
Definition: oct-cmplx.h:32
std::complex< double > Complex
Definition: oct-cmplx.h:31
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:135
write the output to stdout if nargout is
Definition: load-save.cc:1612
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
octave_hdf5_id hdf5_make_complex_type(octave_hdf5_id num_type)
Definition: ls-hdf5.cc:326
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
nd group nd example For each display the value
Definition: sysdep.cc:866
dim_vector dv
Definition: sub2ind.cc:263
octave::stream os
Definition: file-io.cc:627
static const double pi
Definition: lo-specfun.cc:1996
std::complex< double > erfc(std::complex< double > z, double relerr=0)