Class: Plurimath::Formatter::Numbers::Source

Inherits:
Object
  • Object
show all
Defined in:
lib/plurimath/formatter/numbers/source.rb

Overview

Captures raw input, BigDecimal interpretation, and source digit metadata before formatter transforms run.

Constant Summary collapse

DEFAULT_INTEGER =
"0"
EMPTY_STRING =
""
NUMERIC_PATTERN =

Stricter than BigDecimal(), which tolerates underscores, surrounding junk after partial parses, and Infinity/NaN spellings.

/\A[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?\z/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value) ⇒ Source

Returns a new instance of Source.



20
21
22
23
24
25
26
27
28
29
# File 'lib/plurimath/formatter/numbers/source.rb', line 20

def initialize(value)
  @raw = value.to_s
  validate_numeric!(value)
  @decimal = BigDecimal(raw)
  @sign = raw.start_with?("-") ? -1 : 1

  mantissa, @exponent_text = unsigned_value.split("e", 2)
  @exponent = exponent_text.to_i
  @integer_digits, @fraction_digits = split_mantissa(mantissa)
end

Instance Attribute Details

#decimalObject (readonly)

Returns the value of attribute decimal.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def decimal
  @decimal
end

#exponentObject (readonly)

Returns the value of attribute exponent.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def exponent
  @exponent
end

#exponent_textObject (readonly)

Returns the value of attribute exponent_text.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def exponent_text
  @exponent_text
end

#fraction_digitsObject (readonly)

Returns the value of attribute fraction_digits.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def fraction_digits
  @fraction_digits
end

#integer_digitsObject (readonly)

Returns the value of attribute integer_digits.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def integer_digits
  @integer_digits
end

#rawObject (readonly)

Returns the value of attribute raw.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def raw
  @raw
end

#signObject (readonly)

Returns the value of attribute sign.



11
12
13
# File 'lib/plurimath/formatter/numbers/source.rb', line 11

def sign
  @sign
end

Instance Method Details

#decimal_precisionObject



35
36
37
# File 'lib/plurimath/formatter/numbers/source.rb', line 35

def decimal_precision
  decimal_digits.last.length
end

#fractional?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/plurimath/formatter/numbers/source.rb', line 31

def fractional?
  fraction_digits.length > exponent
end

#notation_precisionObject



39
40
41
42
43
44
45
46
47
# File 'lib/plurimath/formatter/numbers/source.rb', line 39

def notation_precision
  # A zero coefficient keeps the source's stated fraction width.
  return fraction_digits.length if decimal.zero?

  # The coefficient's fraction width is its significant-digit count
  # minus the single leading digit; the sign and leading zeros carry
  # no precision.
  [significant_digit_count - 1, 0].max
end

#significant_digit_countObject



49
50
51
# File 'lib/plurimath/formatter/numbers/source.rb', line 49

def significant_digit_count
  significant_digits.length
end

#target_base_integer_length(base) ⇒ Object



53
54
55
56
57
58
59
60
# File 'lib/plurimath/formatter/numbers/source.rb', line 53

def target_base_integer_length(base)
  return decimal_parts_integer_length if base == Base::DEFAULT_BASE

  integer = decimal.abs.to_i
  return 0 if integer.zero?

  integer.to_s(base).length
end

#to_parts(base: nil, precision: nil) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/plurimath/formatter/numbers/source.rb', line 62

def to_parts(base: nil, precision: nil)
  integer, fraction = decimal_digits
  fraction = apply_precision(fraction, precision)

  Parts.new(
    sign: sign,
    base: base || Base::DEFAULT_BASE,
    integer_digits: integer,
    fraction_digits: fraction,
  )
end

#trailing_fraction_zero_countObject



74
75
76
77
78
# File 'lib/plurimath/formatter/numbers/source.rb', line 74

def trailing_fraction_zero_count
  return 0 if fraction_digits.empty?

  fraction_digits.length - fraction_digits.sub(/0+\z/, "").length
end