lo-mappers.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 Copyright (C) 2010 VZLU Prague
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include <cfloat>
00029 
00030 #include "lo-error.h"
00031 #include "lo-ieee.h"
00032 #include "lo-mappers.h"
00033 #include "lo-math.h"
00034 #include "lo-specfun.h"
00035 #include "lo-utils.h"
00036 #include "oct-cmplx.h"
00037 
00038 #include "f77-fcn.h"
00039 
00040 // double -> double mappers.
00041 
00042 // Both xtrunc and xround belong here so we can keep gnulib:: out of
00043 // lo-mappers.h.
00044 
00045 double
00046 xtrunc (double x)
00047 {
00048   return gnulib::trunc (x);
00049 }
00050 
00051 double
00052 xcopysign (double x, double y)
00053 {
00054   return gnulib::copysign (x, y);
00055 }
00056 
00057 double xfloor (double x)
00058 {
00059   return gnulib::floor (x);
00060 }
00061 
00062 double
00063 xround (double x)
00064 {
00065   return gnulib::round (x);
00066 }
00067 
00068 double
00069 xroundb (double x)
00070 {
00071   double t = xround (x);
00072 
00073   if (fabs (x - t) == 0.5)
00074     t = 2 * xtrunc (0.5 * t);
00075 
00076   return t;
00077 }
00078 
00079 double
00080 signum (double x)
00081 {
00082   double tmp = 0.0;
00083 
00084   if (x < 0.0)
00085     tmp = -1.0;
00086   else if (x > 0.0)
00087     tmp = 1.0;
00088 
00089   return xisnan (x) ? octave_NaN : tmp;
00090 }
00091 
00092 double
00093 xlog2 (double x)
00094 {
00095 #if defined (HAVE_LOG2)
00096   return log2 (x);
00097 #else
00098 #if defined (M_LN2)
00099   static double ln2 = M_LN2;
00100 #else
00101   static double ln2 = log (2);
00102 #endif
00103 
00104   return log (x) / ln2;
00105 #endif
00106 }
00107 
00108 Complex
00109 xlog2 (const Complex& x)
00110 {
00111 #if defined (M_LN2)
00112   static double ln2 = M_LN2;
00113 #else
00114   static double ln2 = log (2);
00115 #endif
00116 
00117   return std::log (x) / ln2;
00118 }
00119 
00120 double
00121 xexp2 (double x)
00122 {
00123 #if defined (HAVE_EXP2)
00124   return exp2 (x);
00125 #else
00126 #if defined (M_LN2)
00127   static double ln2 = M_LN2;
00128 #else
00129   static double ln2 = log (2);
00130 #endif
00131 
00132   return exp (x * ln2);
00133 #endif
00134 }
00135 
00136 double
00137 xlog2 (double x, int& exp)
00138 {
00139   return frexp (x, &exp);
00140 }
00141 
00142 Complex
00143 xlog2 (const Complex& x, int& exp)
00144 {
00145   double ax = std::abs (x);
00146   double lax = xlog2 (ax, exp);
00147   return (ax != lax) ? (x / ax) * lax : x;
00148 }
00149 
00150 // double -> bool mappers.
00151 
00152 #if ! defined(HAVE_CMATH_ISNAN)
00153 bool
00154 xisnan (double x)
00155 {
00156   return lo_ieee_isnan (x);
00157 }
00158 #endif
00159 
00160 #if ! defined(HAVE_CMATH_ISFINITE)
00161 bool
00162 xfinite (double x)
00163 {
00164   return lo_ieee_finite (x);
00165 }
00166 #endif
00167 
00168 #if ! defined(HAVE_CMATH_ISINF)
00169 bool
00170 xisinf (double x)
00171 {
00172   return lo_ieee_isinf (x);
00173 }
00174 #endif
00175 
00176 bool
00177 octave_is_NA (double x)
00178 {
00179   return lo_ieee_is_NA (x);
00180 }
00181 
00182 bool
00183 octave_is_NaN_or_NA (double x)
00184 {
00185   return lo_ieee_isnan (x);
00186 }
00187 
00188 // (double, double) -> double mappers.
00189 
00190 // complex -> complex mappers.
00191 
00192 Complex
00193 acos (const Complex& x)
00194 {
00195   static Complex i (0, 1);
00196 
00197   return -i * (log (x + i * (sqrt (1.0 - x*x))));
00198 }
00199 
00200 Complex
00201 acosh (const Complex& x)
00202 {
00203   return log (x + sqrt (x*x - 1.0));
00204 }
00205 
00206 Complex
00207 asin (const Complex& x)
00208 {
00209   static Complex i (0, 1);
00210 
00211   return -i * log (i*x + sqrt (1.0 - x*x));
00212 }
00213 
00214 Complex
00215 asinh (const Complex& x)
00216 {
00217   return log (x + sqrt (x*x + 1.0));
00218 }
00219 
00220 Complex
00221 atan (const Complex& x)
00222 {
00223   static Complex i (0, 1);
00224 
00225   return i * log ((i + x) / (i - x)) / 2.0;
00226 }
00227 
00228 Complex
00229 atanh (const Complex& x)
00230 {
00231   return log ((1.0 + x) / (1.0 - x)) / 2.0;
00232 }
00233 
00234 // complex -> bool mappers.
00235 
00236 bool
00237 octave_is_NA (const Complex& x)
00238 {
00239   return (octave_is_NA (real (x)) || octave_is_NA (imag (x)));
00240 }
00241 
00242 bool
00243 octave_is_NaN_or_NA (const Complex& x)
00244 {
00245   return (xisnan (real (x)) || xisnan (imag (x)));
00246 }
00247 
00248 // (complex, complex) -> complex mappers.
00249 
00250 // FIXME -- need to handle NA too?
00251 
00252 Complex
00253 xmin (const Complex& x, const Complex& y)
00254 {
00255   return abs (x) <= abs (y) ? x : (xisnan (x) ? x : y);
00256 }
00257 
00258 Complex
00259 xmax (const Complex& x, const Complex& y)
00260 {
00261   return abs (x) >= abs (y) ? x : (xisnan (x) ? x : y);
00262 }
00263 
00264 
00265 // float -> float mappers.
00266 
00267 // Both xtrunc and xround belong here so we can keep gnulib:: out of
00268 // lo-mappers.h.
00269 
00270 float
00271 xtrunc (float x)
00272 {
00273   return gnulib::truncf (x);
00274 }
00275 
00276 float
00277 xcopysign (float x, float y)
00278 {
00279   return gnulib::copysignf (x, y);
00280 }
00281 
00282 float
00283 xround (float x)
00284 {
00285   return gnulib::round (x);
00286 }
00287 
00288 float
00289 xroundb (float x)
00290 {
00291   float t = xround (x);
00292 
00293   if (fabsf (x - t) == 0.5)
00294     t = 2 * xtrunc (0.5 * t);
00295 
00296   return t;
00297 }
00298 
00299 float
00300 signum (float x)
00301 {
00302   float tmp = 0.0;
00303 
00304   if (x < 0.0)
00305     tmp = -1.0;
00306   else if (x > 0.0)
00307     tmp = 1.0;
00308 
00309   return xisnan (x) ? octave_Float_NaN : tmp;
00310 }
00311 
00312 float
00313 xlog2 (float x)
00314 {
00315 #if defined (HAVE_LOG2)
00316   return log2 (x);
00317 #else
00318 #if defined (M_LN2)
00319   static float ln2 = M_LN2;
00320 #else
00321   static float ln2 = log2 (2);
00322 #endif
00323 
00324   return log (x) / ln2;
00325 #endif
00326 }
00327 
00328 FloatComplex
00329 xlog2 (const FloatComplex& x)
00330 {
00331 #if defined (M_LN2)
00332   static float ln2 = M_LN2;
00333 #else
00334   static float ln2 = log (2);
00335 #endif
00336 
00337   return std::log (x) / ln2;
00338 }
00339 
00340 float
00341 xexp2 (float x)
00342 {
00343 #if defined (HAVE_EXP2)
00344   return exp2 (x);
00345 #else
00346 #if defined (M_LN2)
00347   static float ln2 = M_LN2;
00348 #else
00349   static float ln2 = log2 (2);
00350 #endif
00351 
00352   return exp (x * ln2);
00353 #endif
00354 }
00355 
00356 float
00357 xlog2 (float x, int& exp)
00358 {
00359   return frexpf (x, &exp);
00360 }
00361 
00362 FloatComplex
00363 xlog2 (const FloatComplex& x, int& exp)
00364 {
00365   float ax = std::abs (x);
00366   float lax = xlog2 (ax, exp);
00367   return (ax != lax) ? (x / ax) * lax : x;
00368 }
00369 
00370 // float -> bool mappers.
00371 
00372 #if ! defined(HAVE_CMATH_ISNANF)
00373 bool
00374 xisnan (float x)
00375 {
00376   return lo_ieee_isnan (x);
00377 }
00378 #endif
00379 
00380 #if ! defined(HAVE_CMATH_ISFINITEF)
00381 bool
00382 xfinite (float x)
00383 {
00384   return lo_ieee_finite (x);
00385 }
00386 #endif
00387 
00388 #if ! defined(HAVE_CMATH_ISINFF)
00389 bool
00390 xisinf (float x)
00391 {
00392   return lo_ieee_isinf (x);
00393 }
00394 #endif
00395 
00396 bool
00397 octave_is_NA (float x)
00398 {
00399   return lo_ieee_is_NA (x);
00400 }
00401 
00402 bool
00403 octave_is_NaN_or_NA (float x)
00404 {
00405   return lo_ieee_isnan (x);
00406 }
00407 
00408 // (float, float) -> float mappers.
00409 
00410 // complex -> complex mappers.
00411 
00412 FloatComplex
00413 acos (const FloatComplex& x)
00414 {
00415   static FloatComplex i (0, 1);
00416 
00417   return -i * (log (x + i * (sqrt (static_cast<float>(1.0) - x*x))));
00418 }
00419 
00420 FloatComplex
00421 acosh (const FloatComplex& x)
00422 {
00423   return log (x + sqrt (x*x - static_cast<float>(1.0)));
00424 }
00425 
00426 FloatComplex
00427 asin (const FloatComplex& x)
00428 {
00429   static FloatComplex i (0, 1);
00430 
00431   return -i * log (i*x + sqrt (static_cast<float>(1.0) - x*x));
00432 }
00433 
00434 FloatComplex
00435 asinh (const FloatComplex& x)
00436 {
00437   return log (x + sqrt (x*x + static_cast<float>(1.0)));
00438 }
00439 
00440 FloatComplex
00441 atan (const FloatComplex& x)
00442 {
00443   static FloatComplex i (0, 1);
00444 
00445   return i * log ((i + x) / (i - x)) / static_cast<float>(2.0);
00446 }
00447 
00448 FloatComplex
00449 atanh (const FloatComplex& x)
00450 {
00451   return log ((static_cast<float>(1.0) + x) / (static_cast<float>(1.0) - x)) / static_cast<float>(2.0);
00452 }
00453 
00454 // complex -> bool mappers.
00455 
00456 bool
00457 octave_is_NA (const FloatComplex& x)
00458 {
00459   return (octave_is_NA (real (x)) || octave_is_NA (imag (x)));
00460 }
00461 
00462 bool
00463 octave_is_NaN_or_NA (const FloatComplex& x)
00464 {
00465   return (xisnan (real (x)) || xisnan (imag (x)));
00466 }
00467 
00468 // (complex, complex) -> complex mappers.
00469 
00470 // FIXME -- need to handle NA too?
00471 
00472 FloatComplex
00473 xmin (const FloatComplex& x, const FloatComplex& y)
00474 {
00475   return abs (x) <= abs (y) ? x : (xisnan (x) ? x : y);
00476 }
00477 
00478 FloatComplex
00479 xmax (const FloatComplex& x, const FloatComplex& y)
00480 {
00481   return abs (x) >= abs (y) ? x : (xisnan (x) ? x : y);
00482 }
00483 
00484 Complex
00485 rc_acos (double x)
00486 {
00487   return fabs (x) > 1.0 ? acos (Complex (x)) : Complex (acos (x));
00488 }
00489 
00490 FloatComplex
00491 rc_acos (float x)
00492 {
00493   return fabsf (x) > 1.0f ? acos (FloatComplex (x)) : FloatComplex (acosf (x));
00494 }
00495 
00496 Complex
00497 rc_acosh (double x)
00498 {
00499   return x < 1.0 ? acosh (Complex (x)) : Complex (acosh (x));
00500 }
00501 
00502 FloatComplex
00503 rc_acosh (float x)
00504 {
00505   return x < 1.0f ? acosh (FloatComplex (x)) : FloatComplex (acoshf (x));
00506 }
00507 
00508 Complex
00509 rc_asin (double x)
00510 {
00511   return fabs (x) > 1.0 ? asin (Complex (x)) : Complex (asin (x));
00512 }
00513 
00514 FloatComplex
00515 rc_asin (float x)
00516 {
00517   return fabsf (x) > 1.0f ? asin (FloatComplex (x)) : FloatComplex (asinf (x));
00518 }
00519 
00520 Complex
00521 rc_atanh (double x)
00522 {
00523   return fabs (x) > 1.0 ? atanh (Complex (x)) : Complex (atanh (x));
00524 }
00525 
00526 FloatComplex
00527 rc_atanh (float x)
00528 {
00529   return fabsf (x) > 1.0f ? atanh (FloatComplex (x)) : FloatComplex (atanhf (x));
00530 }
00531 
00532 Complex
00533 rc_log (double x)
00534 {
00535   const double pi = 3.14159265358979323846;
00536   return x < 0.0 ? Complex (log (-x), pi) : Complex (log (x));
00537 }
00538 
00539 FloatComplex
00540 rc_log (float x)
00541 {
00542   const float pi = 3.14159265358979323846f;
00543   return x < 0.0f ? FloatComplex (logf (-x), pi) : FloatComplex (logf (x));
00544 }
00545 
00546 Complex
00547 rc_log2 (double x)
00548 {
00549   const double pil2 = 4.53236014182719380962; // = pi / log(2)
00550   return x < 0.0 ? Complex (xlog2 (-x), pil2) : Complex (xlog2 (x));
00551 }
00552 
00553 FloatComplex
00554 rc_log2 (float x)
00555 {
00556   const float pil2 = 4.53236014182719380962f; // = pi / log(2)
00557   return x < 0.0f ? FloatComplex (xlog2 (-x), pil2) : FloatComplex (xlog2 (x));
00558 }
00559 
00560 Complex
00561 rc_log10 (double x)
00562 {
00563   const double pil10 = 1.36437635384184134748; // = pi / log(10)
00564   return x < 0.0 ? Complex (log10 (-x), pil10) : Complex (log10 (x));
00565 }
00566 
00567 FloatComplex
00568 rc_log10 (float x)
00569 {
00570   const float pil10 = 1.36437635384184134748f; // = pi / log(10)
00571   return x < 0.0f ? FloatComplex (log10 (-x), pil10) : FloatComplex (log10f (x));
00572 }
00573 
00574 Complex
00575 rc_sqrt (double x)
00576 {
00577   return x < 0.0 ? Complex (0.0, sqrt (-x)) : Complex (sqrt (x));
00578 }
00579 
00580 FloatComplex
00581 rc_sqrt (float x)
00582 {
00583   return x < 0.0f ? FloatComplex (0.0f, sqrtf (-x)) : FloatComplex (sqrtf (x));
00584 }
00585 
00586 bool
00587 xnegative_sign (double x)
00588 {
00589   return __lo_ieee_signbit (x);
00590 }
00591 
00592 bool
00593 xnegative_sign (float x)
00594 {
00595   return __lo_ieee_float_signbit (x);
00596 }
00597 
00598 // Convert X to the nearest integer value.  Should not pass NaN to
00599 // this function.
00600 
00601 // Sometimes you need a large integer, but not always.
00602 
00603 octave_idx_type
00604 NINTbig (double x)
00605 {
00606   if (x > std::numeric_limits<octave_idx_type>::max ())
00607     return std::numeric_limits<octave_idx_type>::max ();
00608   else if (x < std::numeric_limits<octave_idx_type>::min ())
00609     return std::numeric_limits<octave_idx_type>::min ();
00610   else
00611     return static_cast<octave_idx_type> ((x > 0) ? (x + 0.5) : (x - 0.5));
00612 }
00613 
00614 octave_idx_type
00615 NINTbig (float x)
00616 {
00617   if (x > std::numeric_limits<octave_idx_type>::max ())
00618     return std::numeric_limits<octave_idx_type>::max ();
00619   else if (x < std::numeric_limits<octave_idx_type>::min ())
00620     return std::numeric_limits<octave_idx_type>::min ();
00621   else
00622     return static_cast<octave_idx_type> ((x > 0) ? (x + 0.5) : (x - 0.5));
00623 }
00624 
00625 int
00626 NINT (double x)
00627 {
00628   if (x > std::numeric_limits<int>::max ())
00629     return std::numeric_limits<int>::max ();
00630   else if (x < std::numeric_limits<int>::min ())
00631     return std::numeric_limits<int>::min ();
00632   else
00633     return static_cast<int> ((x > 0) ? (x + 0.5) : (x - 0.5));
00634 }
00635 
00636 int
00637 NINT (float x)
00638 {
00639   if (x > std::numeric_limits<int>::max ())
00640     return std::numeric_limits<int>::max ();
00641   else if (x < std::numeric_limits<int>::min ())
00642     return std::numeric_limits<int>::min ();
00643   else
00644     return static_cast<int> ((x > 0) ? (x + 0.5) : (x - 0.5));
00645 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines