is-fixed 0.2.0

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.
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: