epitools 0.5.134 → 0.5.137

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,131 @@
1
+ #
2
+ # A fraction! (Like a Rational, but ... uh ... in pure Ruby!)
3
+ #
4
+ # Can be compared, added, multiplied, simplified, "percent"ed, "to_f"ed, and printed/inspected.
5
+ #
6
+ class Fraction
7
+
8
+ attr_accessor :first, :last
9
+
10
+ alias_method :top, :first
11
+ alias_method :bottom, :last
12
+
13
+ alias_method :numerator, :first
14
+ alias_method :denominator, :last
15
+
16
+ #
17
+ # `first` is the top part of the fraction, `last` is the bottom (eg: `first/last`)
18
+ #
19
+ def initialize(first, last=1)
20
+ @first = first
21
+ @last = last
22
+ end
23
+
24
+ def self.[](*args)
25
+ new(*args)
26
+ end
27
+
28
+ include Comparable
29
+
30
+ def <=>(other)
31
+ to_f <=> other.to_f
32
+ end
33
+
34
+ #
35
+ # Returns a string representation: "a/b"
36
+ #
37
+ def to_s
38
+ "#{@first}/#{@last}"
39
+ end
40
+ alias_method :fraction, :to_s
41
+
42
+ #
43
+ # Returns the fraction as a float. (eg: Fraction[1,2].to_f == 0.5)
44
+ #
45
+ def to_f
46
+ if @last == 0
47
+ raise ZeroDivisionError
48
+ else
49
+ @first.to_f / @last
50
+ end
51
+ end
52
+
53
+ #
54
+ # Returns a string representing the number in percent
55
+ #
56
+ def percent
57
+ "%0.1f%%" % (to_f * 100)
58
+ end
59
+ alias_method :to_percent, :percent
60
+
61
+ #
62
+ # "#<Fraction: 1/2>"
63
+ #
64
+ def inspect
65
+ "#<Fraction: #{to_s}>"
66
+ end
67
+
68
+ #
69
+ # Adds together the tops and bottoms of the fractions.
70
+ #
71
+ # Example: For the fractions `a/c` and `b/d`, returns `a+b/c+d`
72
+ #
73
+ def +(r)
74
+ case r
75
+ when Integer
76
+ self + Fraction[r]
77
+ when Fraction
78
+ Fraction[ r.last*first + r.first*last, r.last*last ]
79
+ else
80
+ raise TypeError.new("Sorry, I can't add a Fraction and a #{r.class}. :(")
81
+ end
82
+ end
83
+
84
+ #
85
+ # Multiply the fractions
86
+ #
87
+ def *(v)
88
+ case v
89
+ when Integer
90
+ Fraction[ v*first, v*last ]
91
+ when Fraction
92
+ Fraction[ v.first*first, v.last*last ]
93
+ else
94
+ raise TypeError.new("I don't know how to multiply a Fraction and a #{v.class}. Sorry. :(")
95
+ end
96
+ end
97
+
98
+ def simplify
99
+ require 'prime'
100
+
101
+ # factor the numerator and denominator into hashes of { factor => exponent } pairs
102
+ n_fact, d_fact = [numerator, denominator].map { |n| Prime.prime_division(n).to_h }
103
+
104
+ # cancel out common factors by subtracting exponents
105
+ d_fact.each do |v, d_exp|
106
+ if n_exp = n_fact[v]
107
+ if n_exp < d_exp
108
+ d_fact[v] = d_exp - n_exp
109
+ n_fact[v] = 0
110
+ else
111
+ n_fact[v] = n_exp - d_exp # <= if n_exp == d_exp, this is 0, which covers the 3rd case
112
+ d_fact[v] = 0
113
+ end
114
+ end
115
+ end
116
+
117
+ # multiply the simplified factors back into full numbers
118
+ simp_n, simp_d = [n_fact, d_fact].map { |h| h.map{ |n, exp| n ** exp }.reduce(:*) }
119
+
120
+ Fraction[simp_n, simp_d]
121
+ end
122
+
123
+ end
124
+
125
+ #####################################################################################
126
+ #
127
+ # Fraction(a,b) is a wrapper for Fraction[a,b]
128
+ #
129
+ def Fraction(*args)
130
+ Fraction.new(*args)
131
+ end
@@ -26,7 +26,7 @@ module Hex
26
26
  :default => 7
27
27
  )
28
28
 
29
- def self.dump(data, options={})
29
+ def self.dump(data, **options)
30
30
  base_offset = options[:base_offset] || 0
31
31
  color = options[:color].nil? ? true : options[:color]
32
32
  highlight = options[:highlight]