GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
lo-mappers.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2015 John W. Eaton
4 Copyright (C) 2010 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <cfloat>
29 
30 #include "lo-error.h"
31 #include "lo-ieee.h"
32 #include "lo-mappers.h"
33 #include "lo-math.h"
34 #include "lo-specfun.h"
35 #include "lo-utils.h"
36 #include "oct-cmplx.h"
37 
38 #include "f77-fcn.h"
39 
40 // double -> double mappers.
41 
42 // Both xtrunc and xround belong here so we can keep gnulib:: out of
43 // lo-mappers.h.
44 
45 double
46 xtrunc (double x)
47 {
48  return gnulib::trunc (x);
49 }
50 
51 double
52 xcopysign (double x, double y)
53 {
54  return gnulib::copysign (x, y);
55 }
56 
57 double xfloor (double x)
58 {
59  return gnulib::floor (x);
60 }
61 
62 double
63 xround (double x)
64 {
65  return gnulib::round (x);
66 }
67 
68 double
69 xroundb (double x)
70 {
71  double t = xround (x);
72 
73  if (fabs (x - t) == 0.5)
74  t = 2 * xtrunc (0.5 * t);
75 
76  return t;
77 }
78 
79 double
80 signum (double x)
81 {
82  double tmp = 0.0;
83 
84  if (x < 0.0)
85  tmp = -1.0;
86  else if (x > 0.0)
87  tmp = 1.0;
88 
89  return xisnan (x) ? octave_NaN : tmp;
90 }
91 
92 double
93 xlog2 (double x)
94 {
95  return gnulib::log2 (x);
96 }
97 
98 Complex
99 xlog2 (const Complex& x)
100 {
101 #if defined (M_LN2)
102  static double ln2 = M_LN2;
103 #else
104  static double ln2 = gnulib::log (2);
105 #endif
106 
107  return std::log (x) / ln2;
108 }
109 
110 double
111 xexp2 (double x)
112 {
113 #if defined (HAVE_EXP2)
114  return exp2 (x);
115 #else
116 #if defined (M_LN2)
117  static double ln2 = M_LN2;
118 #else
119  static double ln2 = gnulib::log (2);
120 #endif
121 
122  return exp (x * ln2);
123 #endif
124 }
125 
126 double
127 xlog2 (double x, int& exp)
128 {
129  return gnulib::frexp (x, &exp);
130 }
131 
132 Complex
133 xlog2 (const Complex& x, int& exp)
134 {
135  double ax = std::abs (x);
136  double lax = xlog2 (ax, exp);
137  return (ax != lax) ? (x / ax) * lax : x;
138 }
139 
140 // double -> bool mappers.
141 
142 #if ! defined(HAVE_CMATH_ISNAN)
143 bool
144 xisnan (double x)
145 {
146  return lo_ieee_isnan (x);
147 }
148 #endif
149 
150 #if ! defined(HAVE_CMATH_ISFINITE)
151 bool
152 xfinite (double x)
153 {
154  return lo_ieee_finite (x);
155 }
156 #endif
157 
158 #if ! defined(HAVE_CMATH_ISINF)
159 bool
160 xisinf (double x)
161 {
162  return lo_ieee_isinf (x);
163 }
164 #endif
165 
166 bool
167 octave_is_NA (double x)
168 {
169  return lo_ieee_is_NA (x);
170 }
171 
172 // (double, double) -> double mappers.
173 
174 // complex -> complex mappers.
175 
176 Complex
177 acos (const Complex& x)
178 {
179  static Complex i (0, 1);
180 
181  Complex tmp;
182 
183  if (imag (x) == 0.0)
184  {
185  // If the imaginary part of X is 0, then avoid generating an
186  // imaginary part of -0 for the expression 1-x*x.
187  // This effectively chooses the same phase of the branch cut as Matlab.
188  double xr = real (x);
189  tmp = Complex (1.0 - xr*xr);
190  }
191  else
192  tmp = 1.0 - x*x;
193 
194  return -i * log (x + i * sqrt (tmp));
195 }
196 
197 Complex
198 acosh (const Complex& x)
199 {
200  return log (x + sqrt (x + 1.0) * sqrt (x - 1.0));
201 }
202 
203 Complex
204 asin (const Complex& x)
205 {
206  static Complex i (0, 1);
207 
208  Complex tmp;
209 
210  if (imag (x) == 0.0)
211  {
212  // If the imaginary part of X is 0, then avoid generating an
213  // imaginary part of -0 for the expression 1-x*x.
214  // This effectively chooses the same phase of the branch cut as Matlab.
215  double xr = real (x);
216  tmp = Complex (1.0 - xr*xr);
217  }
218  else
219  tmp = 1.0 - x*x;
220 
221  return -i * log (i*x + sqrt (tmp));
222 }
223 
224 Complex
225 asinh (const Complex& x)
226 {
227  return log (x + sqrt (x*x + 1.0));
228 }
229 
230 Complex
231 atan (const Complex& x)
232 {
233  static Complex i (0, 1);
234 
235  return i * log ((i + x) / (i - x)) / 2.0;
236 }
237 
238 Complex
239 atanh (const Complex& x)
240 {
241  return log ((1.0 + x) / (1.0 - x)) / 2.0;
242 }
243 
244 // complex -> bool mappers.
245 
246 bool
248 {
249  return (octave_is_NA (real (x)) || octave_is_NA (imag (x)));
250 }
251 
252 bool
254 {
255  return (xisnan (real (x)) || xisnan (imag (x)));
256 }
257 
258 // (complex, complex) -> complex mappers.
259 
260 // FIXME: need to handle NA too?
261 
262 Complex
263 xmin (const Complex& x, const Complex& y)
264 {
265  return abs (x) <= abs (y) ? x : (xisnan (x) ? x : y);
266 }
267 
268 Complex
269 xmax (const Complex& x, const Complex& y)
270 {
271  return abs (x) >= abs (y) ? x : (xisnan (x) ? x : y);
272 }
273 
274 
275 // float -> float mappers.
276 
277 // Both xtrunc and xround belong here so we can keep gnulib:: out of
278 // lo-mappers.h.
279 
280 float
281 xtrunc (float x)
282 {
283  return gnulib::truncf (x);
284 }
285 
286 float
287 xcopysign (float x, float y)
288 {
289  return gnulib::copysignf (x, y);
290 }
291 
292 float xfloor (float x)
293 {
294  return gnulib::floorf (x);
295 }
296 
297 float
298 xround (float x)
299 {
300  return gnulib::roundf (x);
301 }
302 
303 float
304 xroundb (float x)
305 {
306  float t = xround (x);
307 
308  if (fabsf (x - t) == 0.5)
309  t = 2 * xtrunc (0.5 * t);
310 
311  return t;
312 }
313 
314 float
315 signum (float x)
316 {
317  float tmp = 0.0;
318 
319  if (x < 0.0)
320  tmp = -1.0;
321  else if (x > 0.0)
322  tmp = 1.0;
323 
324  return xisnan (x) ? octave_Float_NaN : tmp;
325 }
326 
327 float
328 xlog2 (float x)
329 {
330  return gnulib::log2f (x);
331 }
332 
335 {
336 #if defined (M_LN2)
337  static float ln2 = M_LN2;
338 #else
339  static float ln2 = log (2);
340 #endif
341 
342  return std::log (x) / ln2;
343 }
344 
345 float
346 xexp2 (float x)
347 {
348 #if defined (HAVE_EXP2F)
349  return exp2f (x);
350 #elif defined (HAVE_EXP2)
351  return exp2 (x);
352 #else
353 #if defined (M_LN2)
354  static float ln2 = M_LN2;
355 #else
356  static float ln2 = log2 (2);
357 #endif
358 
359  return exp (x * ln2);
360 #endif
361 }
362 
363 float
364 xlog2 (float x, int& exp)
365 {
366  return gnulib::frexpf (x, &exp);
367 }
368 
370 xlog2 (const FloatComplex& x, int& exp)
371 {
372  float ax = std::abs (x);
373  float lax = xlog2 (ax, exp);
374  return (ax != lax) ? (x / ax) * lax : x;
375 }
376 
377 // float -> bool mappers.
378 
379 #if ! defined(HAVE_CMATH_ISNANF)
380 bool
381 xisnan (float x)
382 {
383  return lo_ieee_isnan (x);
384 }
385 #endif
386 
387 #if ! defined(HAVE_CMATH_ISFINITEF)
388 bool
389 xfinite (float x)
390 {
391  return lo_ieee_finite (x);
392 }
393 #endif
394 
395 #if ! defined(HAVE_CMATH_ISINFF)
396 bool
397 xisinf (float x)
398 {
399  return lo_ieee_isinf (x);
400 }
401 #endif
402 
403 bool
405 {
406  return lo_ieee_is_NA (x);
407 }
408 
409 // (float, float) -> float mappers.
410 
411 // complex -> complex mappers.
412 
415 {
416  static FloatComplex i (0, 1);
417 
418  FloatComplex tmp;
419 
420  if (imag (x) == 0.0f)
421  {
422  // If the imaginary part of X is 0, then avoid generating an
423  // imaginary part of -0 for the expression 1-x*x.
424  // This effectively chooses the same phase of the branch cut as Matlab.
425  float xr = real (x);
426  tmp = FloatComplex (1.0f - xr*xr);
427  }
428  else
429  tmp = 1.0f - x*x;
430 
431  return -i * log (x + i * sqrt (tmp));
432 }
433 
436 {
437  return log (x + sqrt (x + 1.0f) * sqrt (x - 1.0f));
438 }
439 
442 {
443  static FloatComplex i (0, 1);
444 
445  FloatComplex tmp;
446 
447  if (imag (x) == 0.0f)
448  {
449  // If the imaginary part of X is 0, then avoid generating an
450  // imaginary part of -0 for the expression 1-x*x.
451  // This effectively chooses the same phase of the branch cut as Matlab.
452  float xr = real (x);
453  tmp = FloatComplex (1.0f - xr*xr);
454  }
455  else
456  tmp = 1.0f - x*x;
457 
458  return -i * log (i*x + sqrt (tmp));
459 }
460 
463 {
464  return log (x + sqrt (x*x + 1.0f));
465 }
466 
469 {
470  static FloatComplex i (0, 1);
471 
472  return i * log ((i + x) / (i - x)) / 2.0f;
473 }
474 
477 {
478  return log ((1.0f + x) / (1.0f - x)) / 2.0f;
479 }
480 
481 // complex -> bool mappers.
482 
483 bool
485 {
486  return (octave_is_NA (real (x)) || octave_is_NA (imag (x)));
487 }
488 
489 bool
491 {
492  return (xisnan (real (x)) || xisnan (imag (x)));
493 }
494 
495 // (complex, complex) -> complex mappers.
496 
497 // FIXME: need to handle NA too?
498 
500 xmin (const FloatComplex& x, const FloatComplex& y)
501 {
502  return abs (x) <= abs (y) ? x : (xisnan (x) ? x : y);
503 }
504 
506 xmax (const FloatComplex& x, const FloatComplex& y)
507 {
508  return abs (x) >= abs (y) ? x : (xisnan (x) ? x : y);
509 }
510 
511 Complex
512 rc_acos (double x)
513 {
514  return fabs (x) > 1.0 ? acos (Complex (x)) : Complex (acos (x));
515 }
516 
518 rc_acos (float x)
519 {
520  return fabsf (x) > 1.0f ? acos (FloatComplex (x)) : FloatComplex (acosf (x));
521 }
522 
523 Complex
524 rc_acosh (double x)
525 {
526  return x < 1.0 ? acosh (Complex (x)) : Complex (acosh (x));
527 }
528 
530 rc_acosh (float x)
531 {
532  return x < 1.0f ? acosh (FloatComplex (x)) : FloatComplex (acoshf (x));
533 }
534 
535 Complex
536 rc_asin (double x)
537 {
538  return fabs (x) > 1.0 ? asin (Complex (x)) : Complex (asin (x));
539 }
540 
542 rc_asin (float x)
543 {
544  return fabsf (x) > 1.0f ? asin (FloatComplex (x)) : FloatComplex (asinf (x));
545 }
546 
547 Complex
548 rc_atanh (double x)
549 {
550  return fabs (x) > 1.0 ? atanh (Complex (x)) : Complex (atanh (x));
551 }
552 
554 rc_atanh (float x)
555 {
556  return fabsf (x) > 1.0f ? atanh (FloatComplex (x))
557  : FloatComplex (atanhf (x));
558 }
559 
560 Complex
561 rc_log (double x)
562 {
563  const double pi = 3.14159265358979323846;
564  return x < 0.0 ? Complex (gnulib::log (-x), pi) : Complex (gnulib::log (x));
565 }
566 
568 rc_log (float x)
569 {
570  const float pi = 3.14159265358979323846f;
571  return (x < 0.0f
572  ? FloatComplex (gnulib::logf (-x), pi)
573  : FloatComplex (gnulib::logf (x)));
574 }
575 
576 Complex
577 rc_log2 (double x)
578 {
579  const double pil2 = 4.53236014182719380962; // = pi / log(2)
580  return x < 0.0 ? Complex (xlog2 (-x), pil2) : Complex (xlog2 (x));
581 }
582 
584 rc_log2 (float x)
585 {
586  const float pil2 = 4.53236014182719380962f; // = pi / log(2)
587  return x < 0.0f ? FloatComplex (xlog2 (-x), pil2) : FloatComplex (xlog2 (x));
588 }
589 
590 Complex
591 rc_log10 (double x)
592 {
593  const double pil10 = 1.36437635384184134748; // = pi / log(10)
594  return x < 0.0 ? Complex (log10 (-x), pil10) : Complex (log10 (x));
595 }
596 
598 rc_log10 (float x)
599 {
600  const float pil10 = 1.36437635384184134748f; // = pi / log(10)
601  return x < 0.0f ? FloatComplex (log10 (-x), pil10)
602  : FloatComplex (log10f (x));
603 }
604 
605 Complex
606 rc_sqrt (double x)
607 {
608  return x < 0.0 ? Complex (0.0, sqrt (-x)) : Complex (sqrt (x));
609 }
610 
612 rc_sqrt (float x)
613 {
614  return x < 0.0f ? FloatComplex (0.0f, sqrtf (-x)) : FloatComplex (sqrtf (x));
615 }
616 
617 bool
619 {
620  return __lo_ieee_signbit (x);
621 }
622 
623 bool
625 {
626  return __lo_ieee_float_signbit (x);
627 }
628 
629 // Convert X to the nearest integer value. Should not pass NaN to
630 // this function.
631 
632 // Sometimes you need a large integer, but not always.
633 
635 NINTbig (double x)
636 {
641  else
642  return static_cast<octave_idx_type> ((x > 0) ? (x + 0.5) : (x - 0.5));
643 }
644 
646 NINTbig (float x)
647 {
652  else
653  return static_cast<octave_idx_type> ((x > 0) ? (x + 0.5) : (x - 0.5));
654 }
655 
656 int
657 NINT (double x)
658 {
661  else if (x < std::numeric_limits<int>::min ())
663  else
664  return static_cast<int> ((x > 0) ? (x + 0.5) : (x - 0.5));
665 }
666 
667 int
668 NINT (float x)
669 {
672  else if (x < std::numeric_limits<int>::min ())
674  else
675  return static_cast<int> ((x > 0) ? (x + 0.5) : (x - 0.5));
676 }
Complex rc_asin(double x)
Definition: lo-mappers.cc:536
int __lo_ieee_signbit(double x)
Definition: lo-ieee.cc:134
#define lo_ieee_is_NA(x)
Definition: lo-ieee.h:109
Complex asinh(const Complex &x)
Definition: lo-mappers.cc:225
double xround(double x)
Definition: lo-mappers.cc:63
int __lo_ieee_float_signbit(float x)
Definition: lo-ieee.cc:210
bool xisnan(double x)
Definition: lo-mappers.cc:144
double xexp2(double x)
Definition: lo-mappers.cc:111
double xtrunc(double x)
Definition: lo-mappers.cc:46
Complex rc_acos(double x)
Definition: lo-mappers.cc:512
Complex xmax(const Complex &x, const Complex &y)
Definition: lo-mappers.cc:269
bool xnegative_sign(double x)
Definition: lo-mappers.cc:618
#define lo_ieee_finite(x)
Definition: lo-ieee.h:103
bool xisinf(double x)
Definition: lo-mappers.cc:160
Complex xmin(const Complex &x, const Complex &y)
Definition: lo-mappers.cc:263
#define lo_ieee_isinf(x)
Definition: lo-ieee.h:105
#define octave_Float_NaN
Definition: lo-ieee.h:46
double xlog2(double x)
Definition: lo-mappers.cc:93
Complex acosh(const Complex &x)
Definition: lo-mappers.cc:198
#define lo_ieee_isnan(x)
Definition: lo-ieee.h:101
double signum(double x)
Definition: lo-mappers.cc:80
F77_RET_T const double const double * f
Complex atanh(const Complex &x)
Definition: lo-mappers.cc:239
Complex rc_sqrt(double x)
Definition: lo-mappers.cc:606
bool octave_is_NaN_or_NA(const Complex &x)
Definition: lo-mappers.cc:253
Complex rc_log(double x)
Definition: lo-mappers.cc:561
Complex rc_log2(double x)
Definition: lo-mappers.cc:577
double xroundb(double x)
Definition: lo-mappers.cc:69
Complex rc_atanh(double x)
Definition: lo-mappers.cc:548
int NINT(double x)
Definition: lo-mappers.cc:657
Complex rc_log10(double x)
Definition: lo-mappers.cc:591
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:233
bool xfinite(double x)
Definition: lo-mappers.cc:152
Complex rc_acosh(double x)
Definition: lo-mappers.cc:524
#define octave_NaN
Definition: lo-ieee.h:37
Complex asin(const Complex &x)
Definition: lo-mappers.cc:204
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:162
std::complex< float > FloatComplex
Definition: oct-cmplx.h:30
float acoshf(float x)
Definition: lo-specfun.cc:200
std::complex< T > floor(const std::complex< T > &x)
Definition: lo-mappers.h:282
double xcopysign(double x, double y)
Definition: lo-mappers.cc:52
std::complex< double > Complex
Definition: oct-cmplx.h:29
octave_idx_type NINTbig(double x)
Definition: lo-mappers.cc:635
Complex acos(const Complex &x)
Definition: lo-mappers.cc:177
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:156
double xfloor(double x)
Definition: lo-mappers.cc:57
T abs(T x)
Definition: pr-output.cc:3062
Complex atan(const Complex &x)
Definition: lo-mappers.cc:231
float atanhf(float x)
Definition: lo-specfun.cc:240
F77_RET_T const double * x
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:210
bool octave_is_NA(double x)
Definition: lo-mappers.cc:167