more_math 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +28 -1
- data/README.md +25 -54
- data/Rakefile +8 -2
- data/lib/more_math/cantor_pairing_function.rb +59 -0
- data/lib/more_math/constants/functions_constants.rb +37 -0
- data/lib/more_math/continued_fraction.rb +170 -60
- data/lib/more_math/distributions.rb +98 -9
- data/lib/more_math/entropy.rb +74 -2
- data/lib/more_math/exceptions.rb +26 -0
- data/lib/more_math/functions.rb +140 -4
- data/lib/more_math/histogram.rb +86 -3
- data/lib/more_math/linear_regression.rb +108 -7
- data/lib/more_math/newton_bisection.rb +71 -8
- data/lib/more_math/numberify_string_function.rb +96 -20
- data/lib/more_math/permutation.rb +132 -27
- data/lib/more_math/ranking_common.rb +38 -10
- data/lib/more_math/sequence/moving_average.rb +27 -0
- data/lib/more_math/sequence/refinement.rb +26 -0
- data/lib/more_math/sequence.rb +177 -66
- data/lib/more_math/string_numeral.rb +172 -4
- data/lib/more_math/subset.rb +49 -5
- data/lib/more_math/version.rb +1 -1
- data/lib/more_math.rb +1 -0
- data/more_math.gemspec +4 -3
- metadata +17 -3
@@ -3,61 +3,119 @@ require 'more_math/constants/functions_constants'
|
|
3
3
|
|
4
4
|
module MoreMath
|
5
5
|
# This class is used to compute the Normal Distribution.
|
6
|
+
#
|
7
|
+
# The normal distribution is a continuous probability distribution that
|
8
|
+
# describes real-valued random variables whose distributions are symmetric
|
9
|
+
# around their mean.
|
10
|
+
#
|
11
|
+
# @example Creating a normal distribution
|
12
|
+
# # Standard normal (mean=0, std_dev=1)
|
13
|
+
# norm = MoreMath::NormalDistribution.new
|
14
|
+
#
|
15
|
+
# # Custom parameters
|
16
|
+
# custom_norm = MoreMath::NormalDistribution.new(5.0, 2.0) # mean=5, std_dev=2
|
17
|
+
#
|
18
|
+
# @example Calculating probabilities
|
19
|
+
# norm = MoreMath::NormalDistribution.new
|
20
|
+
# p = norm.probability(1.96) # Cumulative probability at z=1.96
|
21
|
+
# x = norm.inverse_probability(0.975) # Inverse: find z such that P(Z <= z) = 0.975
|
6
22
|
class NormalDistribution
|
7
23
|
include Functions
|
8
24
|
include Constants::FunctionsConstants
|
9
25
|
|
10
26
|
# Creates a NormalDistribution instance for the values +mu+ and +sigma+.
|
27
|
+
#
|
28
|
+
# @param mu [Numeric] The mean of the distribution (default: 0.0)
|
29
|
+
# @param sigma [Numeric] The standard deviation of the distribution (default: 1.0)
|
11
30
|
def initialize(mu = 0.0, sigma = 1.0)
|
12
31
|
@mu, @sigma = mu.to_f, sigma.to_f
|
13
32
|
end
|
14
33
|
|
34
|
+
# Returns the mean of this normal distribution.
|
35
|
+
#
|
36
|
+
# @return [Float] The mean value
|
15
37
|
attr_reader :mu
|
16
38
|
|
39
|
+
# Returns the standard deviation of this normal distribution.
|
40
|
+
#
|
41
|
+
# @return [Float] The standard deviation value
|
17
42
|
attr_reader :sigma
|
18
43
|
|
19
44
|
# Returns the cumulative probability (p-value) of the NormalDistribution
|
20
45
|
# for the value +x+.
|
46
|
+
#
|
47
|
+
# This calculates P(X <= x) where X ~ N(μ, σ²).
|
48
|
+
#
|
49
|
+
# @param x [Numeric] The value at which to calculate the cumulative probability
|
50
|
+
# @return [Float] The cumulative probability P(X <= x)
|
21
51
|
def probability(x)
|
22
52
|
0.5 * (1 + erf((x - @mu) / (@sigma * ROOT2)))
|
23
53
|
end
|
24
54
|
|
25
55
|
# Returns the inverse cumulative probability value of the
|
26
56
|
# NormalDistribution for the probability +p+.
|
57
|
+
#
|
58
|
+
# This finds the value x such that P(X <= x) = p where X ~ N(μ, σ²).
|
59
|
+
#
|
60
|
+
# @param p [Numeric] The probability (0 < p < 1)
|
61
|
+
# @return [Float] The inverse cumulative probability (quantile)
|
27
62
|
def inverse_probability(p)
|
28
63
|
case
|
29
64
|
when p <= 0
|
30
|
-
-1 / 0.0
|
65
|
+
-1 / 0.0 # Negative infinity
|
31
66
|
when p >= 1
|
32
|
-
1 / 0.0
|
67
|
+
1 / 0.0 # Positive infinity
|
33
68
|
when (p - 0.5).abs <= Float::EPSILON
|
34
|
-
@mu
|
69
|
+
@mu # Median equals mean for normal distribution
|
35
70
|
else
|
36
71
|
begin
|
37
72
|
NewtonBisection.new { |x| probability(x) - p }.solve(nil, 1_000_000)
|
38
73
|
rescue
|
39
|
-
0 / 0.0
|
74
|
+
0 / 0.0 # NaN on error
|
40
75
|
end
|
41
76
|
end
|
42
77
|
end
|
43
78
|
end
|
44
79
|
|
80
|
+
# A predefined instance of the standard normal distribution (mean=0, std_dev=1).
|
81
|
+
#
|
82
|
+
# @return [NormalDistribution] Standard normal distribution instance
|
45
83
|
STD_NORMAL_DISTRIBUTION = NormalDistribution.new
|
46
84
|
|
47
85
|
# This class is used to compute the Chi-Square Distribution.
|
86
|
+
#
|
87
|
+
# The chi-square distribution is a continuous probability distribution
|
88
|
+
# that arises in the analysis of variance and goodness-of-fit tests.
|
89
|
+
#
|
90
|
+
# @example Creating a chi-square distribution
|
91
|
+
# chi2 = MoreMath::ChiSquareDistribution.new(5) # 5 degrees of freedom
|
92
|
+
#
|
93
|
+
# @example Calculating probabilities
|
94
|
+
# chi2 = MoreMath::ChiSquareDistribution.new(5)
|
95
|
+
# p = chi2.probability(10.645) # Probability that X <= 10.645
|
48
96
|
class ChiSquareDistribution
|
49
97
|
include Functions
|
50
98
|
|
51
99
|
# Creates a ChiSquareDistribution for +df+ degrees of freedom.
|
100
|
+
#
|
101
|
+
# @param df [Integer] The degrees of freedom
|
52
102
|
def initialize(df)
|
53
103
|
@df = df
|
54
104
|
@df_half = @df / 2.0
|
55
105
|
end
|
56
106
|
|
107
|
+
# Returns the degrees of freedom of this distribution.
|
108
|
+
#
|
109
|
+
# @return [Integer] The degrees of freedom
|
57
110
|
attr_reader :df
|
58
111
|
|
59
112
|
# Returns the cumulative probability (p-value) of the ChiSquareDistribution
|
60
113
|
# for the value +x+.
|
114
|
+
#
|
115
|
+
# This calculates P(X <= x) where X ~ χ²(df).
|
116
|
+
#
|
117
|
+
# @param x [Numeric] The value at which to calculate the cumulative probability
|
118
|
+
# @return [Float] The cumulative probability P(X <= x)
|
61
119
|
def probability(x)
|
62
120
|
if x < 0
|
63
121
|
0.0
|
@@ -67,7 +125,12 @@ module MoreMath
|
|
67
125
|
end
|
68
126
|
|
69
127
|
# Returns the inverse cumulative probability value of the
|
70
|
-
#
|
128
|
+
# ChiSquareDistribution for the probability +p+.
|
129
|
+
#
|
130
|
+
# This finds the value x such that P(X <= x) = p where X ~ χ²(df).
|
131
|
+
#
|
132
|
+
# @param p [Numeric] The probability (0 < p < 1)
|
133
|
+
# @return [Float] The inverse cumulative probability (quantile)
|
71
134
|
def inverse_probability(p)
|
72
135
|
case
|
73
136
|
when p <= 0, p >= 1
|
@@ -78,26 +141,47 @@ module MoreMath
|
|
78
141
|
range = bisect.bracket 0.5..10
|
79
142
|
bisect.solve(range, 1_000_000)
|
80
143
|
rescue
|
81
|
-
0 / 0.0
|
144
|
+
0 / 0.0 # NaN on error
|
82
145
|
end
|
83
146
|
end
|
84
147
|
end
|
85
148
|
end
|
86
149
|
|
87
150
|
# This class is used to compute the T-Distribution.
|
151
|
+
#
|
152
|
+
# The t-distribution (Student's t-distribution) is a probability distribution
|
153
|
+
# that is used when estimating the mean of a normally distributed population
|
154
|
+
# in situations where the sample size is small and the population standard
|
155
|
+
# deviation is unknown.
|
156
|
+
#
|
157
|
+
# @example Creating a t-distribution
|
158
|
+
# t_dist = MoreMath::TDistribution.new(10) # 10 degrees of freedom
|
159
|
+
#
|
160
|
+
# @example Calculating probabilities
|
161
|
+
# t_dist = MoreMath::TDistribution.new(10)
|
162
|
+
# p = t_dist.probability(2.228) # Probability that X <= 2.228
|
88
163
|
class TDistribution
|
89
164
|
include Functions
|
90
165
|
|
91
166
|
# Returns a TDistribution instance for the degrees of freedom +df+.
|
167
|
+
#
|
168
|
+
# @param df [Integer] The degrees of freedom
|
92
169
|
def initialize(df)
|
93
170
|
@df = df
|
94
171
|
end
|
95
172
|
|
96
173
|
# Degrees of freedom.
|
174
|
+
#
|
175
|
+
# @return [Integer] The degrees of freedom
|
97
176
|
attr_reader :df
|
98
177
|
|
99
178
|
# Returns the cumulative probability (p-value) of the TDistribution for the
|
100
179
|
# t-value +x+.
|
180
|
+
#
|
181
|
+
# This calculates P(X <= x) where X ~ t(df).
|
182
|
+
#
|
183
|
+
# @param x [Numeric] The t-value at which to calculate the cumulative probability
|
184
|
+
# @return [Float] The cumulative probability P(X <= x)
|
101
185
|
def probability(x)
|
102
186
|
if x == 0
|
103
187
|
0.5
|
@@ -113,19 +197,24 @@ module MoreMath
|
|
113
197
|
|
114
198
|
# Returns the inverse cumulative probability (t-value) of the TDistribution
|
115
199
|
# for the probability +p+.
|
200
|
+
#
|
201
|
+
# This finds the value x such that P(X <= x) = p where X ~ t(df).
|
202
|
+
#
|
203
|
+
# @param p [Numeric] The probability (0 < p < 1)
|
204
|
+
# @return [Float] The inverse cumulative probability (quantile)
|
116
205
|
def inverse_probability(p)
|
117
206
|
case
|
118
207
|
when p <= 0
|
119
|
-
-1 / 0.0
|
208
|
+
-1 / 0.0 # Negative infinity
|
120
209
|
when p >= 1
|
121
|
-
1 / 0.0
|
210
|
+
1 / 0.0 # Positive infinity
|
122
211
|
else
|
123
212
|
begin
|
124
213
|
bisect = NewtonBisection.new { |x| probability(x) - p }
|
125
214
|
range = bisect.bracket(-10..10)
|
126
215
|
bisect.solve(range, 1_000_000)
|
127
216
|
rescue
|
128
|
-
0 / 0.0
|
217
|
+
0 / 0.0 # NaN on error
|
129
218
|
end
|
130
219
|
end
|
131
220
|
end
|
data/lib/more_math/entropy.rb
CHANGED
@@ -1,5 +1,41 @@
|
|
1
1
|
module MoreMath
|
2
|
+
# Provides entropy calculation utilities for measuring information content
|
3
|
+
# and randomness in text data.
|
4
|
+
#
|
5
|
+
# This module implements Shannon entropy calculations to quantify the
|
6
|
+
# unpredictability or information content of text strings. It's commonly used
|
7
|
+
# in cryptography, data compression, and information theory applications.
|
8
|
+
#
|
9
|
+
# The entropy measures help determine how "random" or "predictable" a text is,
|
10
|
+
# which can be useful for:
|
11
|
+
# - Password strength analysis
|
12
|
+
# - Data compression efficiency estimation
|
13
|
+
# - Cryptographic security assessment
|
14
|
+
# - Text analysis and classification
|
15
|
+
#
|
16
|
+
# @example Basic usage
|
17
|
+
# require 'more_math'
|
18
|
+
# include MoreMath
|
19
|
+
#
|
20
|
+
# text = "hello world"
|
21
|
+
# puts entropy(text) # => 2.3219280948873626
|
22
|
+
# puts entropy_ratio(text) # => 0.7428571428571429
|
23
|
+
#
|
24
|
+
# @example Using with different text samples
|
25
|
+
# MoreMath::Entropy.entropy("aaaa") # => 0.0 (no entropy)
|
26
|
+
# MoreMath::Entropy.entropy("abcd") # => 2.0 (maximum entropy)
|
2
27
|
module Entropy
|
28
|
+
# Calculates the Shannon entropy of a text string.
|
29
|
+
#
|
30
|
+
# Shannon entropy measures the average amount of information (in bits) needed
|
31
|
+
# to encode characters in the text based on their frequencies.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# MoreMath::Entropy.entropy("hello") # => 2.3219280948873626
|
35
|
+
# MoreMath::Entropy.entropy("aaaa") # => 0.0
|
36
|
+
#
|
37
|
+
# @param text [String] The input text to calculate entropy for
|
38
|
+
# @return [Float] The Shannon entropy in bits
|
3
39
|
def entropy(text)
|
4
40
|
chars = text.chars
|
5
41
|
size = chars.size
|
@@ -11,14 +47,50 @@ module MoreMath
|
|
11
47
|
end.abs
|
12
48
|
end
|
13
49
|
|
50
|
+
# Calculates the ideal (maximum) entropy for a given character set size.
|
51
|
+
#
|
52
|
+
# This represents the maximum possible entropy when all characters in the
|
53
|
+
# alphabet have equal probability of occurrence.
|
54
|
+
#
|
55
|
+
# @example
|
56
|
+
# MoreMath::Entropy.entropy_ideal(2) # => 1.0
|
57
|
+
# MoreMath::Entropy.entropy_ideal(256) # => 8.0
|
58
|
+
#
|
59
|
+
# @param size [Integer] The number of unique characters in the alphabet
|
60
|
+
# @return [Float] The maximum possible entropy in bits
|
14
61
|
def entropy_ideal(size)
|
15
62
|
size <= 1 and return 0.0
|
16
63
|
frequency = 1.0 / size
|
17
64
|
-1.0 * size * frequency * Math.log2(frequency)
|
18
65
|
end
|
19
66
|
|
20
|
-
|
21
|
-
|
67
|
+
|
68
|
+
# Calculates the normalized entropy ratio of a text string.
|
69
|
+
#
|
70
|
+
# The ratio is calculated as actual entropy divided by ideal entropy,
|
71
|
+
# giving a value between 0 and 1 where:
|
72
|
+
# - 0 indicates no entropy (all characters are identical)
|
73
|
+
# - 1 indicates maximum entropy (uniform distribution across the alphabet)
|
74
|
+
#
|
75
|
+
# The normalization uses the specified alphabet size to calculate the
|
76
|
+
# theoretical maximum entropy for that character set.
|
77
|
+
#
|
78
|
+
# @example
|
79
|
+
# MoreMath::Entropy.entropy_ratio("hello") # => 0.6834
|
80
|
+
# MoreMath::Entropy.entropy_ratio("aaaaa") # => 0.0
|
81
|
+
# MoreMath::Entropy.entropy_ratio("abcde") # => 1.0
|
82
|
+
#
|
83
|
+
# @example With custom alphabet size
|
84
|
+
# # Normalizing against a 26-letter alphabet (English)
|
85
|
+
# MoreMath::Entropy.entropy_ratio("hello", size: 26) # => 0.394...
|
86
|
+
#
|
87
|
+
# @param text [String] The input text to calculate entropy ratio for
|
88
|
+
# @param size [Integer] The size of the character set to normalize against.
|
89
|
+
# Defaults to the total length of the text (`text.each_char.size`), which
|
90
|
+
# normalizes the entropy relative to the text's own character space.
|
91
|
+
# This allows comparison of texts with different lengths on the same scale.
|
92
|
+
# @return [Float] Normalized entropy ratio between 0 and 1
|
93
|
+
def entropy_ratio(text, size: text.each_char.size)
|
22
94
|
size <= 1 and return 0.0
|
23
95
|
entropy(text) / entropy_ideal(size)
|
24
96
|
end
|
data/lib/more_math/exceptions.rb
CHANGED
@@ -1,6 +1,32 @@
|
|
1
1
|
module MoreMath
|
2
|
+
# Module containing custom exception classes for the MoreMath library
|
2
3
|
module Exceptions
|
4
|
+
# Base exception class for all MoreMath exceptions
|
5
|
+
#
|
6
|
+
# All custom exceptions in the MoreMath library inherit from this class
|
7
|
+
#
|
8
|
+
# @example Handling a MoreMath exception
|
9
|
+
# begin
|
10
|
+
# # Some MoreMath operation
|
11
|
+
# rescue MoreMath::Exceptions::MoreMathException => e
|
12
|
+
# puts "MoreMath error: #{e.message}"
|
13
|
+
# end
|
3
14
|
class MoreMathException < StandardError; end
|
15
|
+
|
16
|
+
# Exception raised when a mathematical computation diverges or fails to converge
|
17
|
+
#
|
18
|
+
# This exception is typically raised when numerical methods fail to produce
|
19
|
+
# meaningful results due to divergence, such as:
|
20
|
+
# - Non-converging series expansions
|
21
|
+
# - Divergent continued fractions
|
22
|
+
# - Failed root finding algorithms
|
23
|
+
#
|
24
|
+
# @example Handling a divergent computation
|
25
|
+
# begin
|
26
|
+
# # Some divergent operation
|
27
|
+
# rescue MoreMath::Exceptions::DivergentException => e
|
28
|
+
# puts "Computation diverged: #{e.message}"
|
29
|
+
# end
|
4
30
|
class DivergentException < MoreMathException ; end
|
5
31
|
end
|
6
32
|
end
|
data/lib/more_math/functions.rb
CHANGED
@@ -1,19 +1,44 @@
|
|
1
1
|
require 'more_math/entropy'
|
2
2
|
|
3
3
|
module MoreMath
|
4
|
+
# Provides mathematical functions and special functions for scientific computing.
|
5
|
+
#
|
6
|
+
# This module includes implementations of various mathematical functions commonly
|
7
|
+
# used in statistics, numerical analysis, and scientific computing. It extends
|
8
|
+
# Ruby's built-in Math module with additional functionality and provides
|
9
|
+
# specialized implementations for better accuracy and performance.
|
10
|
+
#
|
11
|
+
# @example Using mathematical functions
|
12
|
+
# include MoreMath::Functions
|
13
|
+
#
|
14
|
+
# # Gamma function calculation
|
15
|
+
# gamma(5) # => ~ 24.0 (4!)
|
16
|
+
# gamma(0.5) # => ~ 1.772 (sqrt(pi))
|
17
|
+
#
|
18
|
+
# # Beta function calculation
|
19
|
+
# beta(2, 3) # => ~ 0.083 (B(2,3) = Gamma(2)*Gamma(3)/Gamma(5))
|
20
|
+
#
|
21
|
+
# # Error function
|
22
|
+
# erf(1) # => ~ 0.843
|
4
23
|
module Functions
|
5
24
|
module_function
|
6
25
|
|
7
26
|
include Math
|
8
27
|
extend Math
|
9
28
|
|
10
|
-
# Returns the natural logarithm of Euler gamma function value for +x+ using
|
11
|
-
# the Lanczos approximation.
|
12
29
|
if Math.respond_to?(:lgamma)
|
30
|
+
# The log_gamma function extends the factorial to real and complex
|
31
|
+
# numbers. For positive integers, Gamma(n) = (n-1)!.
|
32
|
+
#
|
33
|
+
# @param x [Numeric] The input value for which to calculate log_gamma
|
34
|
+
# @return [Float] Natural logarithm of the gamma function at x
|
35
|
+
# @raise [ZeroDivisionError] When x is zero or a negative integer
|
13
36
|
def log_gamma(x)
|
14
37
|
lgamma(x).first
|
15
38
|
end
|
16
39
|
else
|
40
|
+
# Returns the natural logarithm of Euler gamma function value for +x+
|
41
|
+
# using the Lanczos approximation if not provided by Ruby.
|
17
42
|
def log_gamma(x)
|
18
43
|
x = x.to_f
|
19
44
|
if x.nan? || x <= 0
|
@@ -35,6 +60,13 @@ module MoreMath
|
|
35
60
|
end
|
36
61
|
|
37
62
|
# Returns the value of the gamma function, extended to a negative domain.
|
63
|
+
#
|
64
|
+
# The gamma function is defined for all complex numbers except non-positive integers.
|
65
|
+
# For positive real numbers, it extends the factorial: Gamma(n) = (n-1)!
|
66
|
+
#
|
67
|
+
# @param x [Numeric] The input value for which to calculate gamma
|
68
|
+
# @return [Float] The gamma function value at x
|
69
|
+
# @raise [ZeroDivisionError] When x is a non-positive integer
|
38
70
|
def gamma(x)
|
39
71
|
if x < 0.0
|
40
72
|
return PI / (sin(PI * x) * exp(log_gamma(1 - x)))
|
@@ -44,6 +76,13 @@ module MoreMath
|
|
44
76
|
end
|
45
77
|
|
46
78
|
# Returns the natural logarithm of the beta function value for +(a, b)+.
|
79
|
+
#
|
80
|
+
# The beta function is defined as B(a,b) = Gamma(a)*Gamma(b)/Gamma(a+b)
|
81
|
+
# and is commonly used in statistics and probability theory.
|
82
|
+
#
|
83
|
+
# @param a [Numeric] First parameter of the beta function
|
84
|
+
# @param b [Numeric] Second parameter of the beta function
|
85
|
+
# @return [Float] Natural logarithm of the beta function at (a,b)
|
47
86
|
def log_beta(a, b)
|
48
87
|
log_gamma(a) + log_gamma(b) - log_gamma(a + b)
|
49
88
|
rescue Errno::ERANGE, Errno::EDOM
|
@@ -51,6 +90,13 @@ module MoreMath
|
|
51
90
|
end
|
52
91
|
|
53
92
|
# Returns the value of the beta function for +(a, b)+, +a > 0, b > 0'.
|
93
|
+
#
|
94
|
+
# The beta function B(a,b) = Gamma(a)*Gamma(b)/Gamma(a+b) is used in
|
95
|
+
# statistical distributions and probability theory.
|
96
|
+
#
|
97
|
+
# @param a [Numeric] First parameter (must be > 0)
|
98
|
+
# @param b [Numeric] Second parameter (must be > 0)
|
99
|
+
# @return [Float] The beta function value at (a,b)
|
54
100
|
def beta(a, b)
|
55
101
|
if a > 0 && b > 0
|
56
102
|
exp(log_beta(a, b))
|
@@ -62,6 +108,16 @@ module MoreMath
|
|
62
108
|
# Return an approximation value of Euler's regularized beta function for
|
63
109
|
# +x+, +a+, and +b+ with an error <= +epsilon+, but only iterate
|
64
110
|
# +max_iterations+-times.
|
111
|
+
#
|
112
|
+
# The regularized incomplete beta function I_x(a,b) = B(x;a,b)/B(a,b)
|
113
|
+
# is used in statistics to compute probabilities for the beta distribution.
|
114
|
+
#
|
115
|
+
# @param x [Numeric] The upper limit of integration (0 <= x <= 1)
|
116
|
+
# @param a [Numeric] First shape parameter (a > 0)
|
117
|
+
# @param b [Numeric] Second shape parameter (b > 0)
|
118
|
+
# @param epsilon [Float] Convergence tolerance (default: 1E-16)
|
119
|
+
# @param max_iterations [Integer] Maximum number of iterations (default: 65536)
|
120
|
+
# @return [Float] Regularized incomplete beta function value
|
65
121
|
def beta_regularized(x, a, b, epsilon: 1E-16, max_iterations: 1 << 16)
|
66
122
|
x, a, b = x.to_f, a.to_f, b.to_f
|
67
123
|
case
|
@@ -89,6 +145,16 @@ module MoreMath
|
|
89
145
|
# Return an approximation of the regularized gammaP function for +x+ and
|
90
146
|
# +a+ with an error of <= +epsilon+, but only iterate
|
91
147
|
# +max_iterations+-times.
|
148
|
+
#
|
149
|
+
# The regularized lower incomplete gamma function P(a,x) = γ(a,x)/Γ(a)
|
150
|
+
# where γ(a,x) is the lower incomplete gamma function. This is used in
|
151
|
+
# statistics to compute probabilities for the gamma distribution.
|
152
|
+
#
|
153
|
+
# @param x [Numeric] Upper limit of integration (x >= 0)
|
154
|
+
# @param a [Numeric] Shape parameter (a > 0)
|
155
|
+
# @param epsilon [Float] Convergence tolerance (default: 1E-16)
|
156
|
+
# @param max_iterations [Integer] Maximum number of iterations (default: 65536)
|
157
|
+
# @return [Float] Regularized lower incomplete gamma function value
|
92
158
|
def gammaP_regularized(x, a, epsilon: 1E-16, max_iterations: 1 << 16)
|
93
159
|
x, a = x.to_f, a.to_f
|
94
160
|
case
|
@@ -120,6 +186,16 @@ module MoreMath
|
|
120
186
|
# Return an approximation of the regularized gammaQ function for +x+ and
|
121
187
|
# +a+ with an error of <= +epsilon+, but only iterate
|
122
188
|
# +max_iterations+-times.
|
189
|
+
#
|
190
|
+
# The regularized upper incomplete gamma function Q(a,x) = Γ(a,x)/Γ(a)
|
191
|
+
# where Γ(a,x) is the upper incomplete gamma function. This is used in
|
192
|
+
# statistics to compute probabilities for the gamma distribution.
|
193
|
+
#
|
194
|
+
# @param x [Numeric] Upper limit of integration (x >= 0)
|
195
|
+
# @param a [Numeric] Shape parameter (a > 0)
|
196
|
+
# @param epsilon [Float] Convergence tolerance (default: 1E-16)
|
197
|
+
# @param max_iterations [Integer] Maximum number of iterations (default: 65536)
|
198
|
+
# @return [Float] Regularized upper incomplete gamma function value
|
123
199
|
def gammaQ_regularized(x, a, epsilon: 1E-16, max_iterations: 1 << 16)
|
124
200
|
x, a = x.to_f, a.to_f
|
125
201
|
case
|
@@ -143,7 +219,14 @@ module MoreMath
|
|
143
219
|
end
|
144
220
|
|
145
221
|
unless Math.respond_to?(:erf)
|
146
|
-
# Returns an approximate value for the error function's value for +x
|
222
|
+
# Returns an approximate value for the error function's value for +x+
|
223
|
+
# unless provided by Ruby.
|
224
|
+
#
|
225
|
+
# The error function erf(x) = (2/sqrt(pi)) * ∫₀ˣ e^(-t²) dt is used in probability,
|
226
|
+
# statistics, and partial differential equations.
|
227
|
+
#
|
228
|
+
# @param x [Numeric] Input value
|
229
|
+
# @return [Float] Error function value at x
|
147
230
|
def erf(x)
|
148
231
|
erf_a = MoreMath::Constants::FunctionsConstants::ERF_A
|
149
232
|
r = sqrt(1 - exp(-x ** 2 * (4 / Math::PI + erf_a * x ** 2) / (1 + erf_a * x ** 2)))
|
@@ -152,11 +235,27 @@ module MoreMath
|
|
152
235
|
end
|
153
236
|
|
154
237
|
unless Math.respond_to?(:erfc)
|
238
|
+
# Returns the complementary error function value for +x+ unless provided
|
239
|
+
# by Ruby.
|
240
|
+
#
|
241
|
+
# The complementary error function erfc(x) = 1 - erf(x) is used in probability
|
242
|
+
# and statistics when computing tail probabilities.
|
243
|
+
#
|
244
|
+
# @param x [Numeric] Input value
|
245
|
+
# @return [Float] Complementary error function value at x
|
155
246
|
def erfc(x)
|
156
247
|
1.0 - erf(x)
|
157
248
|
end
|
158
249
|
end
|
159
250
|
|
251
|
+
# Computes the ceiling of the base +b+ logarithm of +n+.
|
252
|
+
#
|
253
|
+
# Returns the smallest integer k such that b^k >= n.
|
254
|
+
#
|
255
|
+
# @param n [Integer] The number to compute log for (must be > 0)
|
256
|
+
# @param b [Integer] The base of the logarithm (must be > 1)
|
257
|
+
# @return [Integer] Ceiling of log_b(n)
|
258
|
+
# @raise [ArgumentError] If n <= 0 or b <= 1
|
160
259
|
def log_ceil(n, b = 2)
|
161
260
|
raise ArgumentError, "n is required to be > 0" unless n > 0
|
162
261
|
raise ArgumentError, "b is required to be > 1" unless b > 1
|
@@ -168,6 +267,14 @@ module MoreMath
|
|
168
267
|
result
|
169
268
|
end
|
170
269
|
|
270
|
+
# Computes the floor of the base +b+ logarithm of +n+.
|
271
|
+
#
|
272
|
+
# Returns the largest integer k such that b^k <= n.
|
273
|
+
#
|
274
|
+
# @param n [Integer] The number to compute log for (must be > 0)
|
275
|
+
# @param b [Integer] The base of the logarithm (must be > 1)
|
276
|
+
# @return [Integer] Floor of log_b(n)
|
277
|
+
# @raise [ArgumentError] If n <= 0 or b <= 1
|
171
278
|
def log_floor(n, b = 2)
|
172
279
|
raise ArgumentError, "n is required to be > 0" unless n > 0
|
173
280
|
raise ArgumentError, "b is required to be > 1" unless b > 1
|
@@ -179,35 +286,64 @@ module MoreMath
|
|
179
286
|
result
|
180
287
|
end
|
181
288
|
|
182
|
-
# Returns the base +b+ logarithm of the number +x+. +b+
|
289
|
+
# Returns the base +b+ logarithm of the number +x+. +b+ defaults to base
|
183
290
|
# 2, binary logarithm.
|
291
|
+
#
|
292
|
+
# @param x [Numeric] The number to compute log for (must be > 0)
|
293
|
+
# @param b [Numeric] The base of the logarithm (default: 2)
|
294
|
+
# @return [Float] Logarithm of x in base b
|
184
295
|
def logb(x, b = 2)
|
185
296
|
Math.log(x) / Math.log(b)
|
186
297
|
end
|
187
298
|
|
188
299
|
# Returns Cantor's tuple function for the tuple +*xs+ (the size must be at
|
189
300
|
# least 2).
|
301
|
+
#
|
302
|
+
# The Cantor pairing function uniquely encodes pairs of natural numbers
|
303
|
+
# into a single natural number. This implementation extends it to tuples.
|
304
|
+
#
|
305
|
+
# @param xs [Array<Integer>] Array of integers to encode
|
306
|
+
# @return [Integer] Unique natural number representing the tuple
|
190
307
|
def cantor_pairing(*xs)
|
191
308
|
CantorPairingFunction.cantor_pairing(*xs)
|
192
309
|
end
|
193
310
|
|
194
311
|
# Returns the inverse of Cantor's tuple function for the value +c+. +n+ is
|
195
312
|
# the length of the tuple (defaults to 2, a pair).
|
313
|
+
#
|
314
|
+
# Decodes a natural number back into its original tuple representation.
|
315
|
+
#
|
316
|
+
# @param c [Integer] The encoded natural number
|
317
|
+
# @param n [Integer] Length of the original tuple (default: 2)
|
318
|
+
# @return [Array<Integer>] Original tuple as array of integers
|
196
319
|
def cantor_pairing_inv(c, n = 2)
|
197
320
|
CantorPairingFunction.cantor_pairing_inv(c, n)
|
198
321
|
end
|
199
322
|
|
200
323
|
# Computes a Gödel number from +string+ in the +alphabet+ and returns it.
|
324
|
+
#
|
325
|
+
# Implements Gödel numbering to convert strings into unique natural numbers.
|
326
|
+
#
|
327
|
+
# @param string [String] The input string
|
328
|
+
# @param alphabet [Array<String>, Range<String>] The alphabet to use for conversion
|
329
|
+
# @return [Integer] Unique Gödel number representing the string
|
201
330
|
def numberify_string(string, alphabet = 'a'..'z')
|
202
331
|
NumberifyStringFunction.numberify_string(string, alphabet)
|
203
332
|
end
|
204
333
|
|
205
334
|
# Computes the string in the +alphabet+ from a Gödel number +number+ and
|
206
335
|
# returns it. This is the inverse function of numberify_string.
|
336
|
+
#
|
337
|
+
# Converts a natural number back to its original string representation.
|
338
|
+
#
|
339
|
+
# @param number [Integer] The Gödel number to convert
|
340
|
+
# @param alphabet [Array<String>, Range<String>] The alphabet to use for conversion
|
341
|
+
# @return [String] Original string represented by the number
|
207
342
|
def stringify_number(number, alphabet = 'a'..'z')
|
208
343
|
NumberifyStringFunction.stringify_number(number, alphabet)
|
209
344
|
end
|
210
345
|
|
346
|
+
# Includes entropy calculations functionality
|
211
347
|
include Entropy
|
212
348
|
end
|
213
349
|
end
|