GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
lo-mappers.h
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 (octave_lo_mappers_h)
27 #define octave_lo_mappers_h 1
28 
29 #include "octave-config.h"
30 
31 #include <cmath>
32 
33 #include <limits>
34 
35 #include "lo-ieee.h"
36 #include "oct-cmplx.h"
37 #include "oct-inttypes-fwd.h"
38 
40 
42 
43 extern OCTAVE_API bool isna (double x);
44 extern OCTAVE_API bool isna (float x);
45 extern OCTAVE_API bool isna (const Complex& x);
46 extern OCTAVE_API bool isna (const FloatComplex& x);
47 
48 extern OCTAVE_API bool is_NaN_or_NA (const Complex& x);
49 extern OCTAVE_API bool is_NaN_or_NA (const FloatComplex& x);
50 
51 inline double copysign (double x, double y) { return std::copysign (x, y); }
52 inline float copysign (float x, float y) { return std::copysignf (x, y); }
53 
54 inline double signbit (double x) { return std::signbit (x); }
55 inline float signbit (float x) { return std::signbit (x); }
56 
57 // Test for negative sign.
58 extern OCTAVE_API bool negative_sign (double x);
59 extern OCTAVE_API bool negative_sign (float x);
60 
61 // Test for positive sign.
62 inline bool positive_sign (double x) { return ! negative_sign (x); }
63 inline bool positive_sign (float x) { return ! negative_sign (x); }
64 
65 extern OCTAVE_API Complex acos (const Complex& x);
66 extern OCTAVE_API FloatComplex acos (const FloatComplex& x);
67 
68 extern OCTAVE_API Complex asin (const Complex& x);
69 extern OCTAVE_API FloatComplex asin (const FloatComplex& x);
70 
71 inline Complex atan (const Complex& x) { return std::atan (x); }
72 inline FloatComplex atan (const FloatComplex& x) { return std::atan (x); }
73 
74 // The C++ standard would normally return a std::complex value for conj
75 // even when the input is fully real. Octave overrides this.
76 inline double conj (double x) { return x; }
77 inline float conj (float x) { return x; }
78 
79 template <typename T>
80 std::complex<T>
81 conj (const std::complex<T>& x)
82 {
83  return std::conj (x);
84 }
85 
86 inline double log2 (double x) { return std::log2 (x); }
87 inline float log2 (float x) { return std::log2f (x); }
88 
89 extern OCTAVE_API Complex log2 (const Complex& x);
90 extern OCTAVE_API FloatComplex log2 (const FloatComplex& x);
91 
92 extern OCTAVE_API double log2 (double x, int& exp);
93 extern OCTAVE_API float log2 (float x, int& exp);
94 
95 extern OCTAVE_API Complex log2 (const Complex& x, int& exp);
96 extern OCTAVE_API FloatComplex log2 (const FloatComplex& x, int& exp);
97 
98 inline double exp2 (double x) { return std::exp2 (x); }
99 inline float exp2 (float x) { return std::exp2f (x); }
100 
101 template <typename T>
102 std::complex<T>
103 ceil (const std::complex<T>& x)
104 {
105  return std::complex<T> (std::ceil (std::real (x)),
106  std::ceil (std::imag (x)));
107 }
108 
109 template <typename T>
110 std::complex<T>
111 trunc (const std::complex<T>& x)
112 {
113  return std::complex<T> (std::trunc (std::real (x)),
114  std::trunc (std::imag (x)));
115 }
116 
117 // Provide alias for trunc under the more familiar name of fix.
118 inline double fix (double x) { return std::trunc (x); }
119 inline float fix (float x) { return std::trunc (x); }
120 
121 template <typename T>
122 std::complex<T>
123 fix (const std::complex<T>& x)
124 {
125  return trunc (x);
126 }
127 
128 template <typename T>
129 std::complex<T>
130 floor (const std::complex<T>& x)
131 {
132  return std::complex<T> (std::floor (std::real (x)),
133  std::floor (std::imag (x)));
134 }
135 
136 inline double round (double x) { return std::round (x); }
137 inline float round (float x) { return std::roundf (x); }
138 
139 template <typename T>
140 std::complex<T>
141 round (const std::complex<T>& x)
142 {
143  return std::complex<T> (round (std::real (x)), round (std::imag (x)));
144 }
145 
146 inline double
147 roundb (double x)
148 {
149  double t = round (x);
150 
151  if (fabs (x - t) == 0.5)
152  t = 2 * std::trunc (0.5 * t);
153 
154  return t;
155 }
156 
157 inline float
158 roundb (float x)
159 {
160  float t = round (x);
161 
162  if (fabsf (x - t) == 0.5f)
163  t = 2 * std::trunc (0.5f * t);
164 
165  return t;
166 }
167 
168 template <typename T>
169 std::complex<T>
170 roundb (const std::complex<T>& x)
171 {
172  return std::complex<T> (roundb (std::real (x)), roundb (std::imag (x)));
173 }
174 
175 extern OCTAVE_API double frexp (double x, int *expptr);
176 extern OCTAVE_API float frexp (float x, int *expptr);
177 
178 inline bool isnan (bool) { return false; }
179 inline bool isnan (char) { return false; }
180 
181 inline bool isnan (double x) { return std::isnan (x); }
182 inline bool isnan (float x) { return std::isnan (x); }
183 
184 // FIXME: Do we need the isnan overload for complex?
185 template <typename T>
186 bool
187 isnan (const std::complex<T>& x)
188 {
189  return (isnan (std::real (x)) || isnan (std::imag (x)));
190 }
191 
192 inline bool isfinite (double x) { return std::isfinite (x); }
193 inline bool isfinite (float x) { return std::isfinite (x); }
194 
195 // FIXME: Do we need isfinite overload for complex?
196 template <typename T>
197 bool
198 isfinite (const std::complex<T>& x)
199 {
200  return (isfinite (std::real (x)) && isfinite (std::imag (x)));
201 }
202 
203 inline bool isinf (double x) { return std::isinf (x); }
204 inline bool isinf (float x) { return std::isinf (x); }
205 
206 template <typename T>
207 bool
209 {
210  return false;
211 }
212 
213 // FIXME: Do we need isinf overload for complex?
214 template <typename T>
215 bool
216 isinf (const std::complex<T>& x)
217 {
218  return (isinf (std::real (x)) || isinf (std::imag (x)));
219 }
220 
221 // Some useful tests, that are commonly repeated.
222 // Test for a finite integer.
223 
224 // FIXME: Benchmark whether trunc might be faster than round here.
225 inline bool isinteger (double x) { return isfinite (x) && x == round (x); }
226 inline bool isinteger (float x) { return isfinite (x) && x == round (x); }
227 
228 inline double
229 signum (double x)
230 {
231  double tmp = 0.0;
232 
233  if (x < 0.0)
234  tmp = -1.0;
235  else if (x > 0.0)
236  tmp = 1.0;
237 
238  return isnan (x) ? numeric_limits<double>::NaN () : tmp;
239 }
240 
241 inline float
242 signum (float x)
243 {
244  float tmp = 0.0f;
245 
246  if (x < 0.0f)
247  tmp = -1.0f;
248  else if (x > 0.0f)
249  tmp = 1.0f;
250 
251  return isnan (x) ? numeric_limits<float>::NaN () : tmp;
252 }
253 
254 template <typename T>
255 std::complex<T>
256 signum (const std::complex<T>& x)
257 {
258  T tmp = abs (x);
259 
260  return tmp == 0 ? 0.0 : x / tmp;
261 }
262 
263 // Convert X to the nearest integer value. Should not pass NaN to
264 // this function.
265 
266 // For integer types? Hmm. Need to be sure T is an integer type...
267 template <typename T>
268 T
270 {
271  return x;
272 }
273 
274 template <>
275 inline double x_nint (double x)
276 {
277  return (isfinite (x) ? std::floor (x + 0.5) : x);
278 }
279 
280 template <>
281 inline float x_nint (float x)
282 {
283  return (isfinite (x) ? std::floor (x + 0.5f) : x);
284 }
285 
286 extern OCTAVE_API octave_idx_type nint_big (double x);
287 extern OCTAVE_API octave_idx_type nint_big (float x);
288 
289 extern OCTAVE_API int nint (double x);
290 extern OCTAVE_API int nint (float x);
291 
292 template <typename T>
293 T
294 mod (T x, T y)
295 {
296  T retval;
297 
298  if (y == 0)
299  retval = x;
300  else
301  {
302  T q = x / y;
303 
304  if (x_nint (y) != y
305  && (std::abs ((q - x_nint (q)) / x_nint (q))
306  < std::numeric_limits<T>::epsilon ()))
307  retval = 0;
308  else
309  {
310  T n = std::floor (q);
311 
312  // Prevent use of extra precision.
313  volatile T tmp = y * n;
314 
315  retval = x - tmp;
316  }
317  }
318 
319  if (x != y && y != 0)
320  retval = copysign (retval, y);
321 
322  return retval;
323 }
324 
325 template <typename T>
326 T
327 rem (T x, T y)
328 {
329  T retval;
330 
331  if (y == 0)
332  retval = numeric_limits<T>::NaN ();
333  else
334  {
335  T q = x / y;
336 
337  if (x_nint (y) != y
338  && (std::abs ((q - x_nint (q)) / x_nint (q))
339  < std::numeric_limits<T>::epsilon ()))
340  retval = 0;
341  else
342  {
343  T n = std::trunc (q);
344 
345  // Prevent use of extra precision.
346  volatile T tmp = y * n;
347 
348  retval = x - tmp;
349  }
350  }
351 
352  if (x != y && y != 0)
353  retval = copysign (retval, x);
354 
355  return retval;
356 }
357 
358 // Generic min, max definitions
359 template <typename T>
360 T
361 min (T x, T y)
362 {
363  return x <= y ? x : y;
364 }
365 
366 template <typename T>
367 T
368 max (T x, T y)
369 {
370  return x >= y ? x : y;
371 }
372 
373 // This form is favorable. GCC will translate (x <= y ? x : y) without a
374 // jump, hence the only conditional jump involved will be the first
375 // (isnan), infrequent and hence friendly to branch prediction.
376 
377 inline double
378 min (double x, double y)
379 {
380  return isnan (y) ? x : (x <= y ? x : y);
381 }
382 
383 inline double
384 max (double x, double y)
385 {
386  return isnan (y) ? x : (x >= y ? x : y);
387 }
388 
389 inline float
390 min (float x, float y)
391 {
392  return isnan (y) ? x : (x <= y ? x : y);
393 }
394 
395 inline float
396 max (float x, float y)
397 {
398  return isnan (y) ? x : (x >= y ? x : y);
399 }
400 
401 inline std::complex<double>
402 min (const std::complex<double>& x, const std::complex<double>& y)
403 {
404  return abs (x) <= abs (y) ? x : (isnan (x) ? x : y);
405 }
406 
407 inline std::complex<float>
408 min (const std::complex<float>& x, const std::complex<float>& y)
409 {
410  return abs (x) <= abs (y) ? x : (isnan (x) ? x : y);
411 }
412 
413 inline std::complex<double>
414 max (const std::complex<double>& x, const std::complex<double>& y)
415 {
416  return abs (x) >= abs (y) ? x : (isnan (x) ? x : y);
417 }
418 
419 inline std::complex<float>
420 max (const std::complex<float>& x, const std::complex<float>& y)
421 {
422  return abs (x) >= abs (y) ? x : (isnan (x) ? x : y);
423 }
424 
425 template <typename T>
426 inline octave_int<T>
427 min (const octave_int<T>& x, const octave_int<T>& y)
428 {
429  return xmin (x, y);
430 }
431 
432 template <typename T>
433 inline octave_int<T>
434 max (const octave_int<T>& x, const octave_int<T>& y)
435 {
436  return xmax (x, y);
437 }
438 
439 // These map reals to Complex.
440 
441 extern OCTAVE_API Complex rc_acos (double);
442 extern OCTAVE_API FloatComplex rc_acos (float);
443 
444 extern OCTAVE_API Complex rc_acosh (double);
445 extern OCTAVE_API FloatComplex rc_acosh (float);
446 
447 extern OCTAVE_API Complex rc_asin (double);
448 extern OCTAVE_API FloatComplex rc_asin (float);
449 
450 extern OCTAVE_API Complex rc_atanh (double);
451 extern OCTAVE_API FloatComplex rc_atanh (float);
452 
453 extern OCTAVE_API Complex rc_log (double);
454 extern OCTAVE_API FloatComplex rc_log (float);
455 
456 extern OCTAVE_API Complex rc_log2 (double);
457 extern OCTAVE_API FloatComplex rc_log2 (float);
458 
459 extern OCTAVE_API Complex rc_log10 (double);
460 extern OCTAVE_API FloatComplex rc_log10 (float);
461 
462 extern OCTAVE_API Complex rc_sqrt (double);
463 extern OCTAVE_API FloatComplex rc_sqrt (float);
464 
465 OCTAVE_END_NAMESPACE(math)
466 OCTAVE_END_NAMESPACE(octave)
467 
468 #endif
#define NaN
Definition: Faddeeva.cc:261
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:137
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:143
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
Complex atan(const Complex &x)
Definition: lo-mappers.h:71
bool is_NaN_or_NA(const Complex &x)
Definition: lo-mappers.cc:71
double roundb(double x)
Definition: lo-mappers.h:147
bool isfinite(double x)
Definition: lo-mappers.h:192
bool isinteger(double x)
Definition: lo-mappers.h:225
double log2(double x)
Definition: lo-mappers.h:86
T max(T x, T y)
Definition: lo-mappers.h:368
Complex rc_acosh(double)
Definition: lo-mappers.cc:253
bool isinf(double x)
Definition: lo-mappers.h:203
double signbit(double x)
Definition: lo-mappers.h:54
T mod(T x, T y)
Definition: lo-mappers.h:294
Complex asin(const Complex &x)
Definition: lo-mappers.cc:107
Complex rc_asin(double)
Definition: lo-mappers.cc:265
Complex rc_log2(double)
Definition: lo-mappers.cc:304
bool positive_sign(double x)
Definition: lo-mappers.h:62
octave_idx_type nint_big(double x)
Definition: lo-mappers.cc:188
Complex rc_log10(double)
Definition: lo-mappers.cc:319
Complex rc_sqrt(double)
Definition: lo-mappers.cc:334
T rem(T x, T y)
Definition: lo-mappers.h:327
int nint(double x)
Definition: lo-mappers.cc:216
double signum(double x)
Definition: lo-mappers.h:229
double round(double x)
Definition: lo-mappers.h:136
Complex rc_log(double)
Definition: lo-mappers.cc:291
double exp2(double x)
Definition: lo-mappers.h:98
std::complex< T > trunc(const std::complex< T > &x)
Definition: lo-mappers.h:111
bool negative_sign(double x)
Definition: lo-mappers.cc:181
bool isnan(bool)
Definition: lo-mappers.h:178
bool isna(double x)
Definition: lo-mappers.cc:47
Complex rc_acos(double)
Definition: lo-mappers.cc:240
Complex rc_atanh(double)
Definition: lo-mappers.cc:278
double conj(double x)
Definition: lo-mappers.h:76
std::complex< T > floor(const std::complex< T > &x)
Definition: lo-mappers.h:130
double copysign(double x, double y)
Definition: lo-mappers.h:51
std::complex< T > ceil(const std::complex< T > &x)
Definition: lo-mappers.h:103
T min(T x, T y)
Definition: lo-mappers.h:361
double fix(double x)
Definition: lo-mappers.h:118
Complex acos(const Complex &x)
Definition: lo-mappers.cc:85
T x_nint(T x)
Definition: lo-mappers.h:269
double frexp(double x, int *expptr)
Definition: lo-mappers.cc:129
F77_RET_T const F77_DBLE * x
#define OCTAVE_API
Definition: main.cc:55
octave_idx_type n
Definition: mx-inlines.cc:761
std::complex< double > Complex
Definition: oct-cmplx.h:33
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
octave_int< T > xmin(const octave_int< T > &x, const octave_int< T > &y)
octave_int< T > xmax(const octave_int< T > &x, const octave_int< T > &y)
template int8_t abs(int8_t)