philiprehberger-math_kit 0.3.0 → 0.4.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: bfd866aacb1af07326cd0543912f1d088dec7cc9c7c06f217709a7bbc31f79d1
4
- data.tar.gz: f747448a80beda06245efebbff03f3fb043c042bf625c9b8a7512debb9847e1b
3
+ metadata.gz: a73db6abf0e0f987688786bd18c0b959182dc5290c52ac52e04a55926361436e
4
+ data.tar.gz: 85c7d136bf63030f7009b736aa0d44c81429e383973bb8bd65ca58f0aa08c927
5
5
  SHA512:
6
- metadata.gz: 6b8b029f141507b9cd791c070ae2d9f5cec3f228182a58caaaf1ad7fce42512a2c62d364e8d1a68d7b204e096590d392ebd341042ada39b50c0b35053ed06974
7
- data.tar.gz: 6ec476f44f0728ef45b6ce64806be76544b39a5f4831d2897f7ea2fd9bb0f9959df4fa1f7fba7a61cd8f842f76976935b47301da3353da340f5916a96748c65e
6
+ metadata.gz: 63bbbb1ca5f8c31f476dbb87f9df33569a4cdd420e49b736f2a5289c5f7e3839cff4cc3353af2c8db87f5bf909feb7b7047088e29167ea36d7318752c271848c
7
+ data.tar.gz: 183f0a9fec1904a98d37520df268f260e7f6e4dd9e32403fc5ce1ef3e3fdf1d346947d1751e757a4d81de0eae73cd215b393c19faa82a3b7510d7ff4b23d6c9a
data/CHANGELOG.md CHANGED
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.0] - 2026-04-15
11
+
12
+ ### Added
13
+ - `Numeric` module with common integer and value helpers
14
+ - `Numeric.factorial(n)` for non-negative integer factorial (arbitrary precision)
15
+ - `Numeric.fibonacci(n)` for the n-th Fibonacci number via iterative O(n)/O(1) computation
16
+ - `Numeric.gcd(a, b)` for greatest common divisor (accepts negative inputs)
17
+ - `Numeric.lcm(a, b)` for least common multiple (accepts negative inputs)
18
+ - `Numeric.clamp(value, min, max)` for constraining a value to a range
19
+
10
20
  ## [0.3.0] - 2026-04-10
11
21
 
12
22
  ### Added
@@ -66,3 +76,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66
76
  - Linear interpolation between sorted points with extrapolation
67
77
  - Rounding modes: bankers (round half to even), ceiling, floor, truncate with precision
68
78
  - Simple moving average and exponential moving average
79
+
80
+ [Unreleased]: https://github.com/philiprehberger/rb-math-kit/compare/v0.4.0...HEAD
81
+ [0.4.0]: https://github.com/philiprehberger/rb-math-kit/compare/v0.3.0...v0.4.0
82
+ [0.3.0]: https://github.com/philiprehberger/rb-math-kit/compare/v0.2.3...v0.3.0
83
+ [0.2.3]: https://github.com/philiprehberger/rb-math-kit/compare/v0.2.2...v0.2.3
84
+ [0.2.2]: https://github.com/philiprehberger/rb-math-kit/compare/v0.2.1...v0.2.2
85
+ [0.2.1]: https://github.com/philiprehberger/rb-math-kit/compare/v0.2.0...v0.2.1
86
+ [0.2.0]: https://github.com/philiprehberger/rb-math-kit/compare/v0.1.2...v0.2.0
87
+ [0.1.2]: https://github.com/philiprehberger/rb-math-kit/compare/v0.1.1...v0.1.2
88
+ [0.1.1]: https://github.com/philiprehberger/rb-math-kit/compare/v0.1.0...v0.1.1
89
+ [0.1.0]: https://github.com/philiprehberger/rb-math-kit/releases/tag/v0.1.0
data/README.md CHANGED
@@ -138,6 +138,16 @@ Philiprehberger::MathKit::MovingAverage.simple([1, 2, 3, 4, 5], window: 3)
138
138
  Philiprehberger::MathKit::MovingAverage.exponential([1, 2, 3, 4, 5], alpha: 0.5) # => [1.0, 1.5, 2.25, 3.125, 4.0625]
