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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 347b633c7b95cb4728828e2dcad06f04f824e340d72dc4192b0d81b7e3a2df6e
|
4
|
+
data.tar.gz: 5e1bd55c18723aa18ccab2b7c916811ba8c84f2fb251bcaeb323575da045f7d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41d4ce4dff93f65ef91cd5b414f205b8a64567d148586d2dd7d09f0327aafc802fb655ccdbe6e44da29241cb86f863ffa38104b0d13aa3cc34b2061049db18fe
|
7
|
+
data.tar.gz: bbd8bcfcb4fb17b3ad5ada2e069e1d969429de1f39c2d21305a4e8d7e56dbe3f96ec3d00411428711f82aa89293c2d15d5c028947250bc7f1670408971b1494d
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
## 2025-09-30 v1.6.0
|
4
|
+
|
5
|
+
- Replaced detailed feature sections in README with a concise bullet list of
|
6
|
+
MoreMath capabilities
|
7
|
+
- Added documentation link to GitHub.io and updated installation instructions
|
8
|
+
to include both RubyGems and Bundler
|
9
|
+
- Improved author and license formatting with proper markdown links
|
10
|
+
- Added `.github/workflows/static.yml` to automate documentation generation and
|
11
|
+
deployment using Ruby **3.4**
|
12
|
+
- Updated `Rakefile` to register new documentation workflow with GemHadar
|
13
|
+
- Configured workflow to use Ruby **3.4** for documentation builds and deploy
|
14
|
+
to GitHub Pages on master branch pushes
|
15
|
+
- Added `context_spook` as development dependency for YARD documentation
|
16
|
+
- Added `cscope.out` to `.gitignore` and updated `Rakefile` to include it in
|
17
|
+
the ignore list
|
18
|
+
- Added `code_indexer` configuration to `.utilsrc` with a list of gems
|
19
|
+
including **base64**, **bigdecimal**, **date**, **json**, **mize**,
|
20
|
+
**ostruct**, **rake**, **stringio**, **sync**, **test-unit**, and **tins**
|
21
|
+
- Added `doc` and `.yardoc` directories to gitignore and rake configuration
|
22
|
+
- Updated homepage URL to escape underscore character for proper rendering
|
23
|
+
- Updated `gem_hadar` development dependency from version **2.4** to **2.6**
|
24
|
+
- Modified `package_ignore` in Rakefile to explicitly include `.github` and
|
25
|
+
`.contexts` directories instead of using glob pattern `*.github/**/*`
|
26
|
+
- Enhanced documentation for all methods in MoreMath module
|
27
|
+
- Added documentation directories `.yardoc` and `doc` to `prune_dirs` in
|
28
|
+
utilsrc
|
29
|
+
|
3
30
|
## 2025-09-11 v1.5.0
|
4
31
|
|
5
32
|
- Updated `VERSION` file and `lib/more_math/version.rb` from version **1.4.0** to **1.5.0**
|
@@ -9,7 +36,7 @@
|
|
9
36
|
- Added runtime dependency on `mize` (">= 0")
|
10
37
|
- Set rubygems version to **3.6.9**
|
11
38
|
- Included all library files in `s.files` and `s.extra_rdoc_files`
|
12
|
-
- Set homepage to "https://github.com/flori/
|
39
|
+
- Set homepage to "https://github.com/flori/more\_math"
|
13
40
|
- Set license to "MIT"
|
14
41
|
- Added `yaml-dev` to dockerfile build dependencies
|
15
42
|
- Installed `bundler` and `gem_hadar` gems in dockerfile
|
data/README.md
CHANGED
@@ -6,54 +6,22 @@ Ruby library that contains various mathematical functions and algorithms,
|
|
6
6
|
extending Ruby's capabilities in domains such as statistics, numerical
|
7
7
|
analysis, and combinatorics.
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
- **Random Number Generation**: Generates random numbers following specific
|
26
|
-
distributions.
|
27
|
-
- **Hypothesis Testing**: Performs tests like the Kolmogorov-Smirnov test
|
28
|
-
for distribution comparison.
|
29
|
-
|
30
|
-
4. **Sequence Analysis**
|
31
|
-
- **Moving Averages**: Computes simple moving averages for time series data.
|
32
|
-
- **Autocorrelation and Autovariance**: Analyzes the correlation structure
|
33
|
-
of sequences.
|
34
|
-
- **Histograms**: Visualizes data distributions with customizable bins.
|
35
|
-
|
36
|
-
5. **Combinatorics and Algorithms**
|
37
|
-
- **Permutations and Combinations**: Generates permutations, combinations,
|
38
|
-
and Cartesian products.
|
39
|
-
- **Graph Theory**: Includes algorithms for shortest paths (Dijkstra,
|
40
|
-
Floyd-Warshall) and minimum spanning trees.
|
41
|
-
- **Root Finding**: Uses Newton-Raphson and bisection methods to find roots
|
42
|
-
of functions.
|
43
|
-
|
44
|
-
### Specialized Modules
|
45
|
-
|
46
|
-
1. **String Numeral Conversion**
|
47
|
-
- Converts strings to Gödel numbers and vice versa using a specified
|
48
|
-
alphabet.
|
49
|
-
|
50
|
-
2. **Cantor Pairing Function**
|
51
|
-
- Encodes tuples into a single integer and decodes them back, useful in set
|
52
|
-
theory and combinatorics.
|
53
|
-
|
54
|
-
3. **Histograms**
|
55
|
-
- Creates histograms for data visualization with support for different
|
56
|
-
binning strategies.
|
9
|
+
MoreMath provides a comprehensive set of mathematical tools including:
|
10
|
+
- Advanced mathematical functions (gamma, beta, error functions)
|
11
|
+
- Mathematical constants and precision utilities
|
12
|
+
- Statistical distributions and hypothesis testing
|
13
|
+
- Sequence analysis and time series operations
|
14
|
+
- Combinatorial algorithms (permutations, subsets)
|
15
|
+
- Special functions (continued fractions, Cantor pairing)
|
16
|
+
- Data visualization tools (histograms)
|
17
|
+
- String numeral conversion and Gödel numbering
|
18
|
+
- Numerical integration methods
|
19
|
+
- Statistical quality control tools
|
20
|
+
- Information theory calculations
|
21
|
+
|
22
|
+
## Documentation
|
23
|
+
|
24
|
+
Complete API documentation is available at: [GitHub.io](https://flori.github.io/more_math/)
|
57
25
|
|
58
26
|
## Example Usage
|
59
27
|
|
@@ -86,21 +54,24 @@ Histogram.new([1, 2, 3, 4, 5, 1], bins: 3).display(STDOUT, 80) ; nil
|
|
86
54
|
|
87
55
|
## Installation
|
88
56
|
|
89
|
-
|
90
|
-
|
57
|
+
### Using RubyGems
|
91
58
|
```bash
|
92
59
|
gem install more_math
|
93
60
|
```
|
94
61
|
|
62
|
+
### Using Bundler
|
63
|
+
Add to your Gemfile:
|
64
|
+
```ruby
|
65
|
+
gem 'more_math'
|
66
|
+
```
|
67
|
+
|
95
68
|
## Author
|
96
69
|
|
97
|
-
Florian Frank
|
98
|
-
mailto:flori@ping.de
|
70
|
+
[Florian Frank](mailto:flori@ping.de)
|
99
71
|
|
100
72
|
## License
|
101
73
|
|
102
|
-
This software is licensed under the
|
103
|
-
http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3
|
74
|
+
This software is licensed under the [MIT License](./LICENSE).
|
104
75
|
|
105
76
|
## Homepage
|
106
77
|
|
data/Rakefile
CHANGED
@@ -11,11 +11,16 @@ GemHadar do
|
|
11
11
|
description 'Library that provides more mathematical functions/algorithms than standard Ruby.'
|
12
12
|
test_dir 'tests'
|
13
13
|
ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', 'coverage', '.rvmrc',
|
14
|
-
'.AppleDouble', 'tags', '.byebug_history', '.DS_Store', '.bundle'
|
14
|
+
'.AppleDouble', 'tags', '.byebug_history', '.DS_Store', '.bundle',
|
15
|
+
'.yardoc', 'doc', 'cscope.out'
|
15
16
|
readme 'README.md'
|
16
17
|
title "#{name.camelize} -- More Math in Ruby"
|
17
18
|
package_ignore '.all_images.yml', '.gitignore', 'VERSION', '.utilsrc',
|
18
|
-
|
19
|
+
'.github', '.contexts', '.contexts'
|
20
|
+
|
21
|
+
github_workflows(
|
22
|
+
'static.yml' => { }
|
23
|
+
)
|
19
24
|
|
20
25
|
required_ruby_version '>= 2.0'
|
21
26
|
dependency 'tins', '~>1'
|
@@ -25,5 +30,6 @@ GemHadar do
|
|
25
30
|
development_dependency 'test-unit'
|
26
31
|
development_dependency 'debug'
|
27
32
|
development_dependency 'all_images'
|
33
|
+
development_dependency 'context_spook'
|
28
34
|
licenses << 'MIT'
|
29
35
|
end
|
@@ -1,8 +1,39 @@
|
|
1
1
|
module MoreMath
|
2
|
+
# Provides Cantor pairing function implementations for encoding tuples into
|
3
|
+
# natural numbers and decoding them back.
|
4
|
+
#
|
5
|
+
# The Cantor pairing function is a mathematical construct that uniquely
|
6
|
+
# encodes pairs of natural numbers into a single natural number, and vice
|
7
|
+
# versa. This module implements both the forward pairing function and its
|
8
|
+
# inverse for arbitrary tuples of integers.
|
9
|
+
#
|
10
|
+
# @example Pairing two numbers
|
11
|
+
# CantorPairingFunction.cantor_pairing(5, 3) # => 39
|
12
|
+
#
|
13
|
+
# @example Pairing multiple numbers
|
14
|
+
# CantorPairingFunction.cantor_pairing(1, 2, 3) # => 69
|
15
|
+
#
|
16
|
+
# @example Inverse pairing
|
17
|
+
# CantorPairingFunction.cantor_pairing_inv(39) # => [5, 3]
|
18
|
+
#
|
19
|
+
# @example Inverse pairing for tuples
|
20
|
+
# CantorPairingFunction.cantor_pairing_inv(69, 3) # => [1, 2, 3]
|
2
21
|
module CantorPairingFunction
|
3
22
|
|
4
23
|
module_function
|
5
24
|
|
25
|
+
# Encodes multiple integers into a single natural number using the Cantor
|
26
|
+
# pairing function.
|
27
|
+
#
|
28
|
+
# This method implements the Cantor pairing function, which provides a
|
29
|
+
# unique encoding of tuples of natural numbers into a single natural
|
30
|
+
# number. For two integers, it uses the standard Cantor pairing formula.
|
31
|
+
# For more than two integers, it recursively applies the pairing function
|
32
|
+
# to reduce the tuple to a single value.
|
33
|
+
#
|
34
|
+
# @param xs [Array<Integer>] An array of integers to pair
|
35
|
+
# @return [Integer] A unique natural number representing the input tuple
|
36
|
+
# @raise [ArgumentError] When fewer than two arguments are provided
|
6
37
|
def cantor_pairing(*xs)
|
7
38
|
if xs.size == 1 and xs.first.respond_to?(:to_ary)
|
8
39
|
xs = xs.first.to_ary
|
@@ -18,10 +49,27 @@ module MoreMath
|
|
18
49
|
end
|
19
50
|
end
|
20
51
|
|
52
|
+
# Computes the cantor pairing function f(z) = z * (z + 1) / 2
|
53
|
+
#
|
54
|
+
# This helper method calculates a partial result used in the inverse cantor
|
55
|
+
# pairing function to compute the triangular number sequence that helps in
|
56
|
+
# decoding paired values
|
57
|
+
#
|
58
|
+
# @param z [Integer] The input value to compute the triangular number for
|
59
|
+
# @return [Integer] The computed triangular number value
|
21
60
|
def self.cantor_pairing_inv_f(z)
|
22
61
|
z * (z + 1) / 2
|
23
62
|
end
|
24
63
|
|
64
|
+
# Computes the quotient used in the inverse Cantor pairing function
|
65
|
+
#
|
66
|
+
# This method calculates the largest value v such that the Cantor pairing
|
67
|
+
# function applied to v is less than or equal to the given value z. It's a
|
68
|
+
# helper method that supports the inverse pairing algorithm by determining
|
69
|
+
# the appropriate triangular number boundary for decoding.
|
70
|
+
#
|
71
|
+
# @param z [Integer] The value to compute the quotient for
|
72
|
+
# @return [Integer] The computed quotient value v where cantor_pairing_inv_f(v) <= z
|
25
73
|
def self.cantor_pairing_inv_q(z)
|
26
74
|
v = 0
|
27
75
|
while cantor_pairing_inv_f(v) <= z
|
@@ -30,6 +78,17 @@ module MoreMath
|
|
30
78
|
v - 1
|
31
79
|
end
|
32
80
|
|
81
|
+
# Computes the inverse of the Cantor pairing function for a given value
|
82
|
+
#
|
83
|
+
# This method decodes a natural number back into its original tuple
|
84
|
+
# representation using the inverse Cantor pairing function. It supports
|
85
|
+
# decoding tuples of arbitrary length by recursively applying the inverse
|
86
|
+
# operation.
|
87
|
+
#
|
88
|
+
# @param c [Integer] The natural number to decode back into a tuple
|
89
|
+
# @param n [Integer] The length of the original tuple (default: 2)
|
90
|
+
# @return [Array<Integer>] The decoded tuple as an array of integers
|
91
|
+
# @raise [ArgumentError] When n is less than 2
|
33
92
|
def cantor_pairing_inv(c, n = 2)
|
34
93
|
raise ArgumentError, "n is required to be >= 2" unless n >= 2
|
35
94
|
result = []
|
@@ -1,6 +1,22 @@
|
|
1
1
|
module MoreMath
|
2
|
+
# Contains constant values used in mathematical function implementations.
|
3
|
+
#
|
4
|
+
# These constants are essential for high-precision numerical computations,
|
5
|
+
# particularly in the Lanczos approximation for gamma functions and error
|
6
|
+
# function approximations. The constants are carefully chosen to balance
|
7
|
+
# accuracy and computational efficiency.
|
2
8
|
module Constants
|
9
|
+
# Module containing mathematical constants used in function implementations
|
3
10
|
module FunctionsConstants
|
11
|
+
# Lanczos coefficients for gamma function approximation
|
12
|
+
#
|
13
|
+
# These coefficients are part of the Lanczos approximation formula,
|
14
|
+
# which provides a highly accurate method for computing the logarithm
|
15
|
+
# of the gamma function. The Lanczos method is particularly effective
|
16
|
+
# for maintaining numerical stability across a wide range of inputs.
|
17
|
+
#
|
18
|
+
# @note These values are precomputed for optimal accuracy in the
|
19
|
+
# Lanczos approximation algorithm
|
4
20
|
LANCZOS_COEFFICIENTS = [
|
5
21
|
0.99999999999999709182,
|
6
22
|
57.156235665862923517,
|
@@ -19,10 +35,31 @@ module MoreMath
|
|
19
35
|
0.36899182659531622704e-5,
|
20
36
|
]
|
21
37
|
|
38
|
+
# Precomputed value of half the natural logarithm of 2π
|
39
|
+
#
|
40
|
+
# This constant is used in Stirling's approximation and various
|
41
|
+
# statistical calculations. It's computed as:
|
42
|
+
# 0.5 * Math.log(2 * Math::PI)
|
43
|
+
#
|
44
|
+
# @note This value appears in the Lanczos approximation formula
|
45
|
+
# and other mathematical identities involving the gamma function
|
22
46
|
HALF_LOG_2_PI = 0.5 * Math.log(2 * Math::PI)
|
23
47
|
|
48
|
+
# Parameter for error function approximation
|
49
|
+
#
|
50
|
+
# This constant is used in the rational approximation of the error
|
51
|
+
# function. It's derived from the relationship:
|
52
|
+
# ERF_A = -8 * (Math::PI - 3) / (3 * Math::PI * (Math::PI - 4))
|
53
|
+
#
|
54
|
+
# The value helps optimize the accuracy of the erf approximation
|
55
|
+
# for a wide range of input values
|
24
56
|
ERF_A = -8 * (Math::PI - 3) / (3 * Math::PI * (Math::PI - 4))
|
25
57
|
|
58
|
+
# Square root of 2
|
59
|
+
#
|
60
|
+
# This constant is frequently used in statistics and probability,
|
61
|
+
# particularly in the normal distribution and error function
|
62
|
+
# calculations.
|
26
63
|
ROOT2 = Math.sqrt(2)
|
27
64
|
end
|
28
65
|
end
|
@@ -1,44 +1,88 @@
|
|
1
1
|
module MoreMath
|
2
|
-
#
|
2
|
+
# A continued fraction implementation that supports both simple and
|
3
|
+
# generalized continued fractions.
|
3
4
|
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
# b_2
|
7
|
-
# a_1 + --------------------
|
8
|
-
# b_3
|
9
|
-
# a_2 + ---------------
|
10
|
-
# b_4
|
11
|
-
# a_3 + ----------
|
12
|
-
# b_5
|
13
|
-
# a_4 + -----
|
14
|
-
# ...
|
5
|
+
# Continued fractions are represented in the form:
|
6
|
+
# a₀ + b₁ / (a₁ + b₂ / (a₂ + b₃ / (a₃ + ...)))
|
15
7
|
#
|
8
|
+
# For simple continued fractions, all `b` coefficients default to 1,
|
9
|
+
# and only `a` coefficients vary.
|
10
|
+
#
|
11
|
+
# @example Simple continued fraction for φ (golden ratio)
|
12
|
+
# phi = ContinuedFraction.new
|
13
|
+
# phi.() # => 1.618033988749895
|
14
|
+
#
|
15
|
+
# @example Generalized continued fraction for √2
|
16
|
+
# sqrt_2 = ContinuedFraction.for_a { |n| n == 0 ? 1 : 2 }
|
17
|
+
# sqrt_2.() # => 1.4142135623730951
|
18
|
+
#
|
19
|
+
# @example Generalized continued fraction for π (finite)
|
20
|
+
# pi = ContinuedFraction.for_a [3, 7, 15, 1, 292, 1, 1, 1, 2]
|
21
|
+
# pi.() # => 3.141592653581078
|
22
|
+
#
|
23
|
+
# @example Continued fraction with variable coefficients
|
24
|
+
# atan = ContinuedFraction.for_a do |n, x|
|
25
|
+
# n == 0 ? 0 : 2 * n - 1
|
26
|
+
# end.for_b do |n, x|
|
27
|
+
# n <= 1 ? x : ((n - 1) * x) ** 2
|
28
|
+
# end
|
29
|
+
# atan.(0.5) # => 0.4636476090008061
|
16
30
|
class ContinuedFraction
|
31
|
+
# Default b coefficient generator (returns 1 for all indices)
|
17
32
|
SIMPLE_B = proc { 1 }
|
18
33
|
|
19
|
-
# Creates a continued fraction
|
20
|
-
#
|
34
|
+
# Creates a new continued fraction with default coefficients.
|
35
|
+
# The defaults for `a` and `b` are both set to 1, which approximates
|
36
|
+
# the golden ratio when evaluated.
|
37
|
+
#
|
38
|
+
# @example Create a new instance
|
39
|
+
# cf = ContinuedFraction.new
|
21
40
|
def initialize
|
22
41
|
@a = proc { 1 }
|
23
42
|
@b = SIMPLE_B
|
24
43
|
end
|
25
44
|
|
26
|
-
# Creates a
|
27
|
-
#
|
45
|
+
# Creates a continued fraction instance and sets its `a` coefficients.
|
46
|
+
# This is a class method for convenience when building continued fractions.
|
47
|
+
#
|
48
|
+
# @example Using an array of values
|
49
|
+
# cf = ContinuedFraction.for_a([1, 2, 3])
|
50
|
+
#
|
51
|
+
# @example Using a block
|
52
|
+
# cf = ContinuedFraction.for_a { |n| n + 1 }
|
53
|
+
#
|
54
|
+
# @param arg [Array, nil] An array of coefficients or nil to use a block.
|
55
|
+
# @yield [index] A block that returns the coefficient for index `n`.
|
56
|
+
# @yieldparam index [Integer] The index of the coefficient to retrieve.
|
57
|
+
# @return [ContinuedFraction] A new continued fraction with specified `a` coefficients.
|
28
58
|
def self.for_a(arg = nil, &block)
|
29
59
|
new.for_a(arg, &block)
|
30
60
|
end
|
31
61
|
|
32
|
-
# Creates a
|
33
|
-
#
|
62
|
+
# Creates a continued fraction instance and sets its `b` coefficients.
|
63
|
+
# This is a class method for convenience when building continued fractions.
|
64
|
+
#
|
65
|
+
# @example Using an array of values
|
66
|
+
# cf = ContinuedFraction.for_b([1, 2, 3])
|
67
|
+
#
|
68
|
+
# @example Using a block
|
69
|
+
# cf = ContinuedFraction.for_b { |n| n + 1 }
|
70
|
+
#
|
71
|
+
# @param arg [Array, nil] An array of coefficients or nil to use a block.
|
72
|
+
# @yield [index] A block that returns the coefficient for index `n`.
|
73
|
+
# @yieldparam index [Integer] The index of the coefficient to retrieve.
|
74
|
+
# @return [ContinuedFraction] A new continued fraction with specified `b` coefficients.
|
34
75
|
def self.for_b(arg = nil, &block)
|
35
76
|
new.for_b(arg, &block)
|
36
77
|
end
|
37
78
|
|
79
|
+
# Helper method to validate and process arguments for `for_a` and `for_b`.
|
80
|
+
#
|
81
|
+
# @api private
|
38
82
|
def for_arg(arg = nil, &block)
|
39
|
-
if arg
|
83
|
+
if arg && !block
|
40
84
|
arg.freeze
|
41
|
-
elsif block
|
85
|
+
elsif block && !arg
|
42
86
|
block
|
43
87
|
else
|
44
88
|
raise ArgumentError, "exactly one argument or one block required"
|
@@ -46,6 +90,13 @@ module MoreMath
|
|
46
90
|
end
|
47
91
|
private :for_arg
|
48
92
|
|
93
|
+
# Creates a continued fraction from a Rational number.
|
94
|
+
#
|
95
|
+
# @example Create a continued fraction for π
|
96
|
+
# pi_cf = ContinuedFraction.from(Math::PI)
|
97
|
+
#
|
98
|
+
# @param number [Numeric] The number to convert into a continued fraction.
|
99
|
+
# @return [ContinuedFraction] A continued fraction representation of the number.
|
49
100
|
def self.from(number)
|
50
101
|
number = number.to_r
|
51
102
|
n, d = number.numerator, number.denominator
|
@@ -57,41 +108,51 @@ module MoreMath
|
|
57
108
|
for_a(as)
|
58
109
|
end
|
59
110
|
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
111
|
+
# Sets the `a` coefficients for this continued fraction.
|
112
|
+
#
|
113
|
+
# @example Using an array of values
|
114
|
+
# cf = ContinuedFraction.new.for_a([1, 2, 3])
|
115
|
+
#
|
116
|
+
# @example Using a block
|
117
|
+
# cf = ContinuedFraction.new.for_a { |n| n + 1 }
|
118
|
+
#
|
119
|
+
# @param arg [Array, nil] An array of coefficients or nil to use a block.
|
120
|
+
# @yield [index] A block that returns the coefficient for index `n`.
|
121
|
+
# @yieldparam index [Integer] The index of the coefficient to retrieve.
|
122
|
+
# @return [ContinuedFraction] Returns self for chaining.
|
65
123
|
def for_a(arg = nil, &block)
|
66
124
|
@a = for_arg(arg, &block)
|
67
125
|
self
|
68
126
|
end
|
69
127
|
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
128
|
+
# Sets the `b` coefficients for this continued fraction.
|
129
|
+
#
|
130
|
+
# @example Using an array of values
|
131
|
+
# cf = ContinuedFraction.new.for_b([1, 2, 3])
|
132
|
+
#
|
133
|
+
# @example Using a block
|
134
|
+
# cf = ContinuedFraction.new.for_b { |n| n + 1 }
|
135
|
+
#
|
136
|
+
# @param arg [Array, nil] An array of coefficients or nil to use a block.
|
137
|
+
# @yield [index] A block that returns the coefficient for index `n`.
|
138
|
+
# @yieldparam index [Integer] The index of the coefficient to retrieve.
|
139
|
+
# @return [ContinuedFraction] Returns self for chaining.
|
75
140
|
def for_b(arg = nil, &block)
|
76
141
|
@b = for_arg(arg, &block)
|
77
142
|
self
|
78
143
|
end
|
79
144
|
|
145
|
+
# Checks if this is a simple continued fraction (all `b` coefficients are 1).
|
146
|
+
#
|
147
|
+
# @return [Boolean] True if all `b` coefficients are 1.
|
80
148
|
def simple?
|
81
149
|
@b == SIMPLE_B
|
82
150
|
end
|
83
151
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
include Enumerable
|
89
|
-
def each(&block)
|
90
|
-
if simple?
|
91
|
-
(0..Float::INFINITY).lazy.map { |i| @a[i] }.take_while { |x| x }.each(&block)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
152
|
+
# Returns a string representation of the continued fraction.
|
153
|
+
#
|
154
|
+
# @param length [Integer] The number of terms to display for simple fractions.
|
155
|
+
# @return [String] A formatted string representation.
|
95
156
|
def to_s(length: 10)
|
96
157
|
if simple?
|
97
158
|
convergents = take(length)
|
@@ -101,28 +162,44 @@ module MoreMath
|
|
101
162
|
end
|
102
163
|
end
|
103
164
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
end and result.to_f
|
165
|
+
# Returns a string representation of the continued fraction.
|
166
|
+
#
|
167
|
+
# @return [String] A detailed string representation for debugging.
|
168
|
+
def inspect
|
169
|
+
"#<#{self.class} #{to_s}>"
|
110
170
|
end
|
111
|
-
private :value
|
112
171
|
|
113
|
-
#
|
114
|
-
|
115
|
-
value(@a, n, x)
|
116
|
-
end
|
172
|
+
# Includes Enumerable module to allow iteration over convergents.
|
173
|
+
include Enumerable
|
117
174
|
|
118
|
-
#
|
119
|
-
|
120
|
-
|
175
|
+
# Iterates over convergents of this continued fraction (only for simple fractions).
|
176
|
+
#
|
177
|
+
# @yield [convergent] Yields each convergent value.
|
178
|
+
# @yieldparam convergent [Float] The next convergent in the sequence.
|
179
|
+
def each(&block)
|
180
|
+
if simple?
|
181
|
+
(0..Float::INFINITY).lazy.map { |i| @a[i] }.take_while { |x| x }.each(&block)
|
182
|
+
end
|
121
183
|
end
|
122
184
|
|
123
|
-
# Evaluates the continued fraction for
|
124
|
-
#
|
125
|
-
#
|
185
|
+
# Evaluates the continued fraction for a given value `x`.
|
186
|
+
#
|
187
|
+
# For generalized continued fractions, the coefficients may depend on an external parameter `x`.
|
188
|
+
# The Wallis method with scaling is used for convergence.
|
189
|
+
#
|
190
|
+
# @example Evaluate the golden ratio
|
191
|
+
# phi = ContinuedFraction.new
|
192
|
+
# phi.() # => 1.618033988749895
|
193
|
+
#
|
194
|
+
# @example Evaluate atan(0.5)
|
195
|
+
# atan = ContinuedFraction.for_a { |n, x| n == 0 ? 0 : 2 * n - 1 }
|
196
|
+
# .for_b { |n, x| n <= 1 ? x : ((n - 1) * x) ** 2 }
|
197
|
+
# atan.(0.5) # => 0.4636476090008061
|
198
|
+
#
|
199
|
+
# @param x [Numeric, nil] Optional external parameter for variable coefficients.
|
200
|
+
# @param epsilon [Float] Convergence tolerance (default: 1e-16).
|
201
|
+
# @param max_iterations [Integer] Maximum number of iterations (default: 2^31).
|
202
|
+
# @return [Float] The evaluated result of the continued fraction.
|
126
203
|
def call(x = nil, epsilon: 1E-16, max_iterations: 1 << 31)
|
127
204
|
c_0, c_1 = 1.0, a(0, x)
|
128
205
|
c_1 == nil and return 0 / 0.0
|
@@ -164,6 +241,9 @@ module MoreMath
|
|
164
241
|
result
|
165
242
|
end
|
166
243
|
|
244
|
+
# Returns the reciprocal of this continued fraction.
|
245
|
+
#
|
246
|
+
# @return [ContinuedFraction] A new continued fraction representing the reciprocal.
|
167
247
|
def reciprocal
|
168
248
|
if @a[0] > 0
|
169
249
|
dup.for_a { |i| i == 0 ? 0 : @a[i - 1] }
|
@@ -172,14 +252,44 @@ module MoreMath
|
|
172
252
|
end
|
173
253
|
end
|
174
254
|
|
255
|
+
# Alias for the `call` method.
|
175
256
|
alias [] call
|
176
257
|
|
258
|
+
# Alias for the `call` method.
|
177
259
|
alias to_f call
|
178
260
|
|
179
|
-
#
|
180
|
-
#
|
261
|
+
# Converts this continued fraction into a Proc that can be called directly.
|
262
|
+
#
|
263
|
+
# @return [Proc] A proc that accepts the same arguments as `call`.
|
181
264
|
def to_proc
|
182
265
|
proc { |*a| call(*a) }
|
183
266
|
end
|
267
|
+
|
268
|
+
private
|
269
|
+
|
270
|
+
# Helper method for retrieving coefficient values, supporting both indexed access and block evaluation.
|
271
|
+
#
|
272
|
+
# @api private
|
273
|
+
def value(v, n, x = nil)
|
274
|
+
result = if x
|
275
|
+
v[n, x]
|
276
|
+
else
|
277
|
+
v[n]
|
278
|
+
end and result.to_f
|
279
|
+
end
|
280
|
+
|
281
|
+
# Returns the value for a_n or a_n(x).
|
282
|
+
#
|
283
|
+
# @api private
|
284
|
+
def a(n, x = nil)
|
285
|
+
value(@a, n, x)
|
286
|
+
end
|
287
|
+
|
288
|
+
# Returns the value for b_n or b_n(x).
|
289
|
+
#
|
290
|
+
# @api private
|
291
|
+
def b(n, x = nil)
|
292
|
+
value(@b, n, x)
|
293
|
+
end
|
184
294
|
end
|
185
295
|
end
|