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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77e11fd475e1104e6ff1b26e9d0528c9e6918a0340832106b58eefe09b46da1e
4
- data.tar.gz: ca6538ff0f68ec369df90ced58ab97aa8ed4083680a3c4f4f555f5af80b7ee63
3
+ metadata.gz: 4caf91e22da69c556702463204bf65ea9eec1c52b6dcaf05552fc0c91405af22
4
+ data.tar.gz: be7b0a5d116588a0aad0dac6f9aa7b7eda71eeedb0efb0f45d4ab8d0768a15bb
5
5
  SHA512:
6
- metadata.gz: 48bf9b4e4110cede8150f8abd1521d39e9e39c701d3db7cd0e9697fef8e59aba0e2ac21dd60590b8b71be8d6845bc14212ecc896f1a3085c45cb85ca433dc19e
7
- data.tar.gz: 99f5e0811d117c252c0d703b144f30f1283f72d47ffb65b2b07e27d603357f7ac6cc4aa4c4413e1754c54d9734a2f7e9cf7db3abf754c89eb74fae73dc233762
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  class Measurand
2
- VERSION = '0.0.0'
2
+ VERSION = '0.1.0'
3
3
  end
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
- 'CHANGELOG.md',
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.0.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.md
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.16
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