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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e49149cd5565cd37afbfbe28185a0fbd2a12b245fe19e81882b9df1a0808edb
4
- data.tar.gz: be0a9ffffac8d705bc6aefb5643eb188abc35c38eefa905ce988c8369a5d676e
3
+ metadata.gz: 347b633c7b95cb4728828e2dcad06f04f824e340d72dc4192b0d81b7e3a2df6e
4
+ data.tar.gz: 5e1bd55c18723aa18ccab2b7c916811ba8c84f2fb251bcaeb323575da045f7d3
5
5
  SHA512:
6
- metadata.gz: 2afb5b0fd78fe1becb079a653354103cef2a02ecd854d73b7e749a03b4f9fc1aee79da76c81f6b1a30060d614b7a76b33d81050672f44aadbfe8bb748bb0090b
7
- data.tar.gz: 53e00124977ced033913b519606110c5d75f747c96d84ad80afd35683754dd8c963704afda44ffb7a5fc2138c80d99347199cd9df5d16dc0767b18706c44bd7d
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/more_math"
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
- ### Core Features
10
-
11
- 1. **Mathematical Functions**
12
- - **Gamma Function**: Computes the gamma function for real numbers.
13
- - **Beta Function**: Calculates the beta function and its regularized form.
14
- - **Error Function (erf)**: Provides the error function used in probability
15
- and statistics.
16
-
17
- 2. **Special Functions**
18
- - **Lambert W Function**: Solves equations of the form `x = a * exp(x)`.
19
- - **Continued Fractions**: Evaluates continued fractions for various
20
- mathematical expressions.
21
-
22
- 3. **Statistical Tools**
23
- - **Probability Distributions**: Implements distributions like Student's t,
24
- chi-squared, and Fisher's z.
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
- To install `more_math`, run:
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 X11 (or MIT) license:
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
- *Dir['.github/**/*']
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
- # This class implements a continued fraction of the form:
2
+ # A continued fraction implementation that supports both simple and
3
+ # generalized continued fractions.
3
4
  #
4
- # b_1
5
- # a_0 + -------------------------
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 instance. With the defaults for_a { 1 } and
20
- # for_b { 1 } it approximates the golden ration phi if evaluated.
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 ContinuedFraction instances and passes its arguments to a call
27
- # to for_a.
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 ContinuedFraction instances and passes its arguments to a call
33
- # to for_b.
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 and !block
83
+ if arg && !block
40
84
  arg.freeze
41
- elsif block and !arg
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
- # This method either takes a block or an argument +arg+. The argument +arg+
61
- # has to respond to an integer index n >= 0 and return the value a_n. The
62
- # block has to return the value for a_n when +n+ is passed as the first
63
- # argument to the block. If a_n is dependent on an +x+ value (see the call
64
- # method) the +x+ will be the second argument of the block.
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
- # This method either takes a block or an argument +arg+. The argument +arg+
71
- # has to respond to an integer index n >= 1 and return the value b_n. The
72
- # block has to return the value for b_n when +n+ is passed as the first
73
- # argument to the block. If b_n is dependent on an +x+ value (see the call
74
- # method) the +x+ will be the second argument of the block.
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
- def inspect
85
- "#<#{self.class} #{to_s}>"
86
- end
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
- def value(v, n, x = nil)
105
- result = if x
106
- v[n, x]
107
- else
108
- v[n]
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
- # Returns the value for a_n or a_n(x).
114
- def a(n, x = nil)
115
- value(@a, n, x)
116
- end
172
+ # Includes Enumerable module to allow iteration over convergents.
173
+ include Enumerable
117
174
 
118
- # Returns the value for b_n or b_n(x).
119
- def b(n, x = nil)
120
- value(@b, n, x)
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 the value +x+ (if any) with the
124
- # accuracy +epsilon+ and +max_iterations+ as the maximum number of
125
- # iterations using the Wallis-method with scaling.
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
- # Returns this continued fraction as a Proc object which takes the same
180
- # arguments like its call method does.
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