view liboctave/numeric/lo-mappers.cc @ 21782:2aef506f3fec

use namespace for lo-mappers.h functions * lo-mappers.h, lo-mappers.cc (acos, arg, asin, atan, ceil, conj, copysign, exp2, finite, fix, floor, imag, is_NA, is_NaN_or_NA, isinf, isinteger, isnan, log2, max, min, mod, negative_sign, nint, nint_big, positive_sign, rc_acos, rc_acosh, rc_asin, rc_atanh, rc_log, rc_log10, rc_log2, rc_sqrt, real, rem, round, roundb, signbit, signum, trunc, x_nint): Define in octave::math namespace. Deprecate old names. Change all uses. * oct-inttypes.h: Put round and isnan functions in octave::math namespace and rename from xround and xisnan. Change all uses.
author John W. Eaton <jwe@octave.org>
date Wed, 25 May 2016 16:51:16 -0400
parents aba2e6293dd8
children df064166f180
line wrap: on
line source

/*

Copyright (C) 1996-2015 John W. Eaton
Copyright (C) 2010 VZLU Prague

This file is part of Octave.

Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING.  If not, see
<http://www.gnu.org/licenses/>.

*/

#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

#include <cfloat>

#include "lo-error.h"
#include "lo-ieee.h"
#include "lo-mappers.h"
#include "lo-math.h"
#include "lo-specfun.h"
#include "lo-utils.h"
#include "oct-cmplx.h"

#include "f77-fcn.h"

// Functions that forward to gnulib belong here so we can keep gnulib:: out of
// lo-mappers.h.

namespace octave
{
  namespace math
  {
    bool
    is_NA (double x)
    {
      return lo_ieee_is_NA (x);
    }

    bool
    is_NA (const Complex& x)
    {
      return (is_NA (real (x)) || is_NA (imag (x)));
    }

    bool
    is_NA (float x)
    {
      return lo_ieee_is_NA (x);
    }

    bool
    is_NA (const FloatComplex& x)
    {
      return (is_NA (real (x)) || is_NA (imag (x)));
    }

    bool
    is_NaN_or_NA (const Complex& x)
    {
      return (isnan (real (x)) || isnan (imag (x)));
    }

    bool
    is_NaN_or_NA (const FloatComplex& x)
    {
      return (isnan (real (x)) || isnan (imag (x)));
    }

    Complex
    acos (const Complex& x)
    {
      static Complex i (0, 1);

      Complex tmp;

      if (imag (x) == 0.0)
        {
          // If the imaginary part of X is 0, then avoid generating an
          // imaginary part of -0 for the expression 1-x*x.
          // This effectively chooses the same phase of the branch cut as Matlab.
          double xr = real (x);
          tmp = Complex (1.0 - xr*xr);
        }
      else
        tmp = 1.0 - x*x;

      return -i * log (x + i * sqrt (tmp));
    }

    FloatComplex
    acos (const FloatComplex& x)
    {
      static FloatComplex i (0, 1);

      FloatComplex tmp;

      if (imag (x) == 0.0f)
        {
          // If the imaginary part of X is 0, then avoid generating an
          // imaginary part of -0 for the expression 1-x*x.
          // This effectively chooses the same phase of the branch cut as Matlab.
          float xr = real (x);
          tmp = FloatComplex (1.0f - xr*xr);
        }
      else
        tmp = 1.0f - x*x;

      return -i * log (x + i * sqrt (tmp));
    }

    Complex
    asin (const Complex& x)
    {
      static Complex i (0, 1);

      Complex tmp;

      if (imag (x) == 0.0)
        {
          // If the imaginary part of X is 0, then avoid generating an
          // imaginary part of -0 for the expression 1-x*x.
          // This effectively chooses the same phase of the branch cut as Matlab.
          double xr = real (x);
          tmp = Complex (1.0 - xr*xr);
        }
      else
        tmp = 1.0 - x*x;

      return -i * log (i*x + sqrt (tmp));
    }

    FloatComplex
    asin (const FloatComplex& x)
    {
      static FloatComplex i (0, 1);

      FloatComplex tmp;

      if (imag (x) == 0.0f)
        {
          // If the imaginary part of X is 0, then avoid generating an
          // imaginary part of -0 for the expression 1-x*x.
          // This effectively chooses the same phase of the branch cut as Matlab.
          float xr = real (x);
          tmp = FloatComplex (1.0f - xr*xr);
        }
      else
        tmp = 1.0f - x*x;

      return -i * log (i*x + sqrt (tmp));
    }

