GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
lo-mappers.h
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2025 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
43extern OCTAVE_API bool isna (double x);
44extern OCTAVE_API bool isna (float x);
45extern OCTAVE_API bool isna (const Complex& x);
46extern OCTAVE_API bool isna (const FloatComplex& x);
47
48extern OCTAVE_API bool is_NaN_or_NA (const Complex& x);
49extern OCTAVE_API bool is_NaN_or_NA (const FloatComplex& x);
50
51inline double copysign (double x, double y) { return std::copysign (x, y); }
52inline float copysign (float x, float y) { return std::copysignf (x, y); }
53
54inline double signbit (double x) { return std::signbit (x); }
55inline float signbit (float x) { return std::signbit (x); }
56
57// Test for negative sign.
58extern OCTAVE_API bool negative_sign (double x);
59extern OCTAVE_API bool negative_sign (float x);
60
61// Test for positive sign.
62inline bool positive_sign (double x) { return ! negative_sign (x); }
63inline bool positive_sign (float x) { return ! negative_sign (x); }
64
65extern OCTAVE_API Complex acos (const Complex& x);
67
68extern OCTAVE_API Complex asin (const Complex& x);
70
71inline Complex atan (const Complex& x) { return std::atan (x); }
72inline 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.
76inline double conj (double x) { return x; }
77inline float conj (float x) { return x; }
78
79template <typename T>
80std::complex<T>
81conj (const std::complex<T>& x)
82{
83 return std::conj (x);
84}
85
86inline double log2 (double x) { return std::log2 (x); }
87inline float log2 (float x) { return std::log2f (x); }
88
89extern OCTAVE_API Complex log2 (const Complex& x);
91
92extern OCTAVE_API double log2 (double x, int& exp);
93extern OCTAVE_API float log2 (float x, int& exp);
94
95extern OCTAVE_API Complex log2 (const Complex& x, int& exp);
96extern OCTAVE_API FloatComplex log2 (const FloatComplex& x, int& exp);
97
98inline double exp2 (double x) { return std::exp2 (x); }
99inline float exp2 (float x) { return std::exp2f (x); }
100
101template <typename T>
102std::complex<T>
103ceil (const std::complex<T>& x)
104{
105 return std::complex<T> (std::ceil (std::real (x)),
106 std::ceil (std::imag (x)));
107}
108
109template <typename T>
110std::complex<T>
111trunc (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.
118inline double fix (double x) { return std::trunc (x); }
119inline float fix (float x) { return std::trunc (x); }
120
121template <typename T>
122std::complex<T>
123fix (const std::complex<T>& x)
124{
125 return trunc (x);
126}
127
128template <typename T>
129std::complex<T>
130floor (const std::complex<T>& x)
131{
132 return std::complex<T> (std::floor (std::real (x)),
133 std::floor (std::imag (x)));
134}
135
136inline double round (double x) { return std::round (x); }
137inline float round (float x) { return std::roundf (x); }
138
139template <typename T>
140std::complex<T>
141round (const std::complex<T>& x)
142{
143 return std::complex<T> (round (std::real (x)), round (std::imag (x)));
144}
145
146inline double
147roundb (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
157inline float
158roundb (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
168template <typename T>
169std::complex<T>
170roundb (const std::complex<T>& x)
171{
172 return std::complex<T> (roundb (std::real (x)), roundb (std::imag (x)));
173}
174
175extern OCTAVE_API double frexp (double x, int *expptr);
176extern OCTAVE_API float frexp (float x, int *expptr);
177
178inline bool isnan (bool) { return false; }
179inline bool isnan (char) { return false; }
180
181inline bool isnan (double x) { return std::isnan (x); }
182inline bool isnan (float x) { return std::isnan (x); }
183
184// FIXME: Do we need the isnan overload for complex?
185template <typename T>
186bool
187isnan (const std::complex<T>& x)
188{
189 return (isnan (std::real (x)) || isnan (std::imag (x)));
190}
191
192inline bool isfinite (double x) { return std::isfinite (x); }
193inline bool isfinite (float x) { return std::isfinite (x); }
194
195// FIXME: Do we need isfinite overload for complex?
196template <typename T>
197bool
198isfinite (const std::complex<T>& x)
199{
200 return (isfinite (std::real (x)) && isfinite (std::imag (x)));
201}
202
203inline bool isinf (double x) { return std::isinf (x); }
204inline bool isinf (float x) { return std::isinf (x); }
205
206template <typename T>
207bool
209{
210 return false;
211}
212
213// FIXME: Do we need isinf overload for complex?
214template <typename T>
215bool
216isinf (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.
225inline bool isinteger (double x) { return isfinite (x) && x == round (x); }
226inline bool isinteger (float x) { return isfinite (x) && x == round (x); }
227
228inline double
229signum (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
241inline float
242signum (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
254template <typename T>
255std::complex<T>
256signum (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...
267template <typename T>
268T
270{
271 return x;
272}
273
274template <>
275inline double x_nint (double x)
276{
277 return (isfinite (x) ? std::floor (x + 0.5) : x);
278}
279
280template <>
281inline float x_nint (float x)
282{
283 return (isfinite (x) ? std::floor (x + 0.5f) : x);
284}
285
286extern OCTAVE_API octave_idx_type nint_big (double x);
287extern OCTAVE_API octave_idx_type nint_big (float x);
288
289extern OCTAVE_API int nint (double x);
290extern OCTAVE_API int nint (float x);
291
292template <typename T>
293T
294mod (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 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
325template <typename T>
326T
327rem (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 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
359template <typename T>
360T
361min (T x, T y)
362{
363 return x <= y ? x : y;
364}
365
366template <typename T>
367T
368max (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
377inline double
378min (double x, double y)
379{
380 return isnan (y) ? x : (x <= y ? x : y);
381}
382
383inline double
384max (double x, double y)
385{
386 return isnan (y) ? x : (x >= y ? x : y);
387}
388
389inline float
390min (float x, float y)
391{
392 return isnan (y) ? x : (x <= y ? x : y);
393}
394
395inline float
396max (float x, float y)
397{
398 return isnan (y) ? x : (x >= y ? x : y);
399}
400
401inline std::complex<double>
402min (const std::complex<double>& x, const std::complex<double>& y)
403{
404 return abs (x) <= abs (y) ? x : (isnan (x) ? x : y);
405}
406
407inline std::complex<float>
408min (const std::complex<float>& x, const std::complex<float>& y)
409{
410 return abs (x) <= abs (y) ? x : (isnan (x) ? x : y);
411}
412
413inline std::complex<double>
414max (const std::complex<double>& x, const std::complex<double>& y)
415{
416 return abs (x) >= abs (y) ? x : (isnan (x) ? x : y);
417}
418
419inline std::complex<float>
420max (const std::complex<float>& x, const std::complex<float>& y)
421{
422 return abs (x) >= abs (y) ? x : (isnan (x) ? x : y);
423}
424
425template <typename T>
426inline octave_int<T>
428{
429 return xmin (x, y);
430}
431
432template <typename T>
433inline octave_int<T>
435{
436 return xmax (x, y);
437}
438
439// These map reals to Complex.
440
441extern OCTAVE_API Complex rc_acos (double);
442extern OCTAVE_API FloatComplex rc_acos (float);
443
444extern OCTAVE_API Complex rc_acosh (double);
445extern OCTAVE_API FloatComplex rc_acosh (float);
446
447extern OCTAVE_API Complex rc_asin (double);
448extern OCTAVE_API FloatComplex rc_asin (float);
449
450extern OCTAVE_API Complex rc_atanh (double);
451extern OCTAVE_API FloatComplex rc_atanh (float);
452
453extern OCTAVE_API Complex rc_log (double);
454extern OCTAVE_API FloatComplex rc_log (float);
455
456extern OCTAVE_API Complex rc_log2 (double);
457extern OCTAVE_API FloatComplex rc_log2 (float);
458
459extern OCTAVE_API Complex rc_log10 (double);
460extern OCTAVE_API FloatComplex rc_log10 (float);
461
462extern OCTAVE_API Complex rc_sqrt (double);
463extern OCTAVE_API FloatComplex rc_sqrt (float);
464
465OCTAVE_END_NAMESPACE(math)
466OCTAVE_END_NAMESPACE(octave)
467
468#endif
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
std::complex< T > ceil(const std::complex< T > &x)
Definition lo-mappers.h:103
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
std::complex< T > floor(const std::complex< T > &x)
Definition lo-mappers.h:130
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)
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)
Complex rc_asin(double)
Complex rc_log2(double)
bool positive_sign(double x)
Definition lo-mappers.h:62
octave_idx_type nint_big(double x)
Complex rc_log10(double)
Complex rc_sqrt(double)
T rem(T x, T y)
Definition lo-mappers.h:327
int nint(double x)
double signum(double x)
Definition lo-mappers.h:229
double round(double x)
Definition lo-mappers.h:136
Complex rc_log(double)
double exp2(double x)
Definition lo-mappers.h:98
bool negative_sign(double x)
bool isnan(bool)
Definition lo-mappers.h:178
bool isna(double x)
Definition lo-mappers.cc:47
Complex rc_acos(double)
Complex rc_atanh(double)
double conj(double x)
Definition lo-mappers.h:76
double copysign(double x, double y)
Definition lo-mappers.h:51
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
std::complex< T > trunc(const std::complex< T > &x)
Definition lo-mappers.h:111
T x_nint(T x)
Definition lo-mappers.h:269
double frexp(double x, int *expptr)
F77_RET_T const F77_DBLE * x
#define OCTAVE_API
Definition main.in.cc:55
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)