/*
* numerics.h
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST 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 2 of the License, or
* (at your option) any later version.
*
* NEST 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 NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef NUMERICS_H
#define NUMERICS_H
#include <limits>
#include <cmath>
#if HAVE_EXPM1
# include <math.h>
#endif
namespace numerics {
extern const double e;
extern const double pi;
/** Supply expm1() function independent of system.
* @note Implemented inline for efficiency.
*/
inline
double expm1(double x)
{
#if HAVE_EXPM1
return ::expm1(x); // use library implementation if available
#else
// compute using Taylor series, see GSL
// e^x-1 = x + x^2/2! + x^3/3! + ...
if ( x == 0 )
return 0;
if ( std::abs(x) > std::log(2.0) )
return std::exp(x) - 1;
else
{
double sum = x;
double term = x*x/2;
long n = 2;
while ( std::abs(term) >
std::abs(sum) * std::numeric_limits<double>::epsilon() )
{
sum += term;
++n;
term *= x/n;
}
return sum;
}
#endif
}
}
// later also in namespace
/**
* Round to nearest int, rounding midpoints upwards.
*
* @return Result as long
* @note [-1/2, 1/2) -> 0 and in general [ (2n-1)/2, (2n+1)/2 ) -> n
* @see dround
*/
long ld_round(double);
/**
* Round to nearest int, rounding midpoints upwards.
*
* @return Result as double
* @note [-1/2, 1/2) -> 0 and in general [ (2n-1)/2, (2n+1)/2 ) -> n
* @see ld_round
*/
double dround(double);
/**
* Return integer part of argument.
*/
double dtruncate(double);
# endif