Module: Math
- Defined in:
- lib/standard/facets/math/ec.rb,
lib/standard/facets/math/abs.rb,
lib/standard/facets/math/amd.rb,
lib/standard/facets/math/cdf.rb,
lib/standard/facets/math/cot.rb,
lib/standard/facets/math/csc.rb,
lib/standard/facets/math/gcd.rb,
lib/standard/facets/math/lcm.rb,
lib/standard/facets/math/min.rb,
lib/standard/facets/math/pow.rb,
lib/standard/facets/math/rmd.rb,
lib/standard/facets/math/sec.rb,
lib/standard/facets/math/sqr.rb,
lib/standard/facets/math/std.rb,
lib/standard/facets/math/sum.rb,
lib/standard/facets/math/tau.rb,
lib/standard/facets/math/acot.rb,
lib/standard/facets/math/acsc.rb,
lib/standard/facets/math/asec.rb,
lib/standard/facets/math/beta.rb,
lib/standard/facets/math/ceil.rb,
lib/standard/facets/math/coth.rb,
lib/standard/facets/math/csch.rb,
lib/standard/facets/math/exp2.rb,
lib/standard/facets/math/log2.rb,
lib/standard/facets/math/mean.rb,
lib/standard/facets/math/root.rb,
lib/standard/facets/math/sech.rb,
lib/standard/facets/math/sign.rb,
lib/standard/facets/math/sinc.rb,
lib/standard/facets/math/acoth.rb,
lib/standard/facets/math/acsch.rb,
lib/standard/facets/math/asech.rb,
lib/standard/facets/math/delta.rb,
lib/standard/facets/math/exp10.rb,
lib/standard/facets/math/floor.rb,
lib/standard/facets/math/round.rb,
lib/standard/facets/math/median.rb,
lib/standard/facets/math/tgamma.rb,
lib/standard/facets/math/epsilon.rb,
lib/standard/facets/math/lngamma.rb,
lib/standard/facets/math/sqsolve.rb,
lib/standard/facets/math/distance.rb,
lib/standard/facets/math/linsolve.rb,
lib/standard/facets/math/variance.rb,
lib/standard/facets/math/factorial.rb,
lib/standard/facets/math/percentile.rb,
lib/standard/facets/math/theil_index.rb,
lib/standard/facets/math/approx_equal.rb,
lib/standard/facets/math/kldivergence.rb,
lib/standard/facets/math/summed_sqdevs.rb,
lib/standard/facets/math/atkinson_index.rb,
lib/standard/facets/math/gini_coefficient.rb
Constant Summary collapse
- EC =
Euler’s constant.
0.577_215_664_901_532_861
- TAU =
2 * PI
- INVERSE_LN_2 =
1.0 / ::Math.log(2.0)
- FACTORIALS =
First 16 factorials.
[ 1, 1, 2, 6, 24, 120, 720, 5_040, 40_320, 362_880, 3_628_800, 39_916_800, 479_001_600, 6_227_020_800, 87_178_291_200, 1_307_674_368_000 ]
- EPSILON =
0.000000001
Class Method Summary collapse
-
.abs(x) ⇒ Object
Absolute value of
x
. -
.acosec(x) ⇒ Object
Arcus cosecans of ‘x`.
-
.acot(x) ⇒ Object
Arcus cotangens of
x
. -
.acoth(x) ⇒ Object
Area cotangens hyperbolicus of
x
. -
.acsc(x) ⇒ Object
Arcus cosecans of ‘x`.
-
.amd(array) ⇒ Object
(also: absolute_mean_difference)
The average absolute difference of two independent values drawn from the sample.
-
.approx_equal(a, b, epsilon = EPSILON) ⇒ Object
Approximately equal.
-
.asec(x) ⇒ Object
Arcus secans of
x
. -
.atkinson_index(array) ⇒ Object
Closely related to the Theil index and easily expressible in terms of it.
-
.beta(x, y) ⇒ Object
Beta function of ‘x` and `y`.
-
.cdf(array, normalised = 1.0) ⇒ Object
Returns the Cumulative Density Function of this sample (normalised to a fraction of 1.0).
-
.ceil(x) ⇒ Object
Smallest integer not smaller than
x
. -
.cosec(x) ⇒ Object
Cosecans of ‘x`.
-
.cosech(x) ⇒ Object
Cosecans hyperbolicus of ‘x`.
-
.cot(x) ⇒ Object
Cotangens of
x
. -
.coth(x) ⇒ Object
Cotangens hyperbolicus of
x
. -
.csc(x) ⇒ Object
Cosecans of ‘x`.
-
.csch(x) ⇒ Object
Cosecans hyperbolicus of ‘x`.
-
.delta(i, j) ⇒ Object
Kronecker symbol of
i
andj
. -
.distance(p, q) ⇒ Object
Calculates the Euclidean Distance between points
p
andq
. -
.epsilon(i, j, k) ⇒ Object
Levi-Civita symbol of
i
,j
, andk
- 1 if (i
,j
,k
) is (1, 2, 3), (2, 3, 1), or (3, 1, 2), -1 if it is (1, 3, 2), (2, 1, 3), or (3, 2, 1), 0 as long asi
,j
, andk
are all elements of 2, 3, otherwise returnsnil
. -
.exp10(x) ⇒ Object
10 to the power
x
. -
.exp2(x) ⇒ Object
2 to the power
x
. -
.factorial(n) ⇒ Object
1 * 2 * …
-
.floor(x) ⇒ Object
Largest integer not larger than
x
. -
.gcd(m, n) ⇒ Object
Greatest common divisor of
m
andn
,nil
for non-positive numbers - gcd is computed by means of the Euclidian algorithm. -
.gini_coefficient(array) ⇒ Object
Calculates the Gini Coefficient (a measure of inequality of a distribution based on the area between the Lorenz curve and the uniform curve).
-
.kldivergence(array, q) ⇒ Object
The Kullback-Leibler divergence from this array to that of
q
. -
.lcm(m, n) ⇒ Object
Least common multiple of
m
andn
, computed by multiplyingm
andn
and dividing the product by the gcd ofm
andn
,nil
for non-positive numbers. -
.linsolve(a, b, c = 0.0) ⇒ Object
Returns real solution(s) of
+a+x + b = c
ornil
if no or an infinite number of solutions exist. -
.ln_gamma(x) ⇒ Object
Old name used by Extmath library.
-
.lngamma(x) ⇒ Object
Logarithmus naturalis of gamma function of ‘x`.
-
.log2(x) ⇒ Object
Logarithmus dualis of
x
. - .max(array, block) ⇒ Object
-
.mean(array, &blk) ⇒ Object
(also: mean_average)
Mean average.
-
.median(array) ⇒ Object
Returns the numerical median for the an array of values; or nil if array is empty.
- .min(array, &block) ⇒ Object
-
.percentile(array, pcnt) ⇒ Object
Returns the percentile value for percentile pcnt; nil if array is empty.
-
.pow(x, y) ⇒ Object
‘x` to the power `y`.
-
.pstd(array, &block) ⇒ Object
Standard deviation of a population.
-
.pvariance(array) ⇒ Object
Variance of a population.
-
.pwr(x, y) ⇒ Object
‘x` to the power `y`.
-
.rmd(array) ⇒ Object
(also: relative_mean_difference)
Calculates the relative mean difference of this sample.
-
.root(x, y) ⇒ Object
The ‘y` root of `x`.
-
.round(x) ⇒ Object
Round number to an integer.
-
.sec(x) ⇒ Object
Secans of
x
. -
.sech(x) ⇒ Object
Secans hyperbolicus of
x
. -
.sgn(x, zero = 0.0) ⇒ Object
Same as ‘Math.sign`.
-
.sign(x, zero = 0.0) ⇒ Object
Sign of ‘x`.
-
.sinc(x) ⇒ Object
Sinc function of
x
. -
.sqr(x) ⇒ Object
Square of number.
-
.sqsolve(a, b, c, d = 0.0) ⇒ Object
Returns array of real solution of
ax**2 + bx + c = d
ornil
if no or an infinite number of solutions exist. -
.std(array, &block) ⇒ Object
(also: standard_deviation)
Standard deviation of a sample.
-
.stderr(array) ⇒ Object
Calculates the standard error of a sample.
-
.sum(array) ⇒ Object
Returns sum.
-
.summed_sqdevs(array) ⇒ Object
The sum of the squared deviations from the mean.
-
.tgamma(x) ⇒ Object
Exp of LGamma.
-
.theil_index(array) ⇒ Object
Calculates the Theil index (a statistic used to measure economic inequality).
-
.unit_step(x, zero = 1.0) ⇒ Object
The *Heaviside step function*, also called the the *unit step function*.
- .variance(array, &block) ⇒ Object
-
.variance2(array) ⇒ Object
Variance of the sample.
Instance Method Summary collapse
-
#acsch(x) ⇒ Object
Area cosecans hyperbolicus of
x
. -
#asech(x) ⇒ Object
Area secans hyperbolicus of
x
.
Class Method Details
.abs(x) ⇒ Object
Absolute value of x
.
4 5 6 |
# File 'lib/standard/facets/math/abs.rb', line 4 def self.abs(x) x.abs end |
.acosec(x) ⇒ Object
Arcus cosecans of ‘x`.
9 10 11 |
# File 'lib/standard/facets/math/acsc.rb', line 9 def self.acosec(x) asin(1.0 / x) end |
.acot(x) ⇒ Object
Arcus cotangens of x
4 5 6 |
# File 'lib/standard/facets/math/acot.rb', line 4 def self.acot(x) (PI * 0.5) - atan(x) end |
.acoth(x) ⇒ Object
Area cotangens hyperbolicus of x
4 5 6 |
# File 'lib/standard/facets/math/acoth.rb', line 4 def self.acoth(x) 0.5 * log((x + 1.0) / (x - 1.0)) end |
.acsc(x) ⇒ Object
Arcus cosecans of ‘x`.
4 5 6 |
# File 'lib/standard/facets/math/acsc.rb', line 4 def self.acsc(x) asin(1.0 / x) end |
.amd(array) ⇒ Object Also known as: absolute_mean_difference
The average absolute difference of two independent values drawn from the sample. Equal to the RMD * mean.
8 9 10 |
# File 'lib/standard/facets/math/amd.rb', line 8 def self.amd(array) rmd(array) * mean(array) end |
.approx_equal(a, b, epsilon = EPSILON) ⇒ Object
Approximately equal.
TODO: Use core extension Numeric#approx? instead (?)
9 10 11 12 13 |
# File 'lib/standard/facets/math/approx_equal.rb', line 9 def self.approx_equal(a, b, epsilon=EPSILON) c = a - b c *= -1.0 if c < 0 c < epsilon end |
.asec(x) ⇒ Object
Arcus secans of x
4 5 6 |
# File 'lib/standard/facets/math/asec.rb', line 4 def self.asec(x) acos(1.0 / x) end |
.atkinson_index(array) ⇒ Object
Closely related to the Theil index and easily expressible in terms of it.
AI = 1-e^theil_index
11 12 13 14 |
# File 'lib/standard/facets/math/atkinson_index.rb', line 11 def self.atkinson_index(array) t = theil_index(array) (t < 0) ? -1 : 1-Math::E**(-t) end |
.beta(x, y) ⇒ Object
Beta function of ‘x` and `y`.
beta(x, y) = tgamma(x) * tgamma(y) / tgamma(x + y)
9 10 11 12 |
# File 'lib/standard/facets/math/beta.rb', line 9 def self.beta(x, y) #exp(lgamma(x).first + lgamma(y).first - lgamma(x+y).first) tgamma(x) * tgamma(y) / tgamma(x + y) end |
.cdf(array, normalised = 1.0) ⇒ Object
Returns the Cumulative Density Function of this sample (normalised to a fraction of 1.0).
5 6 7 8 |
# File 'lib/standard/facets/math/cdf.rb', line 5 def self.cdf(array, normalised=1.0) s = sum(array).to_f array.sort.inject([0.0]) { |c,d| c << c[-1] + normalised*d.to_f/s } end |
.ceil(x) ⇒ Object
Smallest integer not smaller than x
.
4 5 6 |
# File 'lib/standard/facets/math/ceil.rb', line 4 def self.ceil(x) x.ceil end |
.cosec(x) ⇒ Object
Cosecans of ‘x`.
9 10 11 |
# File 'lib/standard/facets/math/csc.rb', line 9 def self.cosec(x) 1.0 / sin(x) end |
.cosech(x) ⇒ Object
Cosecans hyperbolicus of ‘x`.
9 10 11 |
# File 'lib/standard/facets/math/csch.rb', line 9 def self.cosech(x) 1.0 / sinh(x) end |
.cot(x) ⇒ Object
Cotangens of x
4 5 6 |
# File 'lib/standard/facets/math/cot.rb', line 4 def self.cot(x) tan((PI * 0.5) - x) end |
.coth(x) ⇒ Object
Cotangens hyperbolicus of x
4 5 6 |
# File 'lib/standard/facets/math/coth.rb', line 4 def self.coth(x) 1.0 / tanh(x) end |
.csc(x) ⇒ Object
Cosecans of ‘x`.
4 5 6 |
# File 'lib/standard/facets/math/csc.rb', line 4 def self.csc(x) 1.0 / sin(x) end |
.csch(x) ⇒ Object
Cosecans hyperbolicus of ‘x`.
4 5 6 |
# File 'lib/standard/facets/math/csch.rb', line 4 def self.csch(x) 1.0 / sinh(x) end |
.delta(i, j) ⇒ Object
Kronecker symbol of i
and j
. Returns 1 if i
and j
are equal, 0 otherwise.
5 6 7 |
# File 'lib/standard/facets/math/delta.rb', line 5 def self.delta(i, j) return Integer(i) == Integer(j) ? 1 : 0 end |
.distance(p, q) ⇒ Object
Calculates the Euclidean Distance between points p
and q
.
‘p`, `q` is assumed to described coordinates in N-dimensions, e. g.:
Math.distance([1, 1], [2, 2]) # 2D coordinates
Math.distance([1, 1, 1], [2, 2, 2]) # 3D coordinates
If N is 1, then ‘::distance` may also be invoked like so:
Math.distance(1, 1)
14 15 16 17 |
# File 'lib/standard/facets/math/distance.rb', line 14 def self.distance(p, q) p, q = [p].flatten, [q].flatten sqrt(p.zip(q).inject(0){ |sum, coord| sum + (coord.first - coord.last)**2 }) end |
.epsilon(i, j, k) ⇒ Object
Levi-Civita symbol of i
, j
, and k
- 1 if (i
, j
, k
) is (1, 2, 3), (2, 3, 1), or (3, 1, 2), -1 if it is (1, 3, 2), (2, 1, 3), or (3, 2, 1), 0 as long as i
, j
, and k
are all elements of 2, 3, otherwise returns nil
.
7 8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/standard/facets/math/epsilon.rb', line 7 def self.epsilon(i, j, k) i = Integer(i) return nil if i < 1 or i > 3 j = Integer(j) return nil if j < 1 or j > 3 k = Integer(k) return nil if k < 1 or k > 3 case i * 16 + j * 4 + k when 27, 45, 54 then return 1 when 30, 39, 57 then return -1 end 0 end |
.exp10(x) ⇒ Object
10 to the power x
4 5 6 |
# File 'lib/standard/facets/math/exp10.rb', line 4 def self.exp10(x) 10.0 ** x end |
.exp2(x) ⇒ Object
2 to the power x
4 5 6 |
# File 'lib/standard/facets/math/exp2.rb', line 4 def self.exp2(x) 2.0 ** x end |
.factorial(n) ⇒ Object
1 * 2 * … * n
, nil
for negative numbers
24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/standard/facets/math/factorial.rb', line 24 def self.factorial(n) n = Integer(n) if n < 0 nil elsif FACTORIALS.length > n FACTORIALS[n] else h = FACTORIALS.last (FACTORIALS.length .. n).each { |i| FACTORIALS.push h *= i } h end end |
.floor(x) ⇒ Object
Largest integer not larger than x
.
4 5 6 |
# File 'lib/standard/facets/math/floor.rb', line 4 def self.floor(x) x.floor end |
.gcd(m, n) ⇒ Object
Greatest common divisor of m
and n
, nil
for non-positive numbers - gcd is computed by means of the Euclidian algorithm.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/standard/facets/math/gcd.rb', line 5 def self.gcd(m, n) m = Integer(m) n = Integer(n) if m <= 0 || n <= 0 return nil end loop { if m < n m, n = n, m end if (l = m % n) == 0 break end m = l } n end |
.gini_coefficient(array) ⇒ Object
Calculates the Gini Coefficient (a measure of inequality of a distribution based on the area between the Lorenz curve and the uniform curve).
en.wikipedia.org/wiki/Gini_coefficient
This is a slightly cleaner way of calculating the Gini Coefficient then the previous implementationj.
GC = \frac{\sum_{i=1}^N (2i-N-1)x_i}{N^2-\bar{x}}
15 16 17 18 19 20 21 |
# File 'lib/standard/facets/math/gini_coefficient.rb', line 15 def self.gini_coefficient(array) return -1 if size <= 0 or any? { |x| x < 0 } return 0 if size < 2 or all? { |x| approx_equal(x,0) } s = 0 sort.each_with_index { |li,i| s += (2*i+1-size)*li } s.to_f/(size**2*mean).to_f end |
.kldivergence(array, q) ⇒ Object
The Kullback-Leibler divergence from this array to that of q
.
NB: You will possibly want to sort both P and Q before calling this depending on what you’re actually trying to measure.
10 11 12 13 14 15 16 |
# File 'lib/standard/facets/math/kldivergence.rb', line 10 def self.kldivergence(array, q) fail "Buggy." fail "Cannot compare differently sized arrays." unless size = q.size kld = 0 each_with_index { |pi,i| kld += pi*Math::log(pi.to_f/q[i].to_f) } kld end |
.lcm(m, n) ⇒ Object
Least common multiple of m
and n
, computed by multiplying m
and n
and dividing the product by the gcd of m
and n
, nil
for non-positive numbers.
6 7 8 9 10 11 12 13 |
# File 'lib/standard/facets/math/lcm.rb', line 6 def self.lcm(m, n) m = Integer(m) n = Integer(n) if m <= 0 || n <= 0 return nil end m / gcd(m, n) * n end |
.linsolve(a, b, c = 0.0) ⇒ Object
Returns real solution(s) of +a+x + b = c
or nil
if no or an infinite number of solutions exist. If c
is missing it is assumed to be 0.
8 9 10 |
# File 'lib/standard/facets/math/linsolve.rb', line 8 def self.linsolve(a, b, c = 0.0) a == 0 ? nil : (c - b) / a end |
.ln_gamma(x) ⇒ Object
Old name used by Extmath library.
13 14 15 |
# File 'lib/standard/facets/math/lngamma.rb', line 13 def self.ln_gamma(x) lgamma(x).first end |
.lngamma(x) ⇒ Object
Logarithmus naturalis of gamma function of ‘x`.
Notice the use of ‘ln` prefix to differentiate from Ruby’s built-in ‘#lgamma` function which returns an Array.
8 9 10 |
# File 'lib/standard/facets/math/lngamma.rb', line 8 def self.lngamma(x) lgamma(x).first end |
.log2(x) ⇒ Object
Logarithmus dualis of x
.
8 9 10 |
# File 'lib/standard/facets/math/log2.rb', line 8 def self.log2(x) Math.log(x) * INVERSE_LN_2 end |
.max(array, block) ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/standard/facets/math/min.rb', line 20 def self.max(array, block) if block_given? if max = find{|i| i} max = yield(max) each{|i| j = yield(i) max = j if max < j } max end else array.max end end |
.mean(array, &blk) ⇒ Object Also known as: mean_average
Mean average.
6 7 8 9 10 |
# File 'lib/standard/facets/math/mean.rb', line 6 def self.mean(array, &blk) s = array.size return 0.0 if s == 0 sum(array, &blk) / s end |
.median(array) ⇒ Object
Returns the numerical median for the an array of values; or nil if array is empty.
8 9 10 |
# File 'lib/standard/facets/math/median.rb', line 8 def self.median(array) percentile(array, 50) end |
.min(array, &block) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# File 'lib/standard/facets/math/min.rb', line 4 def self.min(array, &block) if block_given? if min = array.find{ |i| i } min = yield(min) array.each do |i| j = yield(i) min = j if min > j end min end else array.min end end |
.percentile(array, pcnt) ⇒ Object
Returns the percentile value for percentile pcnt; nil if array is empty.
pcnt
should be expressed as an integer, e.g. ‘percentile(90)` returns the 90th percentile of the array.
Algorithm from NIST
NOTE: This is not a common core extension and is not loaded automatically when using require 'facets'
.
CREDIT: Ben Koski
@non-core
require 'facets/math/percentile'
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/standard/facets/math/percentile.rb', line 18 def self.percentile(array, pcnt) sorted_array = array.sort return nil if array.length == 0 rank = (pcnt.to_f / 100) * (array.length + 1) whole = rank.truncate # if has fractional part if whole != rank s0 = sorted_array[whole - 1] s1 = sorted_array[whole] f = (rank - rank.truncate).abs return (f * (s1 - s0)) + s0 else return sorted_array[whole - 1] end end |
.pow(x, y) ⇒ Object
‘x` to the power `y`.
4 5 6 |
# File 'lib/standard/facets/math/pow.rb', line 4 def self.pow(x, y) x ** y end |
.pstd(array, &block) ⇒ Object
Standard deviation of a population.
17 18 19 |
# File 'lib/standard/facets/math/std.rb', line 17 def self.pstd(array, &block) Math::sqrt(pvariance(array, &block)) end |
.pvariance(array) ⇒ Object
Variance of a population. Variance of 0 or 1 elements is 0.0.
26 27 28 29 |
# File 'lib/standard/facets/math/variance.rb', line 26 def self.pvariance(array) return 0.0 if array.size < 2 summed_sqdevs(array) / array.size end |
.pwr(x, y) ⇒ Object
‘x` to the power `y`.
9 10 11 |
# File 'lib/standard/facets/math/pow.rb', line 9 def self.pwr(x, y) x ** y end |
.rmd(array) ⇒ Object Also known as: relative_mean_difference
Calculates the relative mean difference of this sample. Makes use of the fact that the Gini Coefficient is half the RMD.
7 8 9 10 |
# File 'lib/standard/facets/math/rmd.rb', line 7 def self.rmd(array) return 0.0 if approx_equal(mean(array), 0.0) gini_coefficient(array) * 2 end |
.root(x, y) ⇒ Object
The ‘y` root of `x`.
4 5 6 |
# File 'lib/standard/facets/math/root.rb', line 4 def self.root(x, y) x ** (1.0 / y) end |
.round(x) ⇒ Object
Round number to an integer.
5 6 7 |
# File 'lib/standard/facets/math/round.rb', line 5 def self.round(x) x.round end |
.sec(x) ⇒ Object
Secans of x
.
4 5 6 |
# File 'lib/standard/facets/math/sec.rb', line 4 def self.sec(x) 1.0 / cos(x) end |
.sech(x) ⇒ Object
Secans hyperbolicus of x
4 5 6 |
# File 'lib/standard/facets/math/sech.rb', line 4 def self.sech(x) 1.0 / cosh(x) end |
.sgn(x, zero = 0.0) ⇒ Object
Same as ‘Math.sign`.
10 11 12 |
# File 'lib/standard/facets/math/sign.rb', line 10 def self.sgn(x, zero=0.0) (x > 0.0) ? 1.0 : ((x < 0.0) ? -1.0 : zero) end |
.sign(x, zero = 0.0) ⇒ Object
Sign of ‘x`. This function returns `-1.0` if `x` is negative, `+1.0` if `x` is positive `x`, and `0.0` if `x = 0`.
5 6 7 |
# File 'lib/standard/facets/math/sign.rb', line 5 def self.sign(x, zero=0.0) (x > 0.0) ? 1.0 : ((x < 0.0) ? -1.0 : zero) end |
.sinc(x) ⇒ Object
Sinc function of x
.
4 5 6 |
# File 'lib/standard/facets/math/sinc.rb', line 4 def self.sinc(x) (x == 0.0) ? 1.0 : sin(x) / x end |
.sqr(x) ⇒ Object
Square of number.
4 5 6 |
# File 'lib/standard/facets/math/sqr.rb', line 4 def self.sqr(x) x * x end |
.sqsolve(a, b, c, d = 0.0) ⇒ Object
Returns array of real solution of ax**2 + bx + c = d
or nil
if no or an infinite number of solutions exist. If d
is missing it is assumed to be 0.
In order to solve ax**2 + bx + c = d
sqsolve
identifies several cases:
-
a == 0:
The equation to be solved is the linear equationbx + c = d
. #sqsolve> delegates the computation to #linsolve>. If it results innil
,nil
is returned (not[nil]
!). Otherwise a one-element array containing result of #linsolve is returned. -
a != 0:
The equation to be solved actually is a second order one. * <code>c == d</code> The equation to be solved is <code>ax**2 + bx = 0</code>. One solution of this equation obviously is <code>x = 0</code>, the second one solves <code>ax + b = 0</code>. The solution of the latter is delegated to +linsolve+. An array containing both results in ascending order is returned. * <code>c != d</code> The equation cannot be separated into <code>x</code> times some factor. * <code>b == 0</code> The equation to be solved is <code>ax**2 + c = d</code>. This can be written as the linear equation <code>ay + c = d</code> with <code>y = x ** 2</code>. The solution of the linear equation is delegated to +linsolve+. If the returned value for +y+ is +nil+, that becomes the overall return value. Otherwise an array containing the negative and positive squareroot of +y+ is returned * <code>b != 0 </code> The equation cannot be reduced to simpler cases. We now first have to compute what is called the discriminant <code>x = b**2 + 4a(d - c)</code> (that's what we need to compute the square root of). If the descriminant is negative no real solution exists and <code>nil</code> is returned. The ternary operator checking whether <code>b</code> is negative does ensure better numerical stability --only one of the two solutions is computed using the widely know formula for solving second order equations. The second one is computed from the fact that the product of both solutions is <code>(c - d) / a</code>. Take a look at a book on numerical mathematics if you don't understand why this should be done.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/standard/facets/math/sqsolve.rb', line 37 def self.sqsolve(a, b, c, d = 0.0) if a == 0.0 x = linsolve(b, c, d) return x.nil? ? nil: [ linsolve(b, c, d) ] else return [0.0, linsolve(a, b)].sort if c == d if b == 0.0 x = linsolve(a, c, d) x < 0.0 ? nil : [-Math.sqrt(x), Math.sqrt(x)] else x = b * b + 4.0 * a * (d - c) return nil if x < 0.0 x = b < 0 ? b - Math.sqrt(x) : b + Math.sqrt(x) [-0.5 * x / a, 2.0 * (d - c) / x].sort end end end |
.std(array, &block) ⇒ Object Also known as: standard_deviation
Standard deviation of a sample.
7 8 9 |
# File 'lib/standard/facets/math/std.rb', line 7 def self.std(array, &block) sqrt(variance(array, &block)) end |
.stderr(array) ⇒ Object
Calculates the standard error of a sample.
22 23 24 25 |
# File 'lib/standard/facets/math/std.rb', line 22 def self.stderr(array) return 0.0 if array.size < 2 std(array) / sqrt(array.size) end |
.sum(array) ⇒ Object
Returns sum. When a block is given, summation is taken over the each result of block evaluation.
6 7 8 9 10 11 12 13 14 |
# File 'lib/standard/facets/math/sum.rb', line 6 def self.sum(array) #:yield: sum = 0.0 if block_given? array.each{|i| sum += yield(i)} else array.each{|i| sum += i} end sum end |
.summed_sqdevs(array) ⇒ Object
The sum of the squared deviations from the mean.
8 9 10 11 12 |
# File 'lib/standard/facets/math/summed_sqdevs.rb', line 8 def self.summed_sqdevs(array) return 0 if array.size < 2 m = mean(array) sum(array.map{ |x| (x - m) ** 2 }) end |
.tgamma(x) ⇒ Object
Exp of LGamma.
6 7 8 |
# File 'lib/standard/facets/math/tgamma.rb', line 6 def self.tgamma(x) exp(lngamma(x)) #exp(log(gamma(x).abs) end |
.theil_index(array) ⇒ Object
Calculates the Theil index (a statistic used to measure economic inequality).
TI = sum_i=1^N fracx_isum_{j=1^N x_j} ln fracx_ibar{x}
http://en.wikipedia.org/wiki/Theil_index
14 15 16 17 18 19 20 21 22 |
# File 'lib/standard/facets/math/theil_index.rb', line 14 def self.theil_index(array) return -1 if array.size <= 0 or any? { |x| x < 0 } return 0 if array.size < 2 or all? { |x| approx_equal(x, 0) } m = mean(array) s = sum(array).to_f inject(0) do |theil, xi| theil + ((xi > 0) ? (log(xi.to_f/m) * xi.to_f/s) : 0.0) end end |
.unit_step(x, zero = 1.0) ⇒ Object
The *Heaviside step function*, also called the the *unit step function*. This functions works like ‘Math.sign` but by default returns `1.0` for zero.
16 17 18 |
# File 'lib/standard/facets/math/sign.rb', line 16 def self.unit_step(x, zero=1.0) (x > 0.0) ? 1.0 : ((x < 0.0) ? -1.0 : zero) end |
.variance(array, &block) ⇒ Object
6 7 8 9 10 11 12 13 |
# File 'lib/standard/facets/math/variance.rb', line 6 def self.variance(array, &block) sum2 = if block_given? sum(array){ |i| j = block[i]; j*j } else sum(array){ |i| i**2 } end sum2/array.size - mean(array, &block)**2 end |
.variance2(array) ⇒ Object
Variance of the sample. Variance of 0 or 1 elements is 0.0.
TODO: Same as #variance? Then choose one.
19 20 21 22 |
# File 'lib/standard/facets/math/variance.rb', line 19 def self.variance2(array) return 0.0 if array.size < 2 summed_sqdevs(array) / (array.size - 1) end |
Instance Method Details
#acsch(x) ⇒ Object
Area cosecans hyperbolicus of x
4 5 6 |
# File 'lib/standard/facets/math/acsch.rb', line 4 def acsch(x) ::Math.log(1.0 / x + Math.sqrt(1.0 + 1.0 / (x * x))) end |
#asech(x) ⇒ Object
Area secans hyperbolicus of x
4 5 6 |
# File 'lib/standard/facets/math/asech.rb', line 4 def asech(x) log((1.0 + sqrt(1.0 - x * x)) / x) end |