is-fixed 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/.yardopts +9 -0
  2. data/lib/is/fixed.rb +231 -0
  3. metadata +48 -0
data/.yardopts ADDED
@@ -0,0 +1,9 @@
1
+ --no-cache
2
+ --private
3
+ --protected
4
+ --hide-void-return
5
+ --plugin yard-is-monkey
6
+ --title 'Ruby Gems by Ivan Shikhalev'
7
+ --query="/^@@/ !~ o.name && @api.text != 'ignore'"
8
+ lib/**/*.rb ./*.rb
9
+ - *.md
data/lib/is/fixed.rb ADDED
@@ -0,0 +1,231 @@
1
+ # encoding: utf-8
2
+
3
+ class Fixed < Numeric
4
+
5
+ VERSION = '0.2.0'
6
+
7
+ class << self
8
+
9
+ # @return [Integer]
10
+ attr_accessor :precision
11
+
12
+ def precision= value
13
+ if @precision
14
+ raise 'Already defined.'
15
+ elsif self == Fixed
16
+ raise 'Fixed is an abstract class.'
17
+ else
18
+ @precision = value
19
+ end
20
+ end
21
+
22
+ # @param [Integer] precision
23
+ # @return [Class]
24
+ def subclass precision
25
+ @@classes ||= []
26
+ if ! @@classes[precision]
27
+ @@classes[precision] = Class.new(Fixed)
28
+ @@classes[precision].precision = precision
29
+ end
30
+ @@classes[precision]
31
+ end
32
+
33
+ # @param [Numeric] value
34
+ # @param [Integer] precision
35
+ # @return [Fixed]
36
+ def number value, precision
37
+ subclass(precision).new(value)
38
+ end
39
+
40
+ # @param [Numeric] value
41
+ # @return [Fixed]
42
+ def [] value
43
+ self.new value
44
+ end
45
+
46
+ # @return [String]
47
+ def to_s
48
+ name || "Fixed(#{@precision})"
49
+ end
50
+
51
+ end
52
+
53
+ # @return [Integer]
54
+ attr_reader :precision
55
+
56
+ # @return [Integer]
57
+ attr_reader :number
58
+
59
+ def precision
60
+ self.class.precision
61
+ end
62
+
63
+ # @param [Numeric] number
64
+ # @param [Integer] shift
65
+ def initialize number = 0, shift = nil
66
+ if ! precision
67
+ raise 'Undefined precision.'
68
+ end
69
+ case number
70
+ when Fixed
71
+ np = number.precision + (shift || 0)
72
+ if np = precision
73
+ @number = number.number
74
+ elsif np < precision
75
+ @number = number.number * 10 ** (precision - np)
76
+ else
77
+ nn = number.number.divmod(10 ** (np - precision))
78
+ @number = nn[0] + (nn[1] < 5 && 0 || 1)
79
+ end
80
+ when Integer
81
+ np = (shift || 0)
82
+ if np == precision
83
+ @number = number
84
+ elsif np < precision
85
+ @number = number * 10 ** (precision - np)
86
+ else
87
+ nn = number.divmod(10 ** (np - precision))
88
+ @number = nn[0] + (nn[1] < 5 && 0 || 1)
89
+ end
90
+ else
91
+ np = (shift || 0)
92
+ @number = (Float(number) * Float(10) ** (precision - np)).round
93
+ end
94
+ end
95
+
96
+ # @return [Fixed]
97
+ def +@
98
+ self
99
+ end
100
+
101
+ # @return [Fixed]
102
+ def -@
103
+ self.class.new -@number, precision
104
+ end
105
+
106
+ # @param [Numeric] other
107
+ # @return [Fixed]
108
+ def + other
109
+ other = self.class.new other
110
+ self.class.new @number + other.number, precision
111
+ end
112
+
113
+ # @param [Numeric] other
114
+ # @return [Fixed]
115
+ def - other
116
+ self + (-other)
117
+ end
118
+
119
+ # @param [Numeric] other
120
+ # @return [Fixed]
121
+ def * other
122
+ case other
123
+ when Fixed
124
+ self.class.new @number * other.number, precision + other.precision
125
+ when Integer
126
+ self.class.new @number * other, precision
127
+ else
128
+ self.class.new (Float(other) * @number).round, precision
129
+ end
130
+ end
131
+
132
+ # @param [Numeric] other
133
+ # @return [Fixed]
134
+ def / other
135
+ # /
136
+ case other
137
+ when Fixed
138
+ n = @number * 10 ** other.precision
139
+ nn = n.divmod other.number
140
+ self.class.new nn[0] + (nn[1] < 5 && 0 || 1), precision
141
+ when Integer
142
+ nn = @number.divmod other
143
+ self.class.new nn[0] + (nn[1] < 5 && 0 || 1) / other.number, precision
144
+ else
145
+ self.class.new Float(@number) / Float(other), precision
146
+ end
147
+ end
148
+
149
+ # @param [Numeric] other
150
+ # @return [Fixed]
151
+ def ** other
152
+ case other
153
+ when Integer
154
+ n = self.class.new 1
155
+ if other > 0
156
+ other.times { n = n * self }
157
+ elsif other < 0
158
+ other.times { n = n / self }
159
+ end
160
+ n
161
+ when Fixed
162
+ if other.integer?
163
+ self ** other.to_i
164
+ else
165
+ self ** other.to_f
166
+ end
167
+ else
168
+ self.class.new self.to_f ** Float(other)
169
+ end
170
+ end
171
+
172
+ def integer?
173
+ @number.divmod(10 ** precision)[1] == 0
174
+ end
175
+
176
+ # @return [Integer]
177
+ def to_i
178
+ @number.divmod(10 ** precision)[0]
179
+ end
180
+
181
+ # @return [Float]
182
+ def to_f
183
+ Float(@number) / Float(10 ** precision)
184
+ end
185
+
186
+ # @return [String]
187
+ def to_s
188
+ s = @number.to_s
189
+ l = s.length
190
+ if l <= precision
191
+ s = '0' * (precision - l + 1) + s
192
+ end
193
+ "#{s[0...-precision]}.#{s[-precision..-1]}"
194
+ end
195
+
196
+ def <=> other
197
+ if precision >= other.precision
198
+ @number <=> self.class.new(other).number
199
+ else
200
+ other.class.new(self).number <=> other.number
201
+ end
202
+ end
203
+
204
+ def abs
205
+ self.class.new(@number.abs, precision)
206
+ end
207
+
208
+ def abs2
209
+ self * self
210
+ end
211
+
212
+ def coerce other
213
+ if Integer === other
214
+ [self.class.new(other), self]
215
+ else
216
+ super other
217
+ end
218
+ end
219
+
220
+ protected :precision, :number
221
+
222
+ end
223
+
224
+ # @param [Integer] precision
225
+ # @return [Class]
226
+ def Fixed precision
227
+ Fixed.subclass precision
228
+ end
229
+
230
+ Currency = Fixed(4)
231
+
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: is-fixed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ivan Shikhalev
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-11 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Provides a fixed point numeric class.
15
+ email: shikhalev@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/is/fixed.rb
21
+ - .yardopts
22
+ homepage: https://github.com/shikhalev/gems/
23
+ licenses:
24
+ - GNU LGPL
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: 1.9.2
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 1.8.25
44
+ signing_key:
45
+ specification_version: 3
46
+ summary: Provides a fixed point numeric class
47
+ test_files: []
48
+ has_rdoc: