Module: Horologium::Numeric::Precision Private
- Defined in:
- lib/horologium/numeric/precision.rb,
sig/horologium/numeric/precision.rbs
Overview
This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.
The precision a value computes with: :standard, the fast two-part float
(TwoPartFloat), or :exact, the lossless Rational (Exact). This
module holds the rules that decide the precision of a result and coerce a
value from one precision into another.
The rule for a result is that exactness is contagious: an operation
between two :standard values stays :standard, but mixing :standard
with :exact promotes to :exact rather than dropping to :standard.
Promotion loses nothing, because a two-part float pair is already an
exact Rational. What :exact guarantees is Horologium's own arithmetic.
It cannot bring back precision an input already lost when it was built.
Constant Summary collapse
- NAMES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
The recognised precisions.
%i[standard exact].freeze
Class Method Summary collapse
-
.coerce(value, to:) ⇒ TwoPartFloat, Exact
private
Coerces a numeric value into a precision, losslessly.
-
.resolve(left, right) ⇒ Symbol
private
The precision a result takes from its two operands.
-
.validate!(precision) ⇒ Symbol
private
Checks that a precision is recognised and returns it.
-
.value_type(precision) ⇒ Class
private
The numeric type a value takes at a precision: Exact for
:exactand TwoPartFloat for:standard.
Class Method Details
.coerce(value, to:) ⇒ Exact .coerce(value, to:) ⇒ TwoPartFloat .coerce(value, to:) ⇒ TwoPartFloat, Exact
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Coerces a numeric value into a precision, losslessly. Promoting a
:standard value to :exact keeps its exact value; a value already
in the target precision is returned unchanged. There is no lossy
path: the contagion rule never moves an :exact value down to
:standard, and asking for that raises an error.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/horologium/numeric/precision.rb', line 62 def coerce(value, to:) case to when :exact value.is_a?(Exact) ? value : Exact.new(value) when :standard unless value.is_a?(TwoPartFloat) raise ArgumentError, "cannot coerce #{value.class} down to :standard without loss" end value else raise UnknownPrecisionError.new(to, NAMES) end end |
.resolve(left, right) ⇒ Symbol
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The precision a result takes from its two operands. Same precision
passes through; a mix of :standard and :exact promotes to
:exact.
42 43 44 45 46 47 48 |
# File 'lib/horologium/numeric/precision.rb', line 42 def resolve(left, right) validate!(left) validate!(right) return :exact if left == :exact || right == :exact :standard end |
.validate!(precision) ⇒ Symbol
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Checks that a precision is recognised and returns it.
28 29 30 31 32 |
# File 'lib/horologium/numeric/precision.rb', line 28 def validate!(precision) return precision if NAMES.include?(precision) raise UnknownPrecisionError.new(precision, NAMES) end |
.value_type(precision) ⇒ Class
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The numeric type a value takes at a precision: Exact for :exact
and TwoPartFloat for :standard.
83 84 85 |
# File 'lib/horologium/numeric/precision.rb', line 83 def value_type(precision) (validate!(precision) == :exact) ? Exact : TwoPartFloat end |