more_math 1.9.0 → 1.10.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 +24 -0
- data/lib/more_math/entropy.rb +36 -18
- data/lib/more_math/version.rb +1 -1
- data/more_math.gemspec +2 -2
- data/tests/entropy_test.rb +12 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b375aa122041b022a2c6b6457cbd6ba9a87691e75a816696c004b57824a5c50e
|
|
4
|
+
data.tar.gz: ea3ae210dc593238418ea80b9d8c86b156b7fd53be2971349cbda9985e59aee1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e28aaa3aaf79ab42eac1fbf4c4a678d7676279ebf326fed10e8c094d0040ad1d664b8a5e9b137a68c25077496886036c67fc377cfb0e1f4027d2c3abaf2ccbc8
|
|
7
|
+
data.tar.gz: 8f8f81bd9beb6c9b7f040d58ac6a90acb3fe4a9394896cd4822c148f7ee362e9c0ee5004785953a9f292b7fac2cf23177676cd46ed17f344e19337399b473cd8
|
data/CHANGES.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-01-19 v1.10.0
|
|
4
|
+
|
|
5
|
+
- Added new `entropy_maximum` method to calculate theoretical maximum entropy
|
|
6
|
+
for a text given an alphabet size
|
|
7
|
+
- Made `size` parameter required in `entropy_ratio` and `entropy_ratio_minimum`
|
|
8
|
+
methods instead of defaulting to `text.size`
|
|
9
|
+
- Updated YARD documentation to clarify that `size` parameter represents
|
|
10
|
+
alphabet size
|
|
11
|
+
- Modified examples to use explicit alphabet sizes for better clarity
|
|
12
|
+
- All entropy methods now consistently return values in bits as expected for
|
|
13
|
+
Shannon entropy
|
|
14
|
+
- Updated documentation examples to use simplified method calls without
|
|
15
|
+
`MoreMath::Entropy` prefix
|
|
16
|
+
- Enhanced `entropy_maximum` method documentation to explain its use in
|
|
17
|
+
determining security strength for tokens
|
|
18
|
+
- Added comprehensive tests for `entropy_maximum` function covering edge cases
|
|
19
|
+
and various alphabet sizes
|
|
20
|
+
- Improved `entropy_maximum` method signature to return `0` for invalid
|
|
21
|
+
alphabet sizes (≤ 1) and use `Math.log2` for calculation
|
|
22
|
+
- Updated existing entropy method documentation to clarify it calculates
|
|
23
|
+
entropy in bits
|
|
24
|
+
- Simplified example code in documentation to use direct method calls instead
|
|
25
|
+
of module prefixes
|
|
26
|
+
|
|
3
27
|
## 2026-01-16 v1.9.0
|
|
4
28
|
|
|
5
29
|
- Added support for array inputs in entropy calculation methods by checking
|
data/lib/more_math/entropy.rb
CHANGED
|
@@ -15,24 +15,24 @@ module MoreMath
|
|
|
15
15
|
#
|
|
16
16
|
# @example Basic usage
|
|
17
17
|
# require 'more_math'
|
|
18
|
-
# include MoreMath
|
|
18
|
+
# include MoreMath::Functions
|
|
19
19
|
#
|
|
20
20
|
# text = "hello world"
|
|
21
21
|
# puts entropy(text) # => 2.3219280948873626
|
|
22
22
|
# puts entropy_ratio(text) # => 0.7428571428571429
|
|
23
23
|
#
|
|
24
24
|
# @example Using with different text samples
|
|
25
|
-
#
|
|
26
|
-
#
|
|
25
|
+
# entropy("aaaa") # => 0.0 (no entropy)
|
|
26
|
+
# entropy("abcd") # => 2.0 (actual entropy)
|
|
27
27
|
module Entropy
|
|
28
|
-
# Calculates the Shannon entropy of a text string.
|
|
28
|
+
# Calculates the Shannon entropy in bits of a text string.
|
|
29
29
|
#
|
|
30
30
|
# Shannon entropy measures the average amount of information (in bits) needed
|
|
31
31
|
# to encode characters in the text based on their frequencies.
|
|
32
32
|
#
|
|
33
33
|
# @example
|
|
34
|
-
#
|
|
35
|
-
#
|
|
34
|
+
# entropy("hello") # => 2.3219280948873626
|
|
35
|
+
# entropy("aaaa") # => 0.0
|
|
36
36
|
#
|
|
37
37
|
# @param text [String] The input text to calculate entropy for
|
|
38
38
|
# @return [Float] The Shannon entropy in bits
|
|
@@ -58,8 +58,8 @@ module MoreMath
|
|
|
58
58
|
# alphabet have equal probability of occurrence.
|
|
59
59
|
#
|
|
60
60
|
# @example
|
|
61
|
-
#
|
|
62
|
-
#
|
|
61
|
+
# entropy_ideal(2) # => 1.0
|
|
62
|
+
# entropy_ideal(256) # => 8.0
|
|
63
63
|
#
|
|
64
64
|
# @param size [Integer] The number of unique characters in the alphabet
|
|
65
65
|
# @return [Float] The maximum possible entropy in bits
|
|
@@ -80,21 +80,18 @@ module MoreMath
|
|
|
80
80
|
# theoretical maximum entropy for that character set.
|
|
81
81
|
#
|
|
82
82
|
# @example
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
83
|
+
# entropy_ratio("hello") # => 0.6834
|
|
84
|
+
# entropy_ratio("aaaaa") # => 0.0
|
|
85
|
+
# entropy_ratio("abcde") # => 1.0
|
|
86
86
|
#
|
|
87
87
|
# @example With custom alphabet size
|
|
88
88
|
# # Normalizing against a 26-letter alphabet (English)
|
|
89
|
-
#
|
|
89
|
+
# entropy_ratio("hello", size: 26) # => 0.394...
|
|
90
90
|
#
|
|
91
91
|
# @param text [String] The input text to calculate entropy ratio for
|
|
92
|
-
# @param size [Integer] The size of the character set to normalize against.
|
|
93
|
-
# Defaults to the total length of the text (`text.size`), which
|
|
94
|
-
# normalizes the entropy relative to the text's own character space.
|
|
95
|
-
# This allows comparison of texts with different lengths on the same scale.
|
|
92
|
+
# @param size [Integer] The size of the character set to normalize against (alphabet size).
|
|
96
93
|
# @return [Float] Normalized entropy ratio between 0 and 1
|
|
97
|
-
def entropy_ratio(text, size:
|
|
94
|
+
def entropy_ratio(text, size:)
|
|
98
95
|
size <= 1 and return 0.0
|
|
99
96
|
entropy(text) / entropy_ideal(size)
|
|
100
97
|
end
|
|
@@ -107,11 +104,12 @@ module MoreMath
|
|
|
107
104
|
#
|
|
108
105
|
# @param text [String] The input text to calculate entropy ratio for
|
|
109
106
|
# @param size [Integer] The size of the character set to normalize against
|
|
107
|
+
# (alphabet size).
|
|
110
108
|
# @param alpha [Float] The significance level for the confidence interval (default: 0.05)
|
|
111
109
|
# @return [Float] The adjusted entropy ratio within the confidence interval
|
|
112
110
|
# @raise [ArgumentError] When alphabet size is less than 2
|
|
113
111
|
# @raise [ArgumentError] When text is empty
|
|
114
|
-
def entropy_ratio_minimum(text, size
|
|
112
|
+
def entropy_ratio_minimum(text, size:, alpha: 0.05)
|
|
115
113
|
raise ArgumentError, 'alphabet size must be ≥ 2' if size < 2
|
|
116
114
|
raise ArgumentError, 'text must not be empty' if text.empty?
|
|
117
115
|
|
|
@@ -129,5 +127,25 @@ module MoreMath
|
|
|
129
127
|
|
|
130
128
|
(ratio - z * se).clamp(0, 1)
|
|
131
129
|
end
|
|
130
|
+
|
|
131
|
+
# Calculates the maximum possible entropy for a given text and alphabet
|
|
132
|
+
# size.
|
|
133
|
+
#
|
|
134
|
+
# This represents the theoretical maximum entropy that could be achieved if
|
|
135
|
+
# all characters in the text were chosen uniformly at random from the
|
|
136
|
+
# alphabet. It's used to determine the upper bound of security strength for
|
|
137
|
+
# tokens.
|
|
138
|
+
#
|
|
139
|
+
# @example
|
|
140
|
+
# entropy_maximum("hello", size: 26) # => 23
|
|
141
|
+
# entropy_maximum("abc123", size: 64) # => 36
|
|
142
|
+
#
|
|
143
|
+
# @param text [String] The input text to calculate maximum entropy for
|
|
144
|
+
# @param size [Integer] The size of the character set (alphabet size)
|
|
145
|
+
# @return [Integer] The maximum possible entropy in bits, or 0 if size <= 1
|
|
146
|
+
def entropy_maximum(text, size:)
|
|
147
|
+
size > 1 or return 0
|
|
148
|
+
(text.size * Math.log2(size)).floor
|
|
149
|
+
end
|
|
132
150
|
end
|
|
133
151
|
end
|
data/lib/more_math/version.rb
CHANGED
data/more_math.gemspec
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: more_math 1.
|
|
2
|
+
# stub: more_math 1.10.0 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "more_math".freeze
|
|
6
|
-
s.version = "1.
|
|
6
|
+
s.version = "1.10.0".freeze
|
|
7
7
|
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
9
9
|
s.require_paths = ["lib".freeze]
|
data/tests/entropy_test.rb
CHANGED
|
@@ -36,12 +36,22 @@ class EntropyTest < Test::Unit::TestCase
|
|
|
36
36
|
assert_in_delta 4, entropy_ideal(16), 1E-3
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
def test_entropy_mamxium
|
|
40
|
+
text = 'A' * 64
|
|
41
|
+
assert_equal 0, entropy_maximum(text, size: -1)
|
|
42
|
+
assert_equal 0, entropy_maximum(text, size: 0)
|
|
43
|
+
assert_equal 0, entropy_maximum(text, size: 1)
|
|
44
|
+
assert_equal 64, entropy_maximum(text, size: 2)
|
|
45
|
+
assert_equal 256, entropy_maximum(text, size: 16)
|
|
46
|
+
assert_equal 128, entropy_maximum(text[0, 32], size: 16)
|
|
47
|
+
end
|
|
48
|
+
|
|
39
49
|
def test_entropy_ratio
|
|
40
|
-
assert_equal 0, entropy_ratio(@empty)
|
|
50
|
+
assert_equal 0, entropy_ratio(@empty, size: 128)
|
|
41
51
|
assert_equal 0, entropy_ratio(@low, size: 128)
|
|
42
52
|
assert_in_delta 0.564, entropy_ratio(@string, size: 128), 1E-3
|
|
43
53
|
assert_in_delta 0.633, entropy_ratio(@high, size: 128), 1E-3
|
|
44
|
-
assert_in_delta 1.0, entropy_ratio(@random), 1E-3
|
|
54
|
+
assert_in_delta 1.0, entropy_ratio(@random, size: @random.size), 1E-3
|
|
45
55
|
assert_in_delta 0.462, entropy_ratio(@random, size: 256), 1E-3
|
|
46
56
|
assert_in_delta 0.253, entropy_ratio(@hi, size: 2_136), 1E-3
|
|
47
57
|
end
|