GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
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