bigdecimal-pure 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: dc0062663b0a3bfb0ae8756397f9e02443c49dacb965a6a3da25e01d39c7554a
4
+ data.tar.gz: 703b2fb877149972cf23ad3f5b0791510d4f5ed6932f3c8f5134d8c0053a37cd
5
+ SHA512:
6
+ metadata.gz: 2e60b3c1dc4e26635a84add8eabbdfecb67007be7764318fbbcaaa38c3b9df14129c16e9686a090bbf5848c4b2501e3f629c03c1cdb72c96ab46e5b26bb8b9eb
7
+ data.tar.gz: 9e23c4e38485648472c94c441199de7cc6a306b014d5b2653fa899a257b6c2a258716e512704e1dcc4b38fc833d49db3c2d82e8c5ebacf5e192f5f621c62b7aa
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ ## [0.1.0] - 2026-09-30
4
+
5
+ - First release: BigDecimal in pure Ruby on Rational, taken from the ruby.wasm
6
+ sandbox of Ren. `require 'bigdecimal'` prefers the native gem when installed.
7
+
8
+ [0.1.0]: https://github.com/Largo/bigdecimal-pure/releases/tag/v0.1.0
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Andi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # bigdecimal-pure
2
+
3
+ BigDecimal in pure Ruby, for places where the C extension cannot run —
4
+ ruby.wasm above all. Where the native `bigdecimal` gem is installed, it wins
5
+ automatically.
6
+
7
+ ```ruby
8
+ gem 'bigdecimal-pure'
9
+ ```
10
+
11
+ ```ruby
12
+ require 'bigdecimal' # native if available, pure Ruby otherwise
13
+ require 'bigdecimal/util' # to_d, either way
14
+
15
+ BigDecimal('0.1') + BigDecimal('0.2') # => 0.3e0
16
+ BigDecimalPure.pure? # which one you got
17
+ ```
18
+
19
+ `require 'bigdecimal/pure'` loads the pure class unconditionally (unless a
20
+ BigDecimal is already defined). `BIGDECIMAL_PURE=1` makes `require 'bigdecimal'`
21
+ skip the native one.
22
+
23
+ ## How the native one is found
24
+
25
+ `require 'bigdecimal'` activates the `bigdecimal` gem if it is installed (under
26
+ Bundler: if it is in the bundle), then loads the first `bigdecimal.rb` on the
27
+ load path that is not this gem's; on old Rubies it falls back to
28
+ `bigdecimal.so`. Only when all of that fails does the pure class load.
29
+
30
+ ## What the pure class does
31
+
32
+ Built on `Rational`, so it is exact where BigDecimal is exact:
33
+
34
+ - decimal strings (`"0.1" + "0.2"` is `0.3`), `+ - *`, rounding;
35
+ - division and `sqrt` to 20 significant digits by default, like the original;
36
+ - `round/floor/ceil/truncate` with digits and all `ROUND_*` modes;
37
+ - `to_s` as `0.123e1`, `to_s('F')` as `1.23`; comparisons with Integer, Float
38
+ and Rational; `to_d` from `bigdecimal/util`; `Marshal`.
39
+
40
+ Not supported: NaN and Infinity (they raise), `BigDecimal.limit` and `.mode`,
41
+ precision bookkeeping. `BigMath` goes through Float, so it is good to about 15
42
+ digits whatever precision is asked for.
43
+
44
+ Unlike [hanami-wasm's shim](https://github.com/katafrakt/hanami-wasm)
45
+ (`BigDecimal(v) = v.to_i`), the value is kept: `BigDecimal("0.1")` is not 0.
46
+
47
+ ## Tests
48
+
49
+ ```
50
+ bundle exec rake
51
+ ```
52
+
53
+ ## License
54
+
55
+ MIT
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # `require 'bigdecimal/math'`: the native file with the native bigdecimal. The
4
+ # pure class defines everything of bigdecimal/math itself.
5
+ require_relative '../bigdecimal'
6
+
7
+ BigDecimalPure.require_native('bigdecimal/math') unless BigDecimalPure.pure?
@@ -0,0 +1,327 @@
1
+ # frozen_string_literal: true
2
+
3
+ # BigDecimal in pure Ruby, on top of Rational. lib/bigdecimal.rb loads this only
4
+ # when no native bigdecimal can be found (ruby.wasm, sandboxes without a
5
+ # compiler). Require it directly to get the pure version regardless.
6
+ #
7
+ # Like the C version: decimal strings exactly ("0.1" + "0.2" is 0.3), + - *
8
+ # exactly, division and sqrt to 20 significant digits by default,
9
+ # round/floor/ceil/truncate with digits and the ROUND_* modes, to_s ("0.3e0",
10
+ # or "0.3" with to_s('F')), comparisons with Integer, Float and Rational, to_d.
11
+ # Not: NaN and Infinity (they raise), BigDecimal.limit and .mode, precision
12
+ # bookkeeping. BigMath goes through Float, so it is good to about 15 digits.
13
+
14
+ require_relative '../bigdecimal_pure/version'
15
+
16
+ return if defined?(BigDecimal)
17
+
18
+ # rubocop:disable Lint/BigDecimalNew, Naming/PredicateMethod, Style/ReturnNilInPredicateMethodDefinition
19
+ # -- this is BigDecimal: .new is its own constructor, and infinite?/nonzero? answer
20
+ # nil as the C version does.
21
+ class BigDecimal < Numeric
22
+ ROUND_MODE = 256
23
+ ROUND_UP = 1
24
+ ROUND_DOWN = 2
25
+ ROUND_HALF_UP = 3
26
+ ROUND_HALF_DOWN = 4
27
+ ROUND_CEILING = 5
28
+ ROUND_FLOOR = 6
29
+ ROUND_HALF_EVEN = 7
30
+ SIGN_POSITIVE_ZERO = 1
31
+ SIGN_NEGATIVE_ZERO = -1
32
+ SIGN_POSITIVE_FINITE = 2
33
+ SIGN_NEGATIVE_FINITE = -2
34
+ DIV_DIGITS = 20
35
+ VERSION = BigDecimalPure::VERSION
36
+ PURE = true
37
+
38
+ DECIMAL = /\A\s*([+-]?)(\d[\d_]*)?(?:\.(\d[\d_]*)?)?(?:[eEdD]([+-]?\d+))?\s*\z/
39
+
40
+ attr_reader :rational
41
+ protected :rational
42
+
43
+ def self.parse(text)
44
+ match = DECIMAL.match(text)
45
+ if match.nil? || (match[2].nil? && match[3].nil?)
46
+ raise ArgumentError, "invalid value for BigDecimal(): #{text.inspect}"
47
+ end
48
+
49
+ whole = match[2].to_s.delete('_')
50
+ fraction = match[3].to_s.delete('_')
51
+ digits = Integer("#{whole}#{fraction}".sub(/\A0+(?=\d)/, '').then { |s| s.empty? ? '0' : s }, 10)
52
+ value = Rational(digits, 10**fraction.length) * (Rational(10)**match[4].to_i)
53
+ match[1] == '-' ? -value : value
54
+ end
55
+
56
+ def self.from(value, digits = 0)
57
+ case value
58
+ when BigDecimal then value
59
+ when Integer then new(Rational(value))
60
+ when Rational then new(digits.positive? ? round_significant(value, digits) : value)
61
+ when Float
62
+ raise FloatDomainError, value.to_s unless value.finite?
63
+
64
+ new(digits.positive? ? round_significant(value.to_r, digits) : parse(value.to_s))
65
+ when String then new(parse(value))
66
+ else
67
+ raise TypeError, "can't convert #{value.class} into BigDecimal" unless value.respond_to?(:to_r)
68
+
69
+ new(value.to_r)
70
+ end
71
+ end
72
+
73
+ # Rounds to `digits` significant digits, half up.
74
+ def self.round_significant(value, digits)
75
+ return Rational(0) if value.zero?
76
+
77
+ exponent = Math.log10(value.abs.to_f).floor rescue 0 # rubocop:disable Style/RescueModifier
78
+ scale = digits - exponent - 1
79
+ Rational((value * (Rational(10)**scale)).round, 1) / (Rational(10)**scale)
80
+ end
81
+
82
+ def self.double_fig = 16
83
+ def self.limit(*) = 0
84
+ def self.mode(*) = 0
85
+ def self.save_rounding_mode = yield
86
+ def self.save_exception_mode = yield
87
+ def self.save_limit = yield
88
+
89
+ def initialize(rational)
90
+ super()
91
+ @rational = rational
92
+ freeze
93
+ end
94
+
95
+ def to_r = @rational
96
+ def to_i = @rational.truncate
97
+ alias to_int to_i
98
+ def to_f = @rational.to_f
99
+ def to_d = self
100
+ def zero? = @rational.zero?
101
+ def nonzero? = zero? ? nil : self
102
+ def negative? = @rational.negative?
103
+ def positive? = @rational.positive?
104
+ def finite? = true
105
+ def infinite? = nil
106
+ def nan? = false
107
+ def integer? = false
108
+ def real? = true
109
+ def hash = @rational.hash
110
+ def precs = [digits_of.length, digits_of.length + DIV_DIGITS]
111
+ def precision = digits_of.length
112
+ def exponent = zero? ? 0 : Math.log10(@rational.abs.to_f).floor + 1
113
+
114
+ def sign
115
+ if zero? then SIGN_POSITIVE_ZERO
116
+ else negative? ? SIGN_NEGATIVE_FINITE : SIGN_POSITIVE_FINITE
117
+ end
118
+ end
119
+
120
+ def coerce(other) = [BigDecimal.from(other), self]
121
+ def -@ = BigDecimal.new(-@rational)
122
+ def +@ = self
123
+ def abs = BigDecimal.new(@rational.abs)
124
+
125
+ def +(other) = BigDecimal.new(@rational + value_of(other))
126
+ def -(other) = BigDecimal.new(@rational - value_of(other))
127
+ def *(other) = BigDecimal.new(@rational * value_of(other))
128
+
129
+ def /(other)
130
+ divisor = value_of(other)
131
+ raise ZeroDivisionError, 'divided by 0' if divisor.zero?
132
+
133
+ exact = @rational / divisor
134
+ terminating?(exact) ? BigDecimal.new(exact) : BigDecimal.new(BigDecimal.round_significant(exact, DIV_DIGITS))
135
+ end
136
+ alias quo /
137
+
138
+ def add(other, digits) = limit(self + other, digits)
139
+ def sub(other, digits) = limit(self - other, digits)
140
+ def mult(other, digits) = limit(self * other, digits)
141
+
142
+ def div(other, digits = nil)
143
+ return (self / other).floor if digits.nil?
144
+
145
+ divisor = value_of(other)
146
+ raise ZeroDivisionError, 'divided by 0' if divisor.zero?
147
+
148
+ digits.zero? ? self / other : BigDecimal.new(BigDecimal.round_significant(@rational / divisor, digits))
149
+ end
150
+
151
+ def %(other) = BigDecimal.new(@rational % value_of(other))
152
+ alias modulo %
153
+ def remainder(other) = BigDecimal.new(@rational.remainder(value_of(other)))
154
+ def divmod(other) = [div(other), self % other]
155
+
156
+ def **(other)
157
+ return BigDecimal.new(@rational**other) if other.is_a?(Integer)
158
+
159
+ BigDecimal.from(to_f**other.to_f, DIV_DIGITS)
160
+ end
161
+ alias power **
162
+
163
+ def sqrt(digits = DIV_DIGITS)
164
+ raise FloatDomainError, 'sqrt of negative value' if negative?
165
+
166
+ BigDecimal.from(Math.sqrt(to_f), [digits, 15].min)
167
+ end
168
+
169
+ def <=>(other)
170
+ other.is_a?(Numeric) ? @rational <=> value_of(other) : nil
171
+ end
172
+
173
+ def ==(other) = other.is_a?(Numeric) && @rational == value_of(other)
174
+ alias eql? ==
175
+ alias === ==
176
+ include Comparable
177
+
178
+ # Without digits an Integer, as in the C version; with digits a BigDecimal.
179
+ def round(*args, half: nil)
180
+ digits = args[0].is_a?(Integer) ? args[0] : 0
181
+ half = { up: ROUND_HALF_UP, down: ROUND_HALF_DOWN, even: ROUND_HALF_EVEN }[half]
182
+ mode = args.find { |arg| arg.is_a?(Symbol) } || (args[1].is_a?(Integer) ? args[1] : nil) || half || ROUND_HALF_UP
183
+ rounded = round_to(digits, mode)
184
+ args.empty? ? rounded.to_i : rounded
185
+ end
186
+
187
+ def floor(digits = 0) = digits.zero? ? @rational.floor : round_to(digits, ROUND_FLOOR)
188
+ def ceil(digits = 0) = digits.zero? ? @rational.ceil : round_to(digits, ROUND_CEILING)
189
+ def truncate(digits = 0) = digits.zero? ? @rational.truncate : round_to(digits, ROUND_DOWN)
190
+ alias fix truncate
191
+
192
+ def frac = BigDecimal.new(@rational - @rational.truncate)
193
+
194
+ # "0.123e1" like the C version; to_s('F') for plain notation.
195
+ def to_s(format = nil)
196
+ return plain if format.to_s.upcase.include?('F')
197
+ return '0.0' if zero?
198
+
199
+ digits = digits_of
200
+ "#{'-' if negative?}0.#{digits}e#{exponent_of}"
201
+ end
202
+
203
+ def inspect = to_s
204
+ def to_digits = plain
205
+
206
+ def _dump(_level = 0) = to_s
207
+ def self._load(text) = from(text)
208
+
209
+ private
210
+
211
+ def value_of(other)
212
+ case other
213
+ when BigDecimal then other.rational
214
+ when Integer, Rational then other.to_r
215
+ when Float
216
+ raise FloatDomainError, other.to_s unless other.finite?
217
+
218
+ BigDecimal.parse(other.to_s)
219
+ else
220
+ raise TypeError, "#{other.class} can't be coerced into BigDecimal" unless other.respond_to?(:to_r)
221
+
222
+ other.to_r
223
+ end
224
+ end
225
+
226
+ def limit(value, digits)
227
+ digits.to_i.positive? ? BigDecimal.new(BigDecimal.round_significant(value.to_r, digits.to_i)) : value
228
+ end
229
+
230
+ def terminating?(value)
231
+ denominator = value.denominator
232
+ denominator /= 2 while (denominator % 2).zero?
233
+ denominator /= 5 while (denominator % 5).zero?
234
+ denominator == 1
235
+ end
236
+
237
+ # All significant digits, without leading or trailing zeros.
238
+ def digits_of
239
+ text = plain.delete('-').delete('.').sub(/\A0+/, '').sub(/0+\z/, '')
240
+ text.empty? ? '0' : text
241
+ end
242
+
243
+ def exponent_of
244
+ whole, fraction = plain.delete('-').split('.')
245
+ return whole.length if whole != '0'
246
+
247
+ -(fraction.length - fraction.sub(/\A0+/, '').length)
248
+ end
249
+
250
+ # Plain decimal notation. Every value here terminates: strings, Integers and
251
+ # Floats parse to finite decimals, and division rounds when it would not.
252
+ def plain
253
+ value = @rational.abs
254
+ scale = 0
255
+ scale += 1 until (value * (10**scale)).denominator == 1 || scale > 1000
256
+ digits = (value * (10**scale)).round.to_s.rjust(scale + 1, '0')
257
+ whole = digits[0...(digits.length - scale)]
258
+ fraction = scale.zero? ? '0' : digits[(digits.length - scale)..].sub(/0+\z/, '')
259
+ fraction = '0' if fraction.empty?
260
+ "#{'-' if negative?}#{whole}.#{fraction}"
261
+ end
262
+
263
+ def round_to(digits, mode)
264
+ scale = Rational(10)**digits
265
+ scaled = @rational * scale
266
+ whole = case mode
267
+ when ROUND_UP, :up then scaled.negative? ? scaled.floor : scaled.ceil
268
+ when ROUND_DOWN, :down, :truncate then scaled.truncate
269
+ when ROUND_CEILING, :ceiling, :ceil then scaled.ceil
270
+ when ROUND_FLOOR, :floor then scaled.floor
271
+ when ROUND_HALF_DOWN, :half_down then half(scaled, :down)
272
+ when ROUND_HALF_EVEN, :half_even, :banker then half(scaled, :even)
273
+ else scaled.round(half: :up)
274
+ end
275
+ BigDecimal.new(Rational(whole) / scale)
276
+ end
277
+
278
+ def half(scaled, way) = scaled.round(half: way)
279
+ end
280
+ # rubocop:enable Lint/BigDecimalNew, Naming/PredicateMethod, Style/ReturnNilInPredicateMethodDefinition
281
+
282
+ module Kernel
283
+ def BigDecimal(value, digits = 0, exception: true) # rubocop:disable Naming/MethodName
284
+ BigDecimal.from(value, digits)
285
+ rescue ArgumentError, TypeError
286
+ raise if exception
287
+
288
+ nil
289
+ end
290
+ module_function :BigDecimal
291
+ public :BigDecimal
292
+ end
293
+
294
+ # bigdecimal/util: to_d on the numbers and strings.
295
+ class Integer
296
+ def to_d = BigDecimal(self)
297
+ end
298
+
299
+ class Float
300
+ def to_d(digits = 0) = BigDecimal(self, digits)
301
+ end
302
+
303
+ class Rational
304
+ def to_d(digits) = BigDecimal(self, digits)
305
+ end
306
+
307
+ class String
308
+ def to_d = BigDecimal(self, exception: false) || BigDecimal(0)
309
+ end
310
+
311
+ class NilClass
312
+ def to_d = BigDecimal(0)
313
+ end
314
+
315
+ # bigdecimal/math, through Float: about 15 good digits whatever is asked for.
316
+ module BigMath
317
+ module_function
318
+
319
+ def exp(value, digits) = BigDecimal(Math.exp(value.to_f), [digits, 15].min)
320
+ def log(value, digits) = BigDecimal(Math.log(value.to_f), [digits, 15].min)
321
+ def sqrt(value, digits) = BigDecimal(value).sqrt(digits)
322
+ def PI(digits) = BigDecimal(Math::PI, [digits, 15].min) # rubocop:disable Naming/MethodName
323
+ def E(digits) = BigDecimal(Math::E, [digits, 15].min) # rubocop:disable Naming/MethodName
324
+ def sin(value, digits) = BigDecimal(Math.sin(value.to_f), [digits, 15].min)
325
+ def cos(value, digits) = BigDecimal(Math.cos(value.to_f), [digits, 15].min)
326
+ def atan(value, digits) = BigDecimal(Math.atan(value.to_f), [digits, 15].min)
327
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # `require 'bigdecimal/util'`: the native file with the native bigdecimal. The
4
+ # pure class defines everything of bigdecimal/util itself.
5
+ require_relative '../bigdecimal'
6
+
7
+ BigDecimalPure.require_native('bigdecimal/util') unless BigDecimalPure.pure?
data/lib/bigdecimal.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # `require 'bigdecimal'`: the native bigdecimal when it is installed, else the
4
+ # pure Ruby one from this gem.
5
+ require_relative 'bigdecimal_pure'
6
+
7
+ require_relative 'bigdecimal/pure' unless defined?(BigDecimal) || BigDecimalPure.require_native('bigdecimal')
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BigDecimalPure
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'bigdecimal_pure/version'
4
+
5
+ # Finds the native bigdecimal, if there is one, so that `require 'bigdecimal'`
6
+ # gets it and this gem's pure Ruby class only fills in where it is missing.
7
+ module BigDecimalPure
8
+ OWN_LIB = File.expand_path(__dir__)
9
+
10
+ module_function
11
+
12
+ # true once the pure class is the BigDecimal in use.
13
+ def pure? = defined?(::BigDecimal::PURE) ? true : false
14
+
15
+ # true when the native extension is the BigDecimal in use.
16
+ def native? = defined?(::BigDecimal) && !pure? ? true : false
17
+
18
+ # Loads the native `feature` ("bigdecimal", "bigdecimal/util", ...), or
19
+ # returns false when there is none. BIGDECIMAL_PURE=1 forces false.
20
+ def require_native(feature)
21
+ return false if ENV['BIGDECIMAL_PURE'] == '1'
22
+
23
+ activate_native_gem
24
+ path = native_path(feature)
25
+ if path
26
+ require path
27
+ true
28
+ elsif feature == 'bigdecimal'
29
+ require_native_extension
30
+ else
31
+ false
32
+ end
33
+ end
34
+
35
+ # The bigdecimal gem, installed next to this one: put its lib on the load
36
+ # path. Under Bundler this only works if it is in the bundle, which is right.
37
+ def activate_native_gem
38
+ return unless defined?(Gem) && Gem.respond_to?(:try_activate)
39
+
40
+ gem 'bigdecimal'
41
+ rescue LoadError, StandardError
42
+ nil
43
+ end
44
+
45
+ # "<feature>.rb" anywhere on the load path except in this gem.
46
+ def native_path(feature)
47
+ $LOAD_PATH.each do |dir|
48
+ dir = File.expand_path(dir.to_s)
49
+ next if dir == OWN_LIB
50
+
51
+ candidate = File.join(dir, "#{feature}.rb")
52
+ return candidate if File.file?(candidate)
53
+ end
54
+ nil
55
+ end
56
+
57
+ # Old Rubies ship only bigdecimal.so, without a Ruby part.
58
+ def require_native_extension
59
+ require 'bigdecimal.so'
60
+ true
61
+ rescue LoadError
62
+ false
63
+ end
64
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bigdecimal-pure
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andi
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: "`require 'bigdecimal'` loads the native bigdecimal when it is installed
13
+ and a pure Ruby BigDecimal on Rational otherwise, for ruby.wasm and other places
14
+ without a C compiler."
15
+ email:
16
+ - andi@idogawa.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - CHANGELOG.md
22
+ - LICENSE
23
+ - README.md
24
+ - lib/bigdecimal.rb
25
+ - lib/bigdecimal/math.rb
26
+ - lib/bigdecimal/pure.rb
27
+ - lib/bigdecimal/util.rb
28
+ - lib/bigdecimal_pure.rb
29
+ - lib/bigdecimal_pure/version.rb
30
+ homepage: https://github.com/Largo/bigdecimal-pure
31
+ licenses:
32
+ - MIT
33
+ metadata:
34
+ homepage_uri: https://github.com/Largo/bigdecimal-pure
35
+ changelog_uri: https://github.com/Largo/bigdecimal-pure/blob/main/CHANGELOG.md
36
+ rubygems_mfa_required: 'true'
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '3.1'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubygems_version: 4.0.20
52
+ specification_version: 4
53
+ summary: BigDecimal in pure Ruby, used only where the native one is missing.
54
+ test_files: []