Class: Philiprehberger::Approx::Comparator

Inherits:
Object
  • Object
show all
Defined in:
lib/philiprehberger/approx/comparator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(epsilon: 1e-9, relative: nil) ⇒ Comparator

Create a reusable comparator with preset tolerances

Parameters:

  • epsilon (Float, nil) (defaults to: 1e-9)

    absolute tolerance

  • relative (Float, nil) (defaults to: nil)

    relative tolerance



12
13
14
15
# File 'lib/philiprehberger/approx/comparator.rb', line 12

def initialize(epsilon: 1e-9, relative: nil)
  @epsilon = epsilon
  @relative = relative
end

Instance Attribute Details

#epsilonObject (readonly)

Returns the value of attribute epsilon.



6
7
8
# File 'lib/philiprehberger/approx/comparator.rb', line 6

def epsilon
  @epsilon
end

#relativeObject (readonly)

Returns the value of attribute relative.



6
7
8
# File 'lib/philiprehberger/approx/comparator.rb', line 6

def relative
  @relative
end

Instance Method Details

#assert_near(a, b) ⇒ Object

Assert that two values are approximately equal, raising on mismatch

Parameters:

  • a (Numeric, Array, Hash)

    first value

  • b (Numeric, Array, Hash)

    second value

Raises:

  • (Error)

    if values are not approximately equal



55
56
57
58
59
# File 'lib/philiprehberger/approx/comparator.rb', line 55

def assert_near(a, b)
  return if equal?(a, b)

  raise Error, "expected #{a.inspect} to be near #{b.inspect} (epsilon: #{@epsilon}, relative: #{@relative})"
end

#assert_within(a, b) ⇒ Object

Assert that two values pass within?, raising on mismatch

Parameters:

  • a (Numeric, Array, Hash)

    first value

  • b (Numeric, Array, Hash)

    second value

Raises:

  • (Error)

    if values fail both tolerance checks



102
103
104
# File 'lib/philiprehberger/approx/comparator.rb', line 102

def assert_within(a, b)
  Approx.assert_within(a, b, abs: @epsilon, rel: @relative)
end

#between?(value, min, max) ⇒ Boolean

Check if a numeric value lies within [min, max] with epsilon slack

Parameters:

  • value (Numeric)

    value to test

  • min (Numeric)

    inclusive lower bound

  • max (Numeric)

    inclusive upper bound

Returns:

  • (Boolean)


93
94
95
# File 'lib/philiprehberger/approx/comparator.rb', line 93

def between?(value, min, max)
  Approx.between?(value, min, max, epsilon: @epsilon)
end

#clamp(value, target) ⇒ Numeric

Snap a value to target if approximately equal, otherwise return unchanged

Parameters:

  • value (Numeric)

    the value to potentially snap

  • target (Numeric)

    the target to snap to

Returns:

  • (Numeric)

    target if approximately equal, otherwise value



75
76
77
# File 'lib/philiprehberger/approx/comparator.rb', line 75

def clamp(value, target)
  Approx.clamp(value, target, epsilon: @epsilon)
end

#equal?(a, b) ⇒ Boolean

Check if two values are approximately equal using configured tolerances

Parameters:

  • a (Numeric, Array, Hash)

    first value

  • b (Numeric, Array, Hash)

    second value

Returns:

  • (Boolean)


22
23
24
25
26
27
28
29
30
# File 'lib/philiprehberger/approx/comparator.rb', line 22

def equal?(a, b)
  if @relative && @epsilon
    Approx.within?(a, b, abs: @epsilon, rel: @relative)
  elsif @relative
    Approx.relative_equal?(a, b, tolerance: @relative)
  else
    Approx.equal?(a, b, epsilon: @epsilon)
  end
end

#near?(a, b) ⇒ Boolean

Alias for #equal? matching the module-level near? naming

Parameters:

  • a (Numeric, Array, Hash)

    first value

  • b (Numeric, Array, Hash)

    second value

Returns:

  • (Boolean)


37
38
39
# File 'lib/philiprehberger/approx/comparator.rb', line 37

def near?(a, b)
  equal?(a, b)
end

#relative_equal?(a, b) ⇒ Boolean

Check if two values are approximately equal using relative tolerance

Parameters:

  • a (Numeric, Array, Hash)

    first value

  • b (Numeric, Array, Hash)

    second value

Returns:

  • (Boolean)


66
67
68
# File 'lib/philiprehberger/approx/comparator.rb', line 66

def relative_equal?(a, b)
  Approx.relative_equal?(a, b, tolerance: @relative || @epsilon)
end

#within?(a, b) ⇒ Boolean

Check using combined absolute + relative tolerance from the configured comparator

Parameters:

  • a (Numeric, Array, Hash)

    first value

  • b (Numeric, Array, Hash)

    second value

Returns:

  • (Boolean)


46
47
48
# File 'lib/philiprehberger/approx/comparator.rb', line 46

def within?(a, b)
  Approx.within?(a, b, abs: @epsilon, rel: @relative)
end

#zero?(value) ⇒ Boolean

Check if a numeric value is approximately zero

Parameters:

  • value (Numeric)

    value to test

Returns:

  • (Boolean)


83
84
85
# File 'lib/philiprehberger/approx/comparator.rb', line 83

def zero?(value)
  Approx.zero?(value, epsilon: @epsilon)
end