    Complex
    atan (const Complex& x)
    {
      static Complex i (0, 1);

      return i * log ((i + x) / (i - x)) / 2.0;
    }

    FloatComplex
    atan (const FloatComplex& x)
    {
      static FloatComplex i (0, 1);

      return i * log ((i + x) / (i - x)) / 2.0f;
    }

    double log2 (double x) { return gnulib::log2 (x); }
    float log2 (float x) { return gnulib::log2f (x); }

    Complex
    log2 (const Complex& x)
    {
#if defined (M_LN2)
      static double ln2 = M_LN2;
#else
      static double ln2 = gnulib::log (2.0);
#endif
      return std::log (x) / ln2;
    }

    FloatComplex
    log2 (const FloatComplex& x)
    {
#if defined (M_LN2)
      static float ln2 = M_LN2;
#else
      static float ln2 = log (2.0f);
#endif
      return std::log (x) / ln2;
    }

    double
    log2 (double x, int& exp)
    {
      return gnulib::frexp (x, &exp);
    }

    float
    log2 (float x, int& exp)
    {
      return gnulib::frexpf (x, &exp);
    }

    Complex
    log2 (const Complex& x, int& exp)
    {
      double ax = std::abs (x);
      double lax = log2 (ax, exp);
      return (ax != lax) ? (x / ax) * lax : x;
    }

    FloatComplex
    log2 (const FloatComplex& x, int& exp)
    {
      float ax = std::abs (x);
      float lax = log2 (ax, exp);
      return (ax != lax) ? (x / ax) * lax : x;
    }

    double
    exp2 (double x)
    {
#if defined (HAVE_EXP2)
      return ::exp2 (x);
#else
#  if defined (M_LN2)
      static double ln2 = M_LN2;
#  else
      static double ln2 = gnulib::log (2.0);
#  endif
      return exp (x * ln2);
#endif
    }

    float
    exp2 (float x)
    {
#if defined (HAVE_EXP2F)
      return exp2f (x);
#elif defined (HAVE_EXP2)
      return ::exp2 (x);
#else
#  if defined (M_LN2)
      static float ln2 = M_LN2;
#  else
      static float ln2 = log2 (2.0f);
#  endif
      return exp (x * ln2);
#endif
    }

    double copysign (double x, double y) { return gnulib::copysign (x, y); }
    float copysign (float x, float y) { return gnulib::copysignf (x, y); }

    double signbit (double x) { return ::signbit (x); }
    float signbit (float x) { return ::signbit (x); }

    bool negative_sign (double x) { return __lo_ieee_signbit (x); }
    bool negative_sign (float x) { return __lo_ieee_float_signbit (x); }

    double trunc (double x) { return gnulib::trunc (x); }
    float trunc (float x) { return gnulib::truncf (x); }

    double floor (double x) { return gnulib::floor (x); }
    float floor (float x) { return gnulib::floor (x); }

    double round (double x) { return gnulib::round (x); }
    float round (float x) { return gnulib::roundf (x); }

    bool
    isnan (double x)
    {
#if defined (HAVE_CMATH_ISNAN)
      return std::isnan (x);
#else
      return lo_ieee_isnan (x);
#endif
    }

    bool
    isnan (float x)
    {
#if defined (HAVE_CMATH_ISNANF)
      return std::isnan (x);
#else
      return lo_ieee_isnan (x);
#endif
    }

    bool
    finite (double x)
    {
#if defined (HAVE_CMATH_ISFINITE)
      return std::isfinite (x);
#else
      return lo_ieee_finite (x);
#endif
    }

    bool
    finite (float x)
    {
#if defined (HAVE_CMATH_ISFINITEF)
      return std::isfinite (x);
#else
      return lo_ieee_finite (x);
#endif
    }

    bool
    isinf (double x)
    {
#if defined (HAVE_CMATH_ISINF)
      return std::isinf (x);
#else
      return lo_ieee_isinf (x);
#endif
    }

    bool
    isinf (float x)
    {
#if defined (HAVE_CMATH_ISINFF)
      return std::isinf (x);
#else
      return lo_ieee_isinf (x);
#endif
    }

    // Sometimes you need a large integer, but not always.

