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.4'
EPSILON =

Epsilon defines rounding precision

14
MODES =

Available clamping modes

[:strict, :cycle, :clamp]

Instance Method Summary collapse

Constructor Details

#initialize(from, to, mode = MODES.first, precision = EPSILON) ⇒ NumScaler

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

Precision defines number of significant decimal digits for rounding.

Parameters:

  • from (Range)

    source range

  • to (Range)

    target range

  • mode (Symbol) (defaults to: MODES.first)

    clamping mode

  • precision (Float) (defaults to: EPSILON)

    rounding precision

Raises:

  • (ArgumentError)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/numscaler.rb', line 24

def initialize(from, to, mode = MODES.first, precision = EPSILON)
  raise ArgumentError, 'Unknown mode' unless MODES.member? mode
  raise ArgumentError, 'Precision out of ranger' unless precision > 0

  @mode = mode
  @prec = precision

  @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

Parameters:

  • num (Numeric)

    number to convert

  • a (Hash)

    source range data

  • b (Hash)

    target range data

Returns:

  • (Numeric)


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/numscaler.rb', line 64

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

Parameters:

  • num (Numeric)

Returns:

  • (Numeric)


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

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

#to(num) ⇒ Numeric

Convert number from target to source

Parameters:

  • num (Numeric)

Returns:

  • (Numeric)


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

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