Class: NumScaler

Inherits:
Object
  • Object
show all
Defined in:
lib/numscaler.rb

Overview

See README for practical examples.

Constant Summary collapse

VERSION =

NumScaler version string

'0.0.5'
EPSILON =

Epsilon defines rounding precision

14
MODES =

Available clamping modes

[:strict, :cycle, :clamp]

Instance Method Summary collapse

Constructor Details

#initialize(from, to, options = {}) ⇒ NumScaler

Additional options:

  • :mode - specify clamping mode (default: :strict)
  • :precision - specify Float rounding (default: EPSILON)

Precision defines number of significant decimal digits for rounding.

Current clamping modes:

  • :strict - raise ArgumentError for out-of-range number (default)
  • :clamp - clamp number to source range
  • :cycle - treat range as a circle of values

Raises:

  • (ArgumentError)

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/numscaler.rb', line 28

def initialize(from, to, options = {})
  @mode = options[:mode] || MODES.first
  @prec = options[:precision] || EPSILON

  raise ArgumentError, 'Unknown mode' unless MODES.member? @mode
  raise ArgumentError, 'Precision out of range' unless @prec > 0

  @src = { :orig  => from.min,
           :range => from.max.to_f - from.min.to_f,
           :max   => from.max.to_f,
           :min   => from.min.to_f }
  @tgt = { :orig  => to.min,
           :range => to.max.to_f - to.min.to_f,
           :max   => to.max.to_f,
           :min   => to.min.to_f }
end

Instance Method Details

#calc(num, a, b) ⇒ Numeric (private)

Perform actual calculation:

  1. First check and if necessary apply clamping
  2. Then convert between ranges
  3. Lastly check how to exactly return the result and do so

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/numscaler.rb', line 68

def calc(num, a, b)
  num = num.to_f

  unless num.between?(a[:min], a[:max])
    num = case @mode
          when :cycle
            ((num - a[:min]) % (a[:range])) + a[:min]
          when :clamp
            num > a[:max] ? a[:max] : a[:min]
          when :strict
            raise ArgumentError, 'Number out of range'
          end
  end

  res = (((num - a[:min]) * b[:range]) / a[:range]) + b[:min]

  case b[:orig]
  when Integer
    res.round
  else
    res.round(@prec)
  end
end

#from(num) ⇒ Numeric

Convert number from source to target


49
# File 'lib/numscaler.rb', line 49

def from(num); calc(num, @src, @tgt); end

#to(num) ⇒ Numeric

Convert number from target to source


55
# File 'lib/numscaler.rb', line 55

def to(num);   calc(num, @tgt, @src); end