    octave_idx_type
    nint_big (double x)
    {
      if (x > std::numeric_limits<octave_idx_type>::max ())
        return std::numeric_limits<octave_idx_type>::max ();
      else if (x < std::numeric_limits<octave_idx_type>::min ())
        return std::numeric_limits<octave_idx_type>::min ();
      else
        return static_cast<octave_idx_type> ((x > 0.0) ? (x + 0.5) : (x - 0.5));
    }

    octave_idx_type
    nint_big (float x)
    {
      if (x > std::numeric_limits<octave_idx_type>::max ())
        return std::numeric_limits<octave_idx_type>::max ();
      else if (x < std::numeric_limits<octave_idx_type>::min ())
        return std::numeric_limits<octave_idx_type>::min ();
      else
        return static_cast<octave_idx_type> ((x > 0.0f) ? (x + 0.5f) : (x - 0.5f));
    }

    int
    nint (double x)
    {
      if (x > std::numeric_limits<int>::max ())
        return std::numeric_limits<int>::max ();
      else if (x < std::numeric_limits<int>::min ())
        return std::numeric_limits<int>::min ();
      else
        return static_cast<int> ((x > 0.0) ? (x + 0.5) : (x - 0.5));
    }

    int
    nint (float x)
    {
      if (x > std::numeric_limits<int>::max ())
        return std::numeric_limits<int>::max ();
      else if (x < std::numeric_limits<int>::min ())
        return std::numeric_limits<int>::min ();
      else
        return static_cast<int> ((x > 0.0f) ? (x + 0.5f) : (x - 0.5f));
    }

    Complex
    rc_acos (double x)
    {
      return fabs (x) > 1.0 ? acos (Complex (x)) : Complex (::acos (x));
    }

    FloatComplex
    rc_acos (float x)
    {
      return fabsf (x) > 1.0f ? acos (FloatComplex (x)) : FloatComplex (::acosf (x));
    }

    Complex
    rc_acosh (double x)
    {
      return x < 1.0 ? acosh (Complex (x)) : Complex (acosh (x));
    }

    FloatComplex
    rc_acosh (float x)
    {
      return x < 1.0f ? acosh (FloatComplex (x)) : FloatComplex (acosh (x));
    }

    Complex
    rc_asin (double x)
    {
      return fabs (x) > 1.0 ? asin (Complex (x)) : Complex (::asin (x));
    }

    FloatComplex
    rc_asin (float x)
    {
      return fabsf (x) > 1.0f ? asin (FloatComplex (x)) : FloatComplex (::asinf (x));
    }

    Complex
    rc_atanh (double x)
    {
      return fabs (x) > 1.0 ? atanh (Complex (x)) : Complex (atanh (x));
    }

    FloatComplex
    rc_atanh (float x)
    {
      return fabsf (x) > 1.0f ? xatanh (FloatComplex (x)) : FloatComplex (atanh (x));
    }

    Complex
    rc_log (double x)
    {
      const double pi = 3.14159265358979323846;
      return x < 0.0 ? Complex (gnulib::log (-x), pi) : Complex (gnulib::log (x));
    }

    FloatComplex
    rc_log (float x)
    {
      const float pi = 3.14159265358979323846f;
      return x < 0.0f ? FloatComplex (gnulib::logf (-x), pi) : FloatComplex (gnulib::logf (x));
    }

    Complex
    rc_log2 (double x)
    {
      const double pil2 = 4.53236014182719380962; // = pi / log(2)
      return x < 0.0 ? Complex (log2 (-x), pil2) : Complex (log2 (x));
    }

    FloatComplex
    rc_log2 (float x)
    {
      const float pil2 = 4.53236014182719380962f; // = pi / log(2)
      return x < 0.0f ? FloatComplex (log2 (-x), pil2) : FloatComplex (log2 (x));
    }

    Complex
    rc_log10 (double x)
    {
      const double pil10 = 1.36437635384184134748; // = pi / log(10)
      return x < 0.0 ? Complex (log10 (-x), pil10) : Complex (log10 (x));
    }

    FloatComplex
    rc_log10 (float x)
    {
      const float pil10 = 1.36437635384184134748f; // = pi / log(10)
      return x < 0.0f ? FloatComplex (log10 (-x), pil10) : FloatComplex (log10f (x));
    }

    Complex
    rc_sqrt (double x)
    {
      return x < 0.0 ? Complex (0.0, sqrt (-x)) : Complex (sqrt (x));
    }

    FloatComplex
    rc_sqrt (float x)
    {
      return x < 0.0f ? FloatComplex (0.0f, sqrtf (-x)) : FloatComplex (sqrtf (x));
    }
  }
}