measurand 0.0.0 → 0.1.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/CHANGELOG +44 -0
- data/README.md +11 -0
- data/lib/Measurand/Format.rb +0 -25
- data/lib/Measurand/VERSION.rb +1 -1
- data/lib/measurand.rb +41 -0
- data/measurand.gemspec +7 -4
- data/test/Measurand/Format_test.rb +27 -0
- metadata +3 -3
- data/CHANGELOG.md +0 -27
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4caf91e22da69c556702463204bf65ea9eec1c52b6dcaf05552fc0c91405af22
|
|
4
|
+
data.tar.gz: be7b0a5d116588a0aad0dac6f9aa7b7eda71eeedb0efb0f45d4ab8d0768a15bb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7644fba9dd884b911bb436af4fadfbea172195baa51b57b15c20f6f0ae9e7c2c7a499e8ef6ad815e918df430cfbfac9cddc2abb768eb3ce1f6d48deefe431973
|
|
7
|
+
data.tar.gz: 945f167c52db919848a324a81585f9c0b747c2676bf3361eeac76044080b09139af5d406e28d51799cdcaf6a0a535bb974c459594e2a15f11f4b21ec991a344c
|
data/CHANGELOG
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
## 20260815
|
|
4
|
+
|
|
5
|
+
0.1.0: + Measurand#place, Measurand#rounded_uncertainty.
|
|
6
|
+
|
|
7
|
+
1. + Measurand#place: the power of ten of the least significant digit worth showing, negative for digits after the point, and nil where the measurand is exact — every digit being real and there being no last one. It is what a caller wants in order to render a quantity in a unit of its own choosing rather than take #to_s, and monotonic.rb was reaching into Measurand::Format to get at it.
|
|
8
|
+
2. + Measurand#rounded_uncertainty: the uncertainty as #to_s shows it, rounded by the Particle Data Group convention, and zero where the measurand is exact.
|
|
9
|
+
3. ~ Measurand#to_s and #to_parenthetic: built upon the two above rather than calling Measurand::Format themselves, so that what is published and what is rendered cannot drift apart.
|
|
10
|
+
4. + test/Measurand/Format_test.rb: #place and #rounded_uncertainty, including the exact case and that #place agrees with the digits #to_s renders.
|
|
11
|
+
5. ~ lib/Measurand/Format.rb --> lib/measurand.rb: #place, #rounded_uncertainty, #to_s, #to_parenthetic, #inspect and the private #fixed, which are Measurand's and not Format's. The file is named for the module and now holds only it, as Monotonic/Time.rb holds Monotonic::Time. Naming them by the file they sat in was already a mistake waiting to be made.
|
|
12
|
+
6. + CHANGELOG, and - CHANGELOG.md. Both were present at 0.0.0 and only the .md shipped; the gem is what is immutable, so 0.0.0 has been rewritten to carry the .md alone and the change of file belongs here. CHANGELOG is what every other gem here is spelt.
|
|
13
|
+
7. ~ measurand.gemspec: /CHANGELOG.md/CHANGELOG/, following the above.
|
|
14
|
+
8. ~ README.md: + #place and #rounded_uncertainty to the Presentation section.
|
|
15
|
+
9. ~ Measurand::VERSION: /0.0.0/0.1.0/
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## 20260715
|
|
19
|
+
|
|
20
|
+
0.0.0: + Measurand: measured values with uncertainty and GUM-conformant error propagation.
|
|
21
|
+
|
|
22
|
+
1. + Measurand: Measured values with uncertainty and GUM-conformant error propagation, forward-mode automatic differentiation over a {Source => partial} map; the uncertainty is derived from the partials, not stored, so shared sources correlate (x - x is exactly 0 ± 0).
|
|
23
|
+
2. + Measurand construction methods: .new, .relative, .cast, .cast\_relative, .from\_samples (mean ± standard error of the mean), .derived.
|
|
24
|
+
3. + Measurand arithmetic methods: +, -, \*, /, \*\*, -@, abs, apply — chain-rule propagation; independent uncertainties combine in quadrature; scalars are exact.
|
|
25
|
+
4. + Measurand comparison methods: ==/eql?/hash (exact: value and uncertainty), <=> (by value, Comparable), consistent\_with?, overlaps?, coerce (scalar-on-the-left arithmetic).
|
|
26
|
+
5. + Measurand reader methods: value, uncertainty, relative\_uncertainty, exact?
|
|
27
|
+
6. + Measurand::Format: Uncertainty-driven, PDG-rounded to\_s (ascii: keyword emits +/- instead of ±), to\_parenthetic, inspect (full precision).
|
|
28
|
+
7. + Measurand::Math: Measurand::Math.sqrt, exp, log, log10, sin, cos, tan — chain-rule propagation with no Math monkey-patching.
|
|
29
|
+
8. + Measurand::Numeric: opt-in Numeric#pm / #± and Enumerable#pm (separate require, so nothing is monkey-patched unless asked).
|
|
30
|
+
9. + Measurand::Parse: Measurand.parse for ±, +/-, parenthetic (10), relative %, and exact forms; raises ArgumentError rather than returning nil.
|
|
31
|
+
10. + Measurand::Source: Opaque per-source identity carrying its own uncertainty; deliberately no ==/eql?/hash, so shared sources correlate and independently-constructed ones never collapse.
|
|
32
|
+
11. + Measurand::VERSION: 0.0.0
|
|
33
|
+
12. + measurand.gemspec
|
|
34
|
+
13. + Gemfile
|
|
35
|
+
14. + LICENSE
|
|
36
|
+
15. + Rakefile
|
|
37
|
+
16. + README.md
|
|
38
|
+
17. + test/test_helper.rb
|
|
39
|
+
18. + test/Measurand/Format_test.rb
|
|
40
|
+
19. + test/Measurand/Measurand_test.rb
|
|
41
|
+
20. + test/Measurand/Math_test.rb
|
|
42
|
+
21. + test/Measurand/Numeric_test.rb
|
|
43
|
+
22. + test/Measurand/Parse_test.rb
|
|
44
|
+
23. + test/Measurand/Source_test.rb
|
data/README.md
CHANGED
|
@@ -113,6 +113,17 @@ m.inspect # => "Measurand(5.129213, 0.01)" — full precision
|
|
|
113
113
|
```
|
|
114
114
|
|
|
115
115
|
`to_s` emits the `±` character by default; pass `ascii: true` when writing to a
|
|
116
|
+
|
|
117
|
+
Where a caller wants to render the quantity in some unit of its own rather than
|
|
118
|
+
take the string here, the two figures `to_s` rests upon are readable:
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
m.place # => -3 the power of ten of the last real digit
|
|
122
|
+
m.rounded_uncertainty # => 0.01 the uncertainty as `to_s` shows it
|
|
123
|
+
|
|
124
|
+
Measurand.new(5.129213).place # => nil exact: every digit is real
|
|
125
|
+
Measurand.new(5.129213).rounded_uncertainty # => 0
|
|
126
|
+
```
|
|
116
127
|
stream that isn't UTF-8. `parse` reads both forms, so either round-trips.
|
|
117
128
|
|
|
118
129
|
### Transcendentals
|
data/lib/Measurand/Format.rb
CHANGED
|
@@ -40,29 +40,4 @@ class Measurand
|
|
|
40
40
|
place < 0 ? -place : 0
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
|
-
|
|
44
|
-
def to_s(ascii: false)
|
|
45
|
-
return @value.to_s if exact?
|
|
46
|
-
rounded_uncertainty, place = Format.round_uncertainty(uncertainty)
|
|
47
|
-
digits = Format.decimals(place)
|
|
48
|
-
"#{fixed(Format.round_to_place(@value, place), digits)} #{ascii ? '+/-' : '±'} #{fixed(rounded_uncertainty, digits)}"
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def to_parenthetic
|
|
52
|
-
return @value.to_s if exact?
|
|
53
|
-
rounded_uncertainty, place = Format.round_uncertainty(uncertainty)
|
|
54
|
-
digits = Format.decimals(place)
|
|
55
|
-
parenthetic_digits = (rounded_uncertainty / 10.0 ** place).round
|
|
56
|
-
"#{fixed(Format.round_to_place(@value, place), digits)}(#{parenthetic_digits})"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def inspect
|
|
60
|
-
"Measurand(#{@value}, #{uncertainty})"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
private
|
|
64
|
-
|
|
65
|
-
def fixed(number, digits)
|
|
66
|
-
format("%.#{digits}f", number)
|
|
67
|
-
end
|
|
68
43
|
end
|
data/lib/Measurand/VERSION.rb
CHANGED
data/lib/measurand.rb
CHANGED
|
@@ -154,6 +154,43 @@ class Measurand
|
|
|
154
154
|
[wrap(other), self]
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
+
# The power of ten of the least significant digit worth showing, by the
|
|
158
|
+
# convention above: negative for digits after the point, so a place of -3
|
|
159
|
+
# means thousandths are the last real thing. nil where the measurand is exact,
|
|
160
|
+
# every digit being real and there being no last one.
|
|
161
|
+
#
|
|
162
|
+
# This is what a caller wants in order to render a quantity in some unit of
|
|
163
|
+
# its own choosing, rather than taking the string here.
|
|
164
|
+
def place
|
|
165
|
+
return nil if exact?
|
|
166
|
+
@place ||= Format.round_uncertainty(uncertainty).last
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# The uncertainty as #to_s shows it, rounded to one or two significant figures
|
|
170
|
+
# by the same convention. Zero where the measurand is exact.
|
|
171
|
+
def rounded_uncertainty
|
|
172
|
+
return 0 if exact?
|
|
173
|
+
@rounded_uncertainty ||= Format.round_uncertainty(uncertainty).first
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def to_s(ascii: false)
|
|
177
|
+
return @value.to_s if exact?
|
|
178
|
+
digits = Format.decimals(place)
|
|
179
|
+
"#{fixed(Format.round_to_place(@value, place), digits)} #{ascii ? '+/-' : '±'} #{fixed(rounded_uncertainty, digits)}"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def to_parenthetic
|
|
183
|
+
return @value.to_s if exact?
|
|
184
|
+
digits = Format.decimals(place)
|
|
185
|
+
parenthetic_digits = (rounded_uncertainty / 10.0 ** place).round
|
|
186
|
+
"#{fixed(Format.round_to_place(@value, place), digits)}(#{parenthetic_digits})"
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def inspect
|
|
190
|
+
"Measurand(#{@value}, #{uncertainty})"
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
|
|
157
194
|
protected
|
|
158
195
|
|
|
159
196
|
def partials
|
|
@@ -162,6 +199,10 @@ class Measurand
|
|
|
162
199
|
|
|
163
200
|
private
|
|
164
201
|
|
|
202
|
+
def fixed(number, digits)
|
|
203
|
+
format("%.#{digits}f", number)
|
|
204
|
+
end
|
|
205
|
+
|
|
165
206
|
def initialize(value, uncertainty = 0)
|
|
166
207
|
@value = value
|
|
167
208
|
@partials = uncertainty.zero? ? {} : {Source.new(uncertainty) => 1.0}
|
data/measurand.gemspec
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# measurand.gemspec
|
|
2
|
+
|
|
1
3
|
require_relative './lib/Measurand/VERSION'
|
|
2
4
|
|
|
3
5
|
Gem::Specification.new do |spec|
|
|
@@ -15,13 +17,14 @@ Gem::Specification.new do |spec|
|
|
|
15
17
|
spec.required_ruby_version = '>= 2.5'
|
|
16
18
|
|
|
17
19
|
spec.files = [
|
|
18
|
-
'measurand.gemspec',
|
|
19
|
-
'Gemfile',
|
|
20
20
|
Dir['lib/**/*.rb'],
|
|
21
|
-
'
|
|
21
|
+
Dir['test/**/*.rb'],
|
|
22
|
+
'CHANGELOG',
|
|
23
|
+
'Gemfile',
|
|
22
24
|
'LICENSE',
|
|
25
|
+
'measurand.gemspec',
|
|
23
26
|
'README.md',
|
|
24
|
-
Dir['test/**/*.rb']
|
|
25
27
|
].flatten
|
|
28
|
+
|
|
26
29
|
spec.require_paths = ['lib']
|
|
27
30
|
end
|
|
@@ -51,4 +51,31 @@ describe "Measurand formatting" do
|
|
|
51
51
|
_(Measurand.new(5.129213, 0.01).inspect).must_equal "Measurand(5.129213, 0.01)"
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
|
+
describe "#place" do
|
|
55
|
+
it "is the power of ten of the least significant digit worth showing" do
|
|
56
|
+
_(Measurand.new(1_274_625, 84).place).must_equal(1)
|
|
57
|
+
_(Measurand.new(5.129213, 0.01).place).must_equal(-3)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "is nil where the measurand is exact, every digit being real" do
|
|
61
|
+
_(Measurand.new(5.129213).place).must_be_nil
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "agrees with what #to_s renders" do
|
|
65
|
+
subject = Measurand.new(5.129213, 0.01)
|
|
66
|
+
_(subject.to_s.split(" ").first.split(".").last.length).must_equal(-subject.place)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe "#rounded_uncertainty" do
|
|
71
|
+
it "is the uncertainty as #to_s shows it" do
|
|
72
|
+
_(Measurand.new(1_274_625, 84).rounded_uncertainty).must_equal(80)
|
|
73
|
+
_(Measurand.new(5.129213, 0.01).rounded_uncertainty).must_equal(0.01)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "is zero where the measurand is exact" do
|
|
77
|
+
_(Measurand.new(5.129213).rounded_uncertainty).must_equal(0)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
54
81
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: measurand
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- thoran
|
|
@@ -18,7 +18,7 @@ executables: []
|
|
|
18
18
|
extensions: []
|
|
19
19
|
extra_rdoc_files: []
|
|
20
20
|
files:
|
|
21
|
-
- CHANGELOG
|
|
21
|
+
- CHANGELOG
|
|
22
22
|
- Gemfile
|
|
23
23
|
- LICENSE
|
|
24
24
|
- README.md
|
|
@@ -55,7 +55,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
55
55
|
- !ruby/object:Gem::Version
|
|
56
56
|
version: '0'
|
|
57
57
|
requirements: []
|
|
58
|
-
rubygems_version: 4.0.
|
|
58
|
+
rubygems_version: 4.0.18
|
|
59
59
|
specification_version: 4
|
|
60
60
|
summary: Measured values with uncertainty and GUM-conformant error propagation.
|
|
61
61
|
test_files: []
|
data/CHANGELOG.md
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# CHANGELOG
|
|
2
|
-
|
|
3
|
-
## [0.0.0] - 20260716
|
|
4
|
-
## + Measurand: measured values with uncertainty and GUM-conformant error propagation.
|
|
5
|
-
|
|
6
|
-
1. + lib/measurand.rb: Measurand — forward-mode automatic differentiation over a {Source => partial} map; the uncertainty is derived from the partials, not stored, so shared sources correlate (x - x is exactly 0 ± 0).
|
|
7
|
-
2. + Measurand construction: .new, .relative, .cast, .cast\_relative, .from\_samples (mean ± standard error of the mean), .derived
|
|
8
|
-
3. + Measurand arithmetic: +, -, \*, /, \*\*, -@, abs, apply — chain-rule propagation; independent uncertainties combine in quadrature; scalars are exact
|
|
9
|
-
4. + Measurand comparison: ==/eql?/hash (exact: value and uncertainty), <=> (by value, Comparable), consistent\_with?, overlaps?, coerce (scalar-on-the-left arithmetic)
|
|
10
|
-
5. + Measurand readers: value, uncertainty, relative\_uncertainty, exact?
|
|
11
|
-
6. + lib/Measurand/Source.rb: opaque per-source identity carrying its own uncertainty; deliberately no ==/eql?/hash, so shared sources correlate and independently-constructed ones never collapse
|
|
12
|
-
7. + lib/Measurand/Format.rb: uncertainty-driven, PDG-rounded to\_s (ascii: keyword emits +/- instead of ±), to\_parenthetic, inspect (full precision)
|
|
13
|
-
8. + lib/Measurand/Parse.rb: Measurand.parse for ±, +/-, parenthetic (10), relative %, and exact forms; raises ArgumentError rather than returning nil
|
|
14
|
-
9. + lib/Measurand/Math.rb: Measurand::Math.sqrt, exp, log, log10, sin, cos, tan — chain-rule propagation with no Math monkeypatching
|
|
15
|
-
10. + lib/Measurand/Numeric.rb: opt-in Numeric#pm / #± and Enumerable#pm (separate require, so nothing is monkeypatched unless asked)
|
|
16
|
-
11. + lib/Measurand/VERSION.rb
|
|
17
|
-
12. + measurand.gemspec
|
|
18
|
-
13. + Gemfile
|
|
19
|
-
14. + LICENSE
|
|
20
|
-
15. + README.md
|
|
21
|
-
16. + test/test\_helper.rb, test/test\_all.rb
|
|
22
|
-
17. + test/Measurand/Measurand\_test.rb
|
|
23
|
-
18. + test/Measurand/Source\_test.rb
|
|
24
|
-
19. + test/Measurand/Format\_test.rb
|
|
25
|
-
20. + test/Measurand/Parse\_test.rb
|
|
26
|
-
21. + test/Measurand/Math\_test.rb
|
|
27
|
-
22. + test/Measurand/Numeric\_test.rb
|