/
fuzzy_math.rb
80 lines (61 loc) · 1.88 KB
/
fuzzy_math.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# frozen_string_literal: true
module Sass
module Value
# Sass's {FuzzyMath} module.
module FuzzyMath
PRECISION = 10
EPSILON = 10.pow(-PRECISION - 1)
INVERSE_EPSILON = 1 / EPSILON
module_function
def equals(number1, number2)
(number1 - number2).abs < EPSILON
end
def less_than(number1, number2)
number1 < number2 && !equals(number1, number2)
end
def less_than_or_equals(number1, number2)
number1 < number2 || equals(number1, number2)
end
def greater_than(number1, number2)
number1 > number2 && !equals(number1, number2)
end
def greater_than_or_equals(number1, number2)
number1 > number2 || equals(number1, number2)
end
def integer?(number)
return false unless number.finite?
return true if number.integer?
equals((number - 0.5).abs % 1, 0.5)
end
def to_i(number)
integer?(number) ? number.round : nil
end
def round(number)
if number.positive?
less_than(number % 1, 0.5) ? number.floor : number.ceil
else
less_than_or_equals(number % 1, 0.5) ? number.floor : number.ceil
end
end
def between(number, min, max)
return min if equals(number, min)
return max if equals(number, max)
return number if number > min && number < max
nil
end
def assert_between(number, min, max, name)
result = between(number, min, max)
return result unless result.nil?
raise Sass::ScriptError.new("#{number} must be between #{min} and #{max}.", name)
end
def hash(number)
@hash ||= if number.finite?
(number * INVERSE_EPSILON).round.hash
else
number.hash
end
end
end
private_constant :FuzzyMath
end
end