-
Notifications
You must be signed in to change notification settings - Fork 0
/
sli_numerics.h
94 lines (79 loc) · 1.64 KB
/
sli_numerics.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
* numerics.h
*
* This file is part of NEST
*
* Copyright (C) 2004 by
* The NEST Initiative
*
* See the file AUTHORS for details.
*
* Permission is granted to compile and modify
* this file for non-commercial use.
* See the file LICENSE for details.
*
*/
#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