139
139
  ```
140
140
 
141
+ ### Numeric Helpers
142
+
143
+ ```ruby
144
+ Philiprehberger::MathKit::Numeric.factorial(5) # => 120
145
+ Philiprehberger::MathKit::Numeric.fibonacci(10) # => 55
146
+ Philiprehberger::MathKit::Numeric.gcd(12, 18) # => 6
147
+ Philiprehberger::MathKit::Numeric.lcm(4, 6) # => 12
148
+ Philiprehberger::MathKit::Numeric.clamp(42, 0, 10) # => 10
149
+ ```
150
+
141
151
  ## API
142
152
 
143
153
  ### `Stats`
@@ -198,6 +208,16 @@ Philiprehberger::MathKit::MovingAverage.exponential([1, 2, 3, 4, 5], alpha: 0.5)
198
208
  | `.simple(values, window:)` | Simple moving average |
199
209
  | `.exponential(values, alpha:)` | Exponential moving average |
200
210
 
211
+ ### `Numeric`
212
+
213
+ | Method | Description |
214
+ |--------|-------------|
215
+ | `.factorial(n)` | Factorial of a non-negative integer |
216
+ | `.fibonacci(n)` | N-th Fibonacci number (0-indexed) |
217
+ | `.gcd(a, b)` | Greatest common divisor of two integers |
218
+ | `.lcm(a, b)` | Least common multiple of two integers |
219
+ | `.clamp(value, min, max)` | Clamp a numeric value between min and max |
220
+
201
221
  ## Development
202
222
 
203
223
  ```bash
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Philiprehberger
4
+ module MathKit
5
+ # Numeric helpers for common integer and value operations
6
+ module Numeric
7
+ class << self
8
+ # Factorial of a non-negative integer (n!)
9
+ #
10
+ # @param n [Integer] a non-negative integer
11
+ # @return [Integer] the factorial of n
12
+ # @raise [ArgumentError] if n is negative or not an Integer
13
+ def factorial(n)
14
+ raise ArgumentError, 'factorial requires an Integer' unless n.is_a?(Integer)
15
+ raise ArgumentError, 'factorial requires a non-negative integer' if n.negative?
16
+
17
+ (1..n).reduce(1, :*)
18
+ end
19
+
20
+ # N-th Fibonacci number (0-indexed: fibonacci(0) = 0, fibonacci(1) = 1)
21
+ #
22
+ # Uses an iterative algorithm for O(n) time and O(1) space.
23
+ #
24
+ # @param n [Integer] a non-negative index
25
+ # @return [Integer] the n-th Fibonacci number
26
+ # @raise [ArgumentError] if n is negative or not an Integer
27
+ def fibonacci(n)
28
+ raise ArgumentError, 'fibonacci requires an Integer' unless n.is_a?(Integer)
29
+ raise ArgumentError, 'fibonacci requires a non-negative integer' if n.negative?
30
+
31
+ a = 0
32
+ b = 1
33
+ n.times { a, b = b, a + b }
34
+ a
35
+ end
36
+
37
+ # Greatest common divisor of two integers (Euclidean algorithm)
38
+ #
39
+ # @param a [Integer] first integer
40
+ # @param b [Integer] second integer
41
+ # @return [Integer] the non-negative greatest common divisor
42
+ # @raise [ArgumentError] if either argument is not an Integer
43
+ def gcd(a, b)
44
+ raise ArgumentError, 'gcd requires Integer arguments' unless a.is_a?(Integer) && b.is_a?(Integer)
45
+
46
+ a.abs.gcd(b.abs)
47
+ end
48
+
49
+ # Least common multiple of two integers
50
+ #
51
+ # @param a [Integer] first integer
52
+ # @param b [Integer] second integer
53
+ # @return [Integer] the non-negative least common multiple (0 if either is 0)
54
+ # @raise [ArgumentError] if either argument is not an Integer
55
+ def lcm(a, b)
56
+ raise ArgumentError, 'lcm requires Integer arguments' unless a.is_a?(Integer) && b.is_a?(Integer)
57
+
58
+ a.abs.lcm(b.abs)
59
+ end
60
+
61
+ # Clamp a numeric value between a minimum and maximum
62
+ #
63
+ # @param value [Numeric] the value to clamp
64
+ # @param min [Numeric] lower bound
65
+ # @param max [Numeric] upper bound
66
+ # @return [Numeric] the clamped value
67
+ # @raise [ArgumentError] if min is greater than max
68
+ def clamp(value, min, max)
69
+ raise ArgumentError, 'min must not be greater than max' if min > max
70
+
71
+ return min if value < min
72
+ return max if value > max
73
+
74
+ value
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Philiprehberger
4
4
  module MathKit
5
- VERSION = '0.3.0'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
@@ -6,6 +6,7 @@ require_relative 'math_kit/interpolation'
6
6
  require_relative 'math_kit/round'
7
7
  require_relative 'math_kit/moving_average'
8
8
  require_relative 'math_kit/regression'
9
+ require_relative 'math_kit/numeric'
9
10
 
10
11
  module Philiprehberger
11
12
  module MathKit
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: philiprehberger-math_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philip Rehberger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-10 00:00:00.000000000 Z
11
+ date: 2026-04-15 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Descriptive statistics, linear interpolation, rounding modes, and moving
14
14
  averages. Lightweight math toolkit with zero dependencies.
@@ -24,6 +24,7 @@ files:
24
24
  - lib/philiprehberger/math_kit.rb
25
25
  - lib/philiprehberger/math_kit/interpolation.rb
26
26
  - lib/philiprehberger/math_kit/moving_average.rb
27
+ - lib/philiprehberger/math_kit/numeric.rb
27
28
  - lib/philiprehberger/math_kit/regression.rb
28
29
  - lib/philiprehberger/math_kit/round.rb
29
30
  - lib/philiprehberger/math_kit/stats.rb