class Numerals::Format::BaseScaler
This converts the number representation contained in an ExpSetter scaling the base of the significand.
This is typically used when the ExpSetter base is 2 to render the number in C99 '%A' format, i.e., in hexadecimal base. Only the significand is shown in base 16; the exponent is still a power of two, and represented in base 10.
This is a generalization of the %A format where any base which is a power of the original base can be used for the significand.
The number exponent is previously adjusted in the ExpSetter and that doesn't change, only the significand parts are converted from the original base `base` to the new base `base**base_scale`.
This will require adjusting the repeating digits position and length, and adding leading 0s (in the original base) to the signficant and/or trailing digits may be required.
Attributes
Public Class Methods
# File lib/numerals/format/base_scaler.rb, line 26 def initialize(exp_setter, base_scale) @setter = exp_setter @numeral = @setter.numeral @base_scale = base_scale @scaled_base = @setter.base**@base_scale adjust end
Private Class Methods
Convert base digits to scaled base digits
# File lib/numerals/format/base_scaler.rb, line 147 def self.ungrouped_digits(digits, base, base_scale) digits.flat_map { |d| group = Digits[base: base] group.value = d ungrouped = group.digits_array if ungrouped.size < base_scale ungrouped = [0]*(base_scale - ungrouped.size) + ungrouped end ungrouped } end
Public Instance Methods
# File lib/numerals/format/base_scaler.rb, line 43 def base scaled_base end
# File lib/numerals/format/base_scaler.rb, line 56 def fractional_insignificant_size if @setter.numeral.approximate? (@setter.fractional_insignificant_size + @scaling_trailing_size)/@base_scale else 0 end end
# File lib/numerals/format/base_scaler.rb, line 47 def fractional_part ungrouped = @setter.fractional_part + (0...@scaling_trailing_size).map{|i| repeat_digit(i)} grouped_digits ungrouped end
# File lib/numerals/format/base_scaler.rb, line 52 def fractional_part_size (@setter.fractional_part_size + @scaling_trailing_size)/@base_scale end
# File lib/numerals/format/base_scaler.rb, line 73 def integer_insignificant_size if @setter.numeral.approximate? (@setter.integer_insignificant_size + @scaling_leading_size)/@base_scale else 0 end end
# File lib/numerals/format/base_scaler.rb, line 64 def integer_part ungrouped = [0]*@scaling_leading_size + @setter.integer_part grouped_digits ungrouped end
# File lib/numerals/format/base_scaler.rb, line 69 def integer_part_size (@setter.integer_part_size + @scaling_leading_size)/@base_scale end
# File lib/numerals/format/base_scaler.rb, line 85 def repeat_insignificant_size 0 end
# File lib/numerals/format/base_scaler.rb, line 89 def repeat_part ungrouped = (@scaling_trailing_size...@scaling_trailing_size+@repeat_length).map{|i| repeat_digit(i)} grouped_digits ungrouped end
# File lib/numerals/format/base_scaler.rb, line 81 def repeat_size_size @repeat_length/@base_scale end
Private Instance Methods
# File lib/numerals/format/base_scaler.rb, line 124 def adjust return if special? @setter_repeat_part = @setter.repeat_part @setter_repeat_part_size = @setter.repeat_part_size @scaling_trailing_size = padding_size(@setter.fractional_part_size) @scaling_leading_size = padding_size(@setter.integer_part_size) @repeat_length = @setter.repeat_part_size while (@repeat_length % @base_scale) != 0 @repeat_length += @setter.repeat_part_size end end
Convert base `exponent_base` digits to base `scaled_base` digits the number of digits must be a multiple of base_scale
# File lib/numerals/format/base_scaler.rb, line 111 def grouped_digits(digits) unless (digits.size % @base_scale) == 0 raise "Invalid number of digits for group_digits (#{digits.size} is not a multiple of #{@base_scale})" end digits.each_slice(@base_scale).map{|group| scaled_digit(group)} end
Number of digits (base `exponent_base`) to be added to make the number of digits a multiple of `base_scale`.
# File lib/numerals/format/base_scaler.rb, line 120 def padding_size(digits_size) (@base_scale - digits_size) % @base_scale end
# File lib/numerals/format/base_scaler.rb, line 138 def repeat_digit(i) if @setter_repeat_part_size > 0 @setter_repeat_part[i % @setter_repeat_part_size] else 0 end end
Return the `scaled_base` digit corresponding to a group of `base_scale` `exponent_base` digits
# File lib/numerals/format/base_scaler.rb, line 97 def scaled_digit(group) unless group.size == @base_scale raise "Invalid digits group size for scaled_digit (is #{group.size}; should be #{@base_scale})" end v = 0 group.each do |digit| v *= @setter.base v += digit end v end