Module: Distribution::MathExtension::Log
- Defined in:
- lib/distribution/math_extension/log_utilities.rb
Overview
Various logarithm shortcuts, adapted from GSL-1.9.
Constant Summary collapse
- C1 =
-1.quo(2)
- C2 =
1.quo(3)
- C3 =
-1.quo(4)
- C4 =
1.quo(5)
- C5 =
-1.quo(6)
- C6 =
1.quo(7)
- C7 =
-1.quo(8)
- C8 =
1.quo(9)
- C9 =
-1.quo(10)
Class Method Summary collapse
-
.log1p(x) ⇒ Object
gsl_log1p from GSL-1.9 sys/log1p.c log for very small x.
-
.log_1plusx(x, with_error = false) ⇒ Object
\log(1+x) for x > -1 gsl_sf_log_1plusx_e.
-
.log_1plusx_minusx(x, with_error = false) ⇒ Object
\log(1+x)-x for x > -1 gsl_sf_log_1plusx_mx_e.
Class Method Details
.log1p(x) ⇒ Object
gsl_log1p from GSL-1.9 sys/log1p.c log for very small x
20 21 22 23 24 25 |
# File 'lib/distribution/math_extension/log_utilities.rb', line 20 def log1p(x) # in C, this is volatile double y. # Not sure how to reproduce that in Ruby. y = 1 + x Math.log(y) - ((y - 1) - x).quo(y) # cancel errors with IEEE arithmetic end |
.log_1plusx(x, with_error = false) ⇒ Object
\log(1+x) for x > -1 gsl_sf_log_1plusx_e
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/distribution/math_extension/log_utilities.rb', line 29 def log_1plusx(x, with_error = false) fail(ArgumentError, 'Range error: x must be > -1') if x <= -1 if x.abs < Math::ROOT6_FLOAT_EPSILON result = x * (1.0 + x * (C1 + x * (C2 + x * (C3 + x * (C4 + x * begin C5 + x * (C6 + x * (C7 + x * (C8 + x * C9))) # formerly t = this end))))) return with_error ? [result, Float::EPSILON * result.abs] : result elsif x.abs < 0.5 c = ChebyshevSeries.evaluate(:lopx, (8 * x + 1).quo(2 * x + 4), with_error) return with_error ? [x * c.first, x * c.last] : x * c else result = Math.log(1 + x) return with_error ? [result, Float::EPSILON * result.abs] : result end end |
.log_1plusx_minusx(x, with_error = false) ⇒ Object
\log(1+x)-x for x > -1 gsl_sf_log_1plusx_mx_e
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/distribution/math_extension/log_utilities.rb', line 48 def log_1plusx_minusx(x, with_error = false) fail(ArgumentError, 'Range error: x must be > -1') if x <= -1 if x.abs < Math::ROOT5_FLOAT_EPSILON result = x * x * (C1 + x * (C2 + x * (C3 + x * (C4 + x * begin C5 + x * (C6 + x * (C7 + x * (C8 + x * C9))) # formerly t = this end)))) return with_error ? [result, Float::EPSILON * result.abs] : result elsif x.abs < 0.5 c = ChebyshevSeries.evaluate(:lopxmx, (8 * x + 1).quo(2 * x + 4), with_error) return with_error ? [x * x * c.first, x * x * c.last] : x * x * c else lterm = Math.log(1.0 + x) error = Float::EPSILON * (lterm.abs + x.abs) if with_error result = lterm - x return with_error ? [result, error] : result end end |