GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
fCRowVector.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1994-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 #include <type_traits>
33 
34 #include "Array-util.h"
35 #include "lo-blas-proto.h"
36 #include "lo-error.h"
37 #include "mx-base.h"
38 #include "mx-inlines.cc"
39 #include "oct-cmplx.h"
40 
41 // FloatComplex Row Vector class
42 
43 bool
45 {
47  if (len != a.numel ())
48  return 0;
49  return mx_inline_equal (len, data (), a.data ());
50 }
51 
52 bool
54 {
55  return !(*this == a);
56 }
57 
58 // destructive insert/delete/reorder operations
59 
62 {
63  octave_idx_type a_len = a.numel ();
64 
65  if (c < 0 || c + a_len > numel ())
66  (*current_liboctave_error_handler) ("range error for insert");
67 
68  if (a_len > 0)
69  {
70  make_unique ();
71 
72  for (octave_idx_type i = 0; i < a_len; i++)
73  xelem (c+i) = a.elem (i);
74  }
75 
76  return *this;
77 }
78 
82 {
83  octave_idx_type a_len = a.numel ();
84 
85  if (c < 0 || c + a_len > numel ())
86  (*current_liboctave_error_handler) ("range error for insert");
87 
88  if (a_len > 0)
89  {
90  make_unique ();
91 
92  for (octave_idx_type i = 0; i < a_len; i++)
93  xelem (c+i) = a.elem (i);
94  }
95 
96  return *this;
97 }
98 
101 {
103 
104  if (len > 0)
105  {
106  make_unique ();
107 
108  for (octave_idx_type i = 0; i < len; i++)
109  xelem (i) = val;
110  }
111 
112  return *this;
113 }
114 
117 {
119 
120  if (len > 0)
121  {
122  make_unique ();
123 
124  for (octave_idx_type i = 0; i < len; i++)
125  xelem (i) = val;
126  }
127 
128  return *this;
129 }
130 
133 {
135 
136  if (c1 < 0 || c2 < 0 || c1 >= len || c2 >= len)
137  (*current_liboctave_error_handler) ("range error for fill");
138 
139  if (c1 > c2) { std::swap (c1, c2); }
140 
141  if (c2 >= c1)
142  {
143  make_unique ();
144 
145  for (octave_idx_type i = c1; i <= c2; i++)
146  xelem (i) = val;
147  }
148 
149  return *this;
150 }
151 
155 {
157 
158  if (c1 < 0 || c2 < 0 || c1 >= len || c2 >= len)
159  (*current_liboctave_error_handler) ("range error for fill");
160 
161  if (c1 > c2) { std::swap (c1, c2); }
162 
163  if (c2 >= c1)
164  {
165  make_unique ();
166 
167  for (octave_idx_type i = c1; i <= c2; i++)
168  xelem (i) = val;
169  }
170 
171  return *this;
172 }
173 
176 {
178  octave_idx_type nc_insert = len;
179  FloatComplexRowVector retval (len + a.numel ());
180  retval.insert (*this, 0);
181  retval.insert (a, nc_insert);
182  return retval;
183 }
184 
187 {
189  octave_idx_type nc_insert = len;
190  FloatComplexRowVector retval (len + a.numel ());
191  retval.insert (*this, 0);
192  retval.insert (a, nc_insert);
193  return retval;
194 }
195 
198 {
200 }
201 
204 {
206 }
207 
210 {
211  return do_mx_unary_map<FloatComplex, FloatComplex, std::conj<float>> (a);
212 }
213 
214 // resize is the destructive equivalent for this one
215 
218 {
219  if (c1 > c2) { std::swap (c1, c2); }
220 
221  octave_idx_type new_c = c2 - c1 + 1;
222 
223  FloatComplexRowVector result (new_c);
224 
225  for (octave_idx_type i = 0; i < new_c; i++)
226  result.elem (i) = elem (c1+i);
227 
228  return result;
229 }
230 
233 {
234  FloatComplexRowVector result (n);
235 
236  for (octave_idx_type i = 0; i < n; i++)
237  result.elem (i) = elem (r1+i);
238 
239  return result;
240 }
241 
242 // row vector by row vector -> row vector operations
243 
246 {
248 
249  octave_idx_type a_len = a.numel ();
250 
251  if (len != a_len)
252  octave::err_nonconformant ("operator +=", len, a_len);
253 
254  if (len == 0)
255  return *this;
256 
257  FloatComplex *d = fortran_vec (); // Ensures only 1 reference to my privates!
258 
259  mx_inline_add2 (len, d, a.data ());
260  return *this;
261 }
262 
265 {
267 
268  octave_idx_type a_len = a.numel ();
269 
270  if (len != a_len)
271  octave::err_nonconformant ("operator -=", len, a_len);
272 
273  if (len == 0)
274  return *this;
275 
276  FloatComplex *d = fortran_vec (); // Ensures only 1 reference to my privates!
277 
278  mx_inline_sub2 (len, d, a.data ());
279  return *this;
280 }
281 
282 // row vector by matrix -> row vector
283 
286 {
287  FloatComplexRowVector retval;
288 
289  F77_INT len = octave::to_f77_int (v.numel ());
290 
291  F77_INT a_nr = octave::to_f77_int (a.rows ());
292  F77_INT a_nc = octave::to_f77_int (a.cols ());
293 
294  if (a_nr != len)
295  octave::err_nonconformant ("operator *", 1, len, a_nr, a_nc);
296 
297  if (len == 0)
298  retval.resize (a_nc, 0.0);
299  else
300  {
301  // Transpose A to form A'*x == (x'*A)'
302 
303  F77_INT ld = a_nr;
304 
305  retval.resize (a_nc);
306  FloatComplex *y = retval.fortran_vec ();
307 
308  F77_XFCN (cgemv, CGEMV, (F77_CONST_CHAR_ARG2 ("T", 1),
309  a_nr, a_nc, 1.0, F77_CONST_CMPLX_ARG (a.data ()),
310  ld, F77_CONST_CMPLX_ARG (v.data ()), 1, 0.0, F77_CMPLX_ARG (y), 1
311  F77_CHAR_ARG_LEN (1)));
312  }
313 
314  return retval;
315 }
316 
319 {
320  FloatComplexRowVector tmp (v);
321  return tmp * a;
322 }
323 
324 // other operations
325 
328 {
330  if (len == 0)
331  return FloatComplex (0.0);
332 
333  FloatComplex res = elem (0);
334  float absres = std::abs (res);
335 
336  for (octave_idx_type i = 1; i < len; i++)
337  if (std::abs (elem (i)) < absres)
338  {
339  res = elem (i);
340  absres = std::abs (res);
341  }
342 
343  return res;
344 }
345 
348 {
350  if (len == 0)
351  return FloatComplex (0.0);
352 
353  FloatComplex res = elem (0);
354  float absres = std::abs (res);
355 
356  for (octave_idx_type i = 1; i < len; i++)
357  if (std::abs (elem (i)) > absres)
358  {
359  res = elem (i);
360  absres = std::abs (res);
361  }
362 
363  return res;
364 }
365 
366 // i/o
367 
368 std::ostream&
369 operator << (std::ostream& os, const FloatComplexRowVector& a)
370 {
371 // int field_width = os.precision () + 7;
372  for (octave_idx_type i = 0; i < a.numel (); i++)
373  os << ' ' /* setw (field_width) */ << a.elem (i);
374  return os;
375 }
376 
377 std::istream&
378 operator >> (std::istream& is, FloatComplexRowVector& a)
379 {
380  octave_idx_type len = a.numel ();
381 
382  if (len > 0)
383  {
384  FloatComplex tmp;
385  for (octave_idx_type i = 0; i < len; i++)
386  {
387  is >> tmp;
388  if (is)
389  a.elem (i) = tmp;
390  else
391  break;
392  }
393  }
394  return is;
395 }
396 
397 // row vector by column vector -> scalar
398 
399 // row vector by column vector -> scalar
400 
403 {
404  FloatComplexColumnVector tmp (a);
405  return v * tmp;
406 }
407 
410 {
411  FloatComplex retval (0.0, 0.0);
412 
413  F77_INT len = octave::to_f77_int (v.numel ());
414 
415  F77_INT a_len = octave::to_f77_int (a.numel ());
416 
417  if (len != a_len)
418  octave::err_nonconformant ("operator *", len, a_len);
419 
420  if (len != 0)
421  F77_FUNC (xcdotu, XCDOTU) (len, F77_CONST_CMPLX_ARG (v.data ()), 1,
422  F77_CONST_CMPLX_ARG (a.data ()), 1, F77_CMPLX_ARG (&retval));
423 
424  return retval;
425 }
426 
427 // other operations
428 
430 linspace (const FloatComplex& x1, const FloatComplex& x2, octave_idx_type n_in)
431 {
432  FloatComplexRowVector retval;
433 
434  if (n_in < 1)
435  return retval;
436  else if (n_in == 1)
437  {
438  retval.resize (1, x2);
439  return retval;
440  }
441  else if (x1 == x2)
442  {
443  retval.resize (n_in, x2);
444  return retval;
445  }
446 
447  // Use unsigned type (guaranteed n_in > 1 at this point) so that divisions
448  // by 2 can be replaced by compiler with shift right instructions.
449  typedef std::make_unsigned<octave_idx_type>::type unsigned_octave_idx_type;
450 
451  unsigned_octave_idx_type n = n_in;
452 
453  // Set endpoints, rather than calculate, for maximum accuracy.
454  retval.clear (n);
455  retval.xelem (0) = x1;
456  retval.xelem (n-1) = x2;
457 
458  // Construct linspace symmetrically from both ends.
459  bool isnan_delta = false;
460  FloatComplex delta = (x2 - x1) / (n - 1.0f);
461  if (octave::math::isinf (delta))
462  {
463  if (octave::math::isinf (delta.real ()))
464  delta.real (octave::numeric_limits<float>::NaN ());
465  if (octave::math::isinf (delta.imag ()))
466  delta.imag (octave::numeric_limits<float>::NaN ());
467  isnan_delta = true;
468  }
469 
470  unsigned_octave_idx_type n2 = n/2;
471  for (unsigned_octave_idx_type i = 1; i < n2; i++)
472  {
473  retval.xelem (i) = x1 + static_cast<float> (i)*delta;
474  retval.xelem (n-1-i) = x2 - static_cast<float> (i)*delta;
475  }
476  if (n % 2 == 1) // Middle element if number of elements is odd.
477  {
478  if (x1 == -x2)
479  retval.xelem (n2) = 0;
480  else
481  {
482  FloatComplex c = (x1 + x2) / 2.0f;
483  if (isnan_delta)
484  {
485  if (octave::math::isnan (delta.real ()))
487  if (octave::math::isnan (delta.imag ()))
489  }
490  retval.xelem (n2) = c;
491  }
492  }
493 
494  return retval;
495 }
#define NaN
Definition: Faddeeva.cc:261
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:562
T * fortran_vec()
Size of the specified dimension.
Definition: Array-base.cc:1764
octave_idx_type rows() const
Definition: Array.h:459
const T * data() const
Size of the specified dimension.
Definition: Array.h:663
octave_idx_type cols() const
Definition: Array.h:469
void make_unique()
Definition: Array.h:216
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:524
octave_idx_type numel() const
Number of elements in the array.
Definition: Array.h:414
void clear(octave_idx_type n)
Definition: fCRowVector.h:140
void resize(octave_idx_type n, const FloatComplex &rfv=FloatComplex(0))
Definition: fCRowVector.h:135
FloatComplexColumnVector hermitian() const
Definition: fCRowVector.cc:197
FloatComplexColumnVector transpose() const
Definition: fCRowVector.cc:203
FloatComplexRowVector append(const FloatRowVector &a) const
Definition: fCRowVector.cc:175
bool operator!=(const FloatComplexRowVector &a) const
Definition: fCRowVector.cc:53
FloatComplexRowVector & operator+=(const FloatRowVector &a)
Definition: fCRowVector.cc:245
FloatComplex max() const
Definition: fCRowVector.cc:347
FloatComplexRowVector & fill(float val)
Definition: fCRowVector.cc:100
FloatComplexRowVector & insert(const FloatRowVector &a, octave_idx_type c)
Definition: fCRowVector.cc:61
FloatComplexRowVector extract_n(octave_idx_type c1, octave_idx_type n) const
Definition: fCRowVector.cc:232
FloatComplexRowVector extract(octave_idx_type c1, octave_idx_type c2) const
Definition: fCRowVector.cc:217
FloatComplexRowVector & operator-=(const FloatRowVector &a)
Definition: fCRowVector.cc:264
bool operator==(const FloatComplexRowVector &a) const
Definition: fCRowVector.cc:44
FloatComplex min() const
Definition: fCRowVector.cc:327
MArray< T > hermitian(T(*fcn)(const T &)=nullptr) const
Definition: MArray.h:102
MArray< T > transpose() const
Definition: MArray.h:99
#define F77_CONST_CMPLX_ARG(x)
Definition: f77-fcn.h:313
#define F77_CMPLX_ARG(x)
Definition: f77-fcn.h:310
#define F77_XFCN(f, F, args)
Definition: f77-fcn.h:45
octave_f77_int_type F77_INT
Definition: f77-fcn.h:306
std::ostream & operator<<(std::ostream &os, const FloatComplexRowVector &a)
Definition: fCRowVector.cc:369
FloatComplexRowVector operator*(const FloatComplexRowVector &v, const FloatComplexMatrix &a)
Definition: fCRowVector.cc:285
FloatComplexRowVector linspace(const FloatComplex &x1, const FloatComplex &x2, octave_idx_type n_in)
Definition: fCRowVector.cc:430
std::istream & operator>>(std::istream &is, FloatComplexRowVector &a)
Definition: fCRowVector.cc:378
FloatComplexRowVector conj(const FloatComplexRowVector &a)
Definition: fCRowVector.cc:209
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
bool isinf(double x)
Definition: lo-mappers.h:203
bool isnan(bool)
Definition: lo-mappers.h:178
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
void mx_inline_sub2(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:128
void mx_inline_add2(std::size_t n, R *r, const X *x)
Definition: mx-inlines.cc:127
bool mx_inline_equal(std::size_t n, const T1 *x, const T2 *y)
Definition: mx-inlines.cc:577
octave_idx_type n
Definition: mx-inlines.cc:761
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
subroutine xcdotu(n, zx, incx, zy, incy, retval)
Definition: xcdotu.f:2
F77_RET_T F77_FUNC(xerbla, XERBLA)(F77_CONST_CHAR_ARG_DEF(s_arg
F77_RET_T len
Definition: xerbla.cc:61