GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov-flt-complex.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <istream>
31 #include <ostream>
32 
33 #include "lo-ieee.h"
34 #include "lo-specfun.h"
35 #include "lo-mappers.h"
36 
37 #include "mxarray.h"
38 #include "ovl.h"
39 #include "oct-hdf5.h"
40 #include "oct-stream.h"
41 #include "ops.h"
42 #include "ov-complex.h"
43 #include "ov-base.h"
44 #include "ov-base-scalar.h"
45 #include "ov-base-scalar.cc"
46 #include "ov-flt-cx-mat.h"
47 #include "ov-float.h"
48 #include "ov-flt-complex.h"
49 #include "errwarn.h"
50 #include "pr-output.h"
51 #include "ops.h"
52 
53 #include "ls-oct-text.h"
54 #include "ls-hdf5.h"
55 
56 // Prevent implicit instantiations on some systems (Windows, others?)
57 // that can lead to duplicate definitions of static data members.
58 
59 extern template class octave_base_scalar<float>;
60 
62 
64  "float complex scalar", "single");
65 
68 {
69  octave_base_value *retval = nullptr;
70 
71  float im = scalar.imag ();
72 
73  if (im == 0.0)
74  retval = new octave_float_scalar (scalar.real ());
75 
76  return retval;
77 }
78 
81 {
82  // FIXME: this doesn't solve the problem of
83  //
84  // a = i; a([1,1], [1,1], [1,1])
85  //
86  // and similar constructions. Hmm...
87 
88  // FIXME: using this constructor avoids narrowing the
89  // 1x1 matrix back to a scalar value. Need a better solution
90  // to this problem.
91 
93 
94  return tmp.index_op (idx, resize_ok);
95 }
96 
97 double
98 octave_float_complex::double_value (bool force_conversion) const
99 {
100  if (! force_conversion)
101  warn_implicit_conversion ("Octave:imag-to-real",
102  "complex scalar", "real scalar");
103 
104  return scalar.real ();
105 }
106 
107 float
108 octave_float_complex::float_value (bool force_conversion) const
109 {
110  if (! force_conversion)
111  warn_implicit_conversion ("Octave:imag-to-real",
112  "complex scalar", "real scalar");
113 
114  return scalar.real ();
115 }
116 
117 Matrix
118 octave_float_complex::matrix_value (bool force_conversion) const
119 {
120  Matrix retval;
121 
122  if (! force_conversion)
123  warn_implicit_conversion ("Octave:imag-to-real",
124  "complex scalar", "real matrix");
125 
126  retval = Matrix (1, 1, scalar.real ());
127 
128  return retval;
129 }
130 
132 octave_float_complex::float_matrix_value (bool force_conversion) const
133 {
134  FloatMatrix retval;
135 
136  if (! force_conversion)
137  warn_implicit_conversion ("Octave:imag-to-real",
138  "complex scalar", "real matrix");
139 
140  retval = FloatMatrix (1, 1, scalar.real ());
141 
142  return retval;
143 }
144 
145 NDArray
146 octave_float_complex::array_value (bool force_conversion) const
147 {
148  NDArray retval;
149 
150  if (! force_conversion)
151  warn_implicit_conversion ("Octave:imag-to-real",
152  "complex scalar", "real matrix");
153 
154  retval = NDArray (dim_vector (1, 1), scalar.real ());
155 
156  return retval;
157 }
158 
160 octave_float_complex::float_array_value (bool force_conversion) const
161 {
162  FloatNDArray retval;
163 
164  if (! force_conversion)
165  warn_implicit_conversion ("Octave:imag-to-real",
166  "complex scalar", "real matrix");
167 
168  retval = FloatNDArray (dim_vector (1, 1), scalar.real ());
169 
170  return retval;
171 }
172 
173 Complex
175 {
176  return scalar;
177 }
178 
181 {
182  return static_cast<FloatComplex> (scalar);
183 }
184 
187 {
188  return ComplexMatrix (1, 1, scalar);
189 }
190 
193 {
194  return FloatComplexMatrix (1, 1, scalar);
195 }
196 
198 octave_float_complex::complex_array_value (bool /* force_conversion */) const
199 {
200  return ComplexNDArray (dim_vector (1, 1), scalar);
201 }
202 
204 octave_float_complex::float_complex_array_value (bool /* force_conversion */) const
205 {
206  return FloatComplexNDArray (dim_vector (1, 1), scalar);
207 }
208 
210 octave_float_complex::resize (const dim_vector& dv, bool fill) const
211 {
212  if (fill)
213  {
214  FloatComplexNDArray retval (dv, FloatComplex (0));
215 
216  if (dv.numel ())
217  retval(0) = scalar;
218 
219  return retval;
220  }
221  else
222  {
223  FloatComplexNDArray retval (dv);
224 
225  if (dv.numel ())
226  retval(0) = scalar;
227 
228  return retval;
229  }
230 }
231 
234 {
235  return Complex (scalar);
236 }
237 
240 {
241  return scalar;
242 }
243 
246 {
247  return
249  m, n);
250 }
251 
252 bool
254 {
256 
257  octave::write_value<FloatComplex> (os, c);
258 
259  os << "\n";
260 
261  return true;
262 }
263 
264 bool
266 {
267  scalar = octave::read_value<FloatComplex> (is);
268 
269  if (! is)
270  error ("load: failed to load complex scalar constant");
271 
272  return true;
273 }
274 
275 bool
276 octave_float_complex::save_binary (std::ostream& os, bool /* save_as_floats */)
277 {
278  char tmp = static_cast<char> (LS_FLOAT);
279  os.write (reinterpret_cast<char *> (&tmp), 1);
281  os.write (reinterpret_cast<char *> (&ctmp), 8);
282 
283  return true;
284 }
285 
286 bool
287 octave_float_complex::load_binary (std::istream& is, bool swap,
289 {
290  char tmp;
291  if (! is.read (reinterpret_cast<char *> (&tmp), 1))
292  return false;
293 
294  FloatComplex ctmp;
295  read_floats (is, reinterpret_cast<float *> (&ctmp),
296  static_cast<save_type> (tmp), 2, swap, fmt);
297 
298  if (! is)
299  return false;
300 
301  scalar = ctmp;
302  return true;
303 }
304 
305 bool
307  bool /* save_as_floats */)
308 {
309  bool retval = false;
310 
311 #if defined (HAVE_HDF5)
312 
313  hsize_t dimens[3] = {0};
314  hid_t space_hid, type_hid, data_hid;
315  space_hid = type_hid = data_hid = -1;
316 
317  space_hid = H5Screate_simple (0, dimens, nullptr);
318  if (space_hid < 0)
319  return false;
320 
321  type_hid = hdf5_make_complex_type (H5T_NATIVE_FLOAT);
322  if (type_hid < 0)
323  {
324  H5Sclose (space_hid);
325  return false;
326  }
327 #if defined (HAVE_HDF5_18)
328  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid,
331 #else
332  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, octave_H5P_DEFAULT);
333 #endif
334  if (data_hid < 0)
335  {
336  H5Sclose (space_hid);
337  H5Tclose (type_hid);
338  return false;
339  }
340 
342  retval = H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,
343  octave_H5P_DEFAULT, &tmp) >= 0;
344 
345  H5Dclose (data_hid);
346  H5Tclose (type_hid);
347  H5Sclose (space_hid);
348 
349 #else
350  octave_unused_parameter (loc_id);
351  octave_unused_parameter (name);
352 
353  warn_save ("hdf5");
354 #endif
355 
356  return retval;
357 }
358 
359 bool
361 {
362  bool retval = false;
363 
364 #if defined (HAVE_HDF5)
365 
366 #if defined (HAVE_HDF5_18)
367  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);
368 #else
369  hid_t data_hid = H5Dopen (loc_id, name);
370 #endif
371  hid_t type_hid = H5Dget_type (data_hid);
372 
373  hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_FLOAT);
374 
375  if (! hdf5_types_compatible (type_hid, complex_type))
376  {
377  H5Tclose (complex_type);
378  H5Dclose (data_hid);
379  return false;
380  }
381 
382  hid_t space_id = H5Dget_space (data_hid);
383  hsize_t rank = H5Sget_simple_extent_ndims (space_id);
384 
385  if (rank != 0)
386  {
387  H5Tclose (complex_type);
388  H5Sclose (space_id);
389  H5Dclose (data_hid);
390  return false;
391  }
392 
393  // complex scalar:
394  FloatComplex ctmp;
395  if (H5Dread (data_hid, complex_type, octave_H5S_ALL, octave_H5S_ALL,
396  octave_H5P_DEFAULT, &ctmp)
397  >= 0)
398  {
399  retval = true;
400  scalar = ctmp;
401  }
402 
403  H5Tclose (complex_type);
404  H5Sclose (space_id);
405  H5Dclose (data_hid);
406 
407 #else
408  octave_unused_parameter (loc_id);
409  octave_unused_parameter (name);
410 
411  warn_load ("hdf5");
412 #endif
413 
414  return retval;
415 }
416 
417 mxArray *
418 octave_float_complex::as_mxArray (bool interleaved) const
419 {
420  mxArray *retval = new mxArray (interleaved, mxSINGLE_CLASS, 1, 1, mxCOMPLEX);
421 
422  if (interleaved)
423  {
424  mxComplexSingle *pd
425  = static_cast<mxComplexSingle *> (retval->get_data ());
426 
427  pd[0].real = scalar.real ();
428  pd[0].imag = scalar.imag ();
429  }
430  else
431  {
432  mxSingle *pr = static_cast<mxSingle *> (retval->get_data ());
433  mxSingle *pi = static_cast<mxSingle *> (retval->get_imag_data ());
434 
435  pr[0] = scalar.real ();
436  pi[0] = scalar.imag ();
437  }
438 
439  return retval;
440 }
441 
444 {
445  switch (umap)
446  {
447 #define SCALAR_MAPPER(UMAP, FCN) \
448  case umap_ ## UMAP: \
449  return octave_value (FCN (scalar))
450 
451  SCALAR_MAPPER (abs, std::abs);
454  SCALAR_MAPPER (angle, std::arg);
455  SCALAR_MAPPER (arg, std::arg);
467  SCALAR_MAPPER (cos, std::cos);
468  SCALAR_MAPPER (cosh, std::cosh);
469  SCALAR_MAPPER (exp, std::exp);
474  SCALAR_MAPPER (log, std::log);
476  SCALAR_MAPPER (log10, std::log10);
482  SCALAR_MAPPER (sin, std::sin);
483  SCALAR_MAPPER (sinh, std::sinh);
484  SCALAR_MAPPER (sqrt, std::sqrt);
485  SCALAR_MAPPER (tan, std::tan);
486  SCALAR_MAPPER (tanh, std::tanh);
491 
492  // Special cases for Matlab compatibility
493  case umap_xtolower:
494  case umap_xtoupper:
495  return scalar;
496 
497  default:
498  return octave_base_value::map (umap);
499  }
500 }
ComplexColumnVector conj(const ComplexColumnVector &a)
Definition: CColVector.cc:217
N Dimensional Array with copy-on-write semantics.
Definition: Array.h:130
Definition: dMatrix.h:42
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:335
void * get_imag_data() const
Definition: mxarray.h:511
void * get_data() const
Definition: mxarray.h:473
virtual octave_value map(unary_mapper_t) const
Definition: ov-base.cc:1181
void warn_load(const char *type) const
Definition: ov-base.cc:1157
void warn_save(const char *type) const
Definition: ov-base.cc:1166
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
bool load_ascii(std::istream &is)
FloatMatrix float_matrix_value(bool=false) const
octave_value as_double() const
bool save_ascii(std::ostream &os)
FloatComplexNDArray float_complex_array_value(bool=false) const
Complex complex_value(bool=false) const
NDArray array_value(bool=false) const
ComplexNDArray complex_array_value(bool=false) const
bool save_binary(std::ostream &os, bool save_as_floats)
octave_value map(unary_mapper_t umap) const
ComplexMatrix complex_matrix_value(bool=false) const
mxArray * as_mxArray(bool interleaved) const
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
octave_value diag(octave_idx_type m, octave_idx_type n) const
float float_value(bool=false) const
Matrix matrix_value(bool=false) const
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
double double_value(bool=false) const
FloatComplexMatrix float_complex_matrix_value(bool=false) const
octave_value as_single() const
FloatNDArray float_array_value(bool=false) const
octave_base_value * try_narrowing_conversion()
FloatComplex float_complex_value(bool=false) const
octave_value resize(const dim_vector &dv, bool fill=false) const
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
octave_value index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov.h:504
const octave_hdf5_id octave_H5P_DEFAULT
const octave_hdf5_id octave_H5S_ALL
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:137
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:143
void read_floats(std::istream &is, float *data, save_type type, octave_idx_type len, bool swap, octave::mach_info::float_format fmt)
Definition: data-conv.cc:836
save_type
Definition: data-conv.h:87
@ LS_FLOAT
Definition: data-conv.h:94
void() error(const char *fmt,...)
Definition: error.cc:988
void warn_implicit_conversion(const char *id, const char *from, const char *to)
Definition: errwarn.cc:344
Complex log2(const Complex &x)
Definition: lo-mappers.cc:141
Complex asin(const Complex &x)
Definition: lo-mappers.cc:107
bool isna(double x)
Definition: lo-mappers.cc:47
Complex acos(const Complex &x)
Definition: lo-mappers.cc:85
Complex atan(const Complex &x)
Definition: lo-mappers.h:71
double roundb(double x)
Definition: lo-mappers.h:147
bool isfinite(double x)
Definition: lo-mappers.h:192
bool isinf(double x)
Definition: lo-mappers.h:203
double signum(double x)
Definition: lo-mappers.h:229
double round(double x)
Definition: lo-mappers.h:136
bool isnan(bool)
Definition: lo-mappers.h:178
std::complex< T > floor(const std::complex< T > &x)
Definition: lo-mappers.h:130
std::complex< T > ceil(const std::complex< T > &x)
Definition: lo-mappers.h:103
double fix(double x)
Definition: lo-mappers.h:118
double dawson(double x)
Definition: lo-specfun.cc:1467
Complex expm1(const Complex &x)
Definition: lo-specfun.cc:1835
Complex log1p(const Complex &x)
Definition: lo-specfun.cc:1919
double asinh(double x)
Definition: lo-specfun.h:58
double atanh(double x)
Definition: lo-specfun.h:63
double acosh(double x)
Definition: lo-specfun.h:40
octave_hdf5_id hdf5_make_complex_type(octave_hdf5_id num_type)
Definition: ls-hdf5.cc:405
bool hdf5_types_compatible(octave_hdf5_id t1, octave_hdf5_id t2)
Definition: ls-hdf5.cc:269
float_format
Definition: mach-info.h:38
void mxArray
Definition: mex.h:58
T octave_idx_type m
Definition: mx-inlines.cc:781
octave_idx_type n
Definition: mx-inlines.cc:761
float mxSingle
Definition: mxtypes.h:92
@ mxSINGLE_CLASS
Definition: mxtypes.h:65
@ mxCOMPLEX
Definition: mxtypes.h:81
std::complex< double > erfc(std::complex< double > z, double relerr=0)
std::complex< double > erfcx(std::complex< double > z, double relerr=0)
std::complex< double > erfi(std::complex< double > z, double relerr=0)
std::complex< double > erf(std::complex< double > z, double relerr=0)
std::complex< double > Complex
Definition: oct-cmplx.h:33
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
int64_t octave_hdf5_id
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:235
#define SCALAR_MAPPER(UMAP, FCN)
template int8_t abs(int8_t)
mxSingle real
Definition: mxtypes.h:105
mxSingle imag
Definition: mxtypes.h:105