radix-firstbanco 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,466 @@
1
+ require 'radix/numeric'
2
+
3
+ module Radix
4
+
5
+ ##
6
+ # Advanced integer class for Radix conversions and mathematical operations
7
+ # with other bases.
8
+ #
9
+ # @!attribute [r] value
10
+ # @return [Fixnum] Integer's decimal value.
11
+ # @!attribute [r] base
12
+ # @return [Fixnum] The base level of Integer instance.
13
+ # @!attribute [r] code
14
+ # @return [Array<String>, nil] Substitution chars or nil if default.
15
+ class Integer < Numeric
16
+
17
+ ##
18
+ # Stores the numeric value as normal number.
19
+ #
20
+ # @return [Fixnum] Integer's decimal value.
21
+ attr :value
22
+
23
+ ##
24
+ # Base of the number.
25
+ #
26
+ # @return [Fixnum] The base level of Integer instance.
27
+ attr :base
28
+
29
+ ##
30
+ # Base encoding table.
31
+ #
32
+ # @return [Array<String>, nil] Substitution chars or nil if default.
33
+ attr :code
34
+
35
+ private
36
+
37
+ ##
38
+ # Starts a new instance of the Radix::Integer class
39
+ #
40
+ # @param [Radix::Numeric, Numeric, Array, String] value
41
+ # The value of the new integer in context of base.
42
+ #
43
+ # @param [Fixnum, Array<String>] base The base context in which value is
44
+ # determined. Can be an array of characters to use in place of default.
45
+ #
46
+ # @return [void]
47
+ def initialize(value, base=10)
48
+ @value = parse_value(value, base)
49
+ @base, @code = parse_base(base)
50
+ end
51
+
52
+ ##
53
+ # Takes a Radix::Numeric, String or array and returns the decimal value for
54
+ # storage in @value.
55
+ #
56
+ # @param [Radix::Numeric, Numeric, String, Array<Numeric, String>] value
57
+ # The value of the integer in base context.
58
+ #
59
+ # @param [Fixnum, Array<String>] base
60
+ # The context base of value.
61
+ #
62
+ # @return [Fixnum] Decimal value of Integer.
63
+ def parse_value(value, base)
64
+ case value
65
+ when Integer, Float # Radix
66
+ parse_numeric(value.to_i, base)
67
+ when ::Array
68
+ parse_array(value, base)
69
+ when ::String
70
+ parse_string(value, base)
71
+ when ::Numeric
72
+ parse_numeric(value, base)
73
+ end
74
+ end
75
+
76
+ ##
77
+ # Take an Array in the form of [..., d2, d1, d0] and convert it to
78
+ # base ten, and store in @value.
79
+ #
80
+ # @note If a float style array is passed in for +value+, e.g. [9, '.', 5],
81
+ # the fractional part will simply be truncated.
82
+ #
83
+ # @param [Array<String, Numeric>] value Given value.
84
+ #
85
+ # @param [Fixnum, Array<String>] base Desired base.
86
+ #
87
+ # @return [Fixnum] Decimal version of array value in base context.
88
+ def parse_array(value, base)
89
+ if i = value.index(DOT)
90
+ value = [0...i]
91
+ end
92
+ super(value, base)
93
+ end
94
+
95
+ ## digits << #Radix.convert(d, base, 10).to_i
96
+
97
+ public
98
+
99
+
100
+ ##
101
+ # Makes this Radix::Integer a ruby integer.
102
+ #
103
+ # @return [Fixnum] Base(10) value.
104
+ def to_i
105
+ value.to_i #(sign + convert(10).digits.join('')).to_i
106
+ end
107
+
108
+ alias :to_int :to_i
109
+
110
+ ##
111
+ # Makes this Radix::Integer a ruby float.
112
+ #
113
+ # @return [Float] Base(10) value as float.
114
+ def to_f
115
+ value.to_f #(sign + convert(10).digits.join('')).to_f
116
+ end
117
+
118
+ ##
119
+ # Makes this Radix::Integer an array using code if defined. Returns an
120
+ # array using default chars otherwise.
121
+ #
122
+ # @param [Fixnum] base Desired base.
123
+ #
124
+ # @return [Array<Fixnum, String>] Current base encoded array.
125
+ def to_a(base=nil)
126
+ if base
127
+ convert(base).digits_encoded
128
+ else
129
+ digits_encoded
130
+ end
131
+ end
132
+
133
+ ##
134
+ # Creates an encoded string in desired base, with desired digit divider.
135
+ #
136
+ # @note For base 10 or less does not use a divider unless specified.
137
+ #
138
+ # @param [Fixnum, Array<String>] base
139
+ # Desired base.
140
+ #
141
+ # @param [String] divider
142
+ # Desired divider character(s).
143
+ #
144
+ # @return [String] Encoded string with specified divider.
145
+ def to_s(base=nil, divider=nil)
146
+ divider = divider.to_s if divider
147
+ if base
148
+ convert(base).to_s(nil, divider)
149
+ else
150
+ if code
151
+ digits_encoded.join(divider)
152
+ else
153
+ if @base > 10
154
+ digits.join(divider || DIVIDER)
155
+ else
156
+ digits.join(divider)
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ ##
163
+ # Creates a string representation of self.
164
+ #
165
+ # @return [String] String rep of self.digits and @base.
166
+ def inspect
167
+ "#{digits.join(' ')} (#{base})"
168
+ end
169
+
170
+ ##
171
+ # Returns an array representation of each column's value in decimal chars.
172
+ #
173
+ # @return [Array<String, Fixnum>] Values per column of @base as array.
174
+ # Prepended with "-" if negative.
175
+ def digits
176
+ i = base_conversion(value, base)
177
+ i.unshift('-') if negative?
178
+ i
179
+ end
180
+
181
+ ##
182
+ # Returns the encoded version of digits.
183
+ #
184
+ # @return [Array<String>] The encoded digits. Or digits if @code exists.
185
+ def digits_encoded
186
+ base_encode(digits)
187
+ end
188
+
189
+ ##
190
+ # Returns true if the number is negative.
191
+ #
192
+ # @return [Boolean] True if negative.
193
+ def negative?
194
+ value < 0
195
+ end
196
+
197
+ ##
198
+ # Converts Integer to a new base.
199
+ #
200
+ # @param [Fixnum, Array<String>] base
201
+ # The base context in which value is determined. Can be an array
202
+ # of characters to use in place of default.
203
+ #
204
+ # @return [Radix:Integer] New Integer of same value, different base.
205
+ def convert(base)
206
+ self.class.new(value, base)
207
+ #new_digits = Radix::Base.convert_base(digits, base, new_base)
208
+ #self.class.new(new_digits, new_base)
209
+ end
210
+
211
+ ##
212
+ # Addition binary operation.
213
+ #
214
+ # @param [#to_i] other
215
+ #
216
+ # @example Which operand determines the base?
217
+ # > i = Radix::Integer.new(123,16)
218
+ # 7 11 (16)
219
+ # > i2 = Radix::Integer.new(456,10)
220
+ # 4 5 6 (10)
221
+ # > i + i2 # i is base 16 and is first operand
222
+ # 2 4 3 (16) # so base of return is 16
223
+ # > i2 + i # i2 is base 10 and is first operand
224
+ # 5 7 9 (10) # so base of return is 10
225
+ #
226
+ # @return [Radix::Integer] Result of arithmetic operation.
227
+ def +(other)
228
+ operation(:+, other)
229
+ end
230
+
231
+ ##
232
+ # Subtraction binary operation.
233
+ #
234
+ # @param [#to_i] other
235
+ #
236
+ # @return [Radix::Integer] Result of arithmetic operation.
237
+ def -(other)
238
+ operation(:-, other)
239
+ end
240
+
241
+ ##
242
+ # Multiplication binary operation.
243
+ #
244
+ # @param [#to_i] other
245
+ #
246
+ # @return [Radix::Integer] Result of arithmetic operation.
247
+ def *(other)
248
+ operation(:*, other)
249
+ end
250
+
251
+ ##
252
+ # Division binary operation.
253
+ #
254
+ # @param [#to_i] other
255
+ #
256
+ # @return [Radix::Integer] Result of arithmetic operation.
257
+ def /(other)
258
+ operation(:/, other)
259
+ end
260
+
261
+ ##
262
+ # Power, exponentional operation.
263
+ #
264
+ # @param [#to_i] other
265
+ # The exponent by which to raise Integer.
266
+ #
267
+ # @return [Radix::Integer] Result of exponential operation.
268
+ def **(other)
269
+ operation(:**, other)
270
+ end
271
+
272
+ ##
273
+ # Modulo binary operation.
274
+ #
275
+ # @param [#to_i] other
276
+ #
277
+ # @return [Radix::Integer] Modulo result of division operation.
278
+ def %(other)
279
+ operation(:%, other)
280
+ end
281
+
282
+ ##
283
+ # Leftwise bit shift operator.
284
+ #
285
+ # @note Negative numbers will shift rightward. This will truncate bytes
286
+ # that get carried past zero.
287
+ #
288
+ # @param [#to_int] integer
289
+ # The number of places to shift the bits of self.
290
+ #
291
+ # @return [Radix::Integer] The new Radix::Integer with shifted bits.
292
+ def <<(integer)
293
+ Radix::Integer.new(to_int << integer.to_int, base)
294
+ end
295
+
296
+ ##
297
+ # AND bitwise operator
298
+ #
299
+ # @param [#to_int] integer
300
+ #
301
+ # @return [Radix::Integer] The logical AND.
302
+ def &(integer)
303
+ Radix::Integer.new(to_int & integer.to_int, base)
304
+ end
305
+
306
+ ##
307
+ # Returns the absolute value of self in @base.
308
+ #
309
+ # @return [Radix::Integer] Absolute of @value.
310
+ def abs
311
+ self.class.new(value.abs, base)
312
+ end
313
+
314
+ ##
315
+ # Strict equality requires same class as well as value.
316
+ #
317
+ # @param [Object] num
318
+ # Object to compare.
319
+ #
320
+ # @return [Boolean] True if class and value are equal.
321
+ def eql?(num)
322
+ self.class.equal?(num.class) && self == num
323
+ end
324
+
325
+ ##
326
+ # Simple equality requires equal values only.
327
+ # @todo Handle Float and Radix::Float.
328
+ #
329
+ # @param [#value] other
330
+ # Any object that responds to value.
331
+ #
332
+ # @return [Boolean] True if values are equal.
333
+ def ==(other)
334
+ case other
335
+ when Float, Integer # Radix
336
+ value == other.value
337
+ else
338
+ value == other
339
+ end
340
+ end
341
+
342
+ ##
343
+ # Comparitive binary operation. Very useful for sorting methods.
344
+ #
345
+ # @param [#to_f] other The object to compare value against.
346
+ #
347
+ # @example Comparison testing
348
+ # > lower = Radix::Integer.new(123,10)
349
+ # 1 2 3 (10)
350
+ # > higher = Radix::Integer.new(456, 16)
351
+ # 1 12 8 (16)
352
+ # > lower <=> higher
353
+ # -1
354
+ # > lower <=> 123
355
+ # 0
356
+ # > higher <=> lower
357
+ # 1
358
+ #
359
+ # @return [Fixnum] Returns -1 for less than, 0 for equal or 1 for more than.
360
+ def <=>(other)
361
+ value <=> other.to_f # to_num
362
+ end
363
+
364
+ ##
365
+ # Create a new Radix::Integer from value in Base-10
366
+ #
367
+ # @return [Array<Radix::Integer>] An array of the new Integer object and
368
+ # self.
369
+ def coerce(value)
370
+ [Radix::Integer.new(value), self]
371
+ end
372
+
373
+ private
374
+
375
+ ##
376
+ # Perform passed arithmetic operation.
377
+ #
378
+ # @param [#to_i] other
379
+ #
380
+ # @example Which operand determines the base?
381
+ # > i = Radix::Integer.new(123,16)
382
+ # 7 11 (16)
383
+ # > i2 = Radix::Integer.new(456,10)
384
+ # 4 5 6 (10)
385
+ # > i + i2 # i is base 16 and is first operand
386
+ # 2 4 3 (16) # so base of return is 16
387
+ # > i2 + i # i2 is base 10 and is first operand
388
+ # 5 7 9 (10) # so base of return is 10
389
+ #
390
+ # @return [Radix::Integer] Result of binary operation in @base.
391
+ def operation(op, other)
392
+ a = self.to_i
393
+ b = other.to_i
394
+ x = a.__send__(op, b)
395
+ self.class.new(x, base)
396
+ end
397
+
398
+ ##
399
+ # Returns the value as an array of decimal values where each column is a
400
+ # place of @base.
401
+ #
402
+ # @param (see #Radix::Integer.value)
403
+ # @param (see #Radix::Integer.base)
404
+ #
405
+ # @return [Array<Fixnum>]
406
+ def base_conversion(value, base)
407
+ #if value < 0
408
+ # @negative, value = true, value.abs
409
+ #end
410
+ i = value.abs
411
+
412
+ a = []
413
+ while i > 0
414
+ i, r = i.divmod(base)
415
+ a << r
416
+ end
417
+
418
+ # if nothing add zero
419
+ a << 0 if a.empty?
420
+
421
+ a.reverse
422
+ end
423
+
424
+ end
425
+
426
+ end
427
+
428
+ ### Want to see the hard way to do addition?
429
+ ##
430
+ ## def +(other)
431
+ ## other = convert_other(other)
432
+ ##
433
+ ## result = []
434
+ ## index = -1
435
+ ## carry = 0
436
+ ##
437
+ ## x1 = self.digits[index]
438
+ ## x2 = other.digits[index]
439
+ ## while x1 or x2
440
+ ## r = (x1||0) + (x2||0) + carry
441
+ ## if r >= base
442
+ ## result.unshift(r - base)
443
+ ## carry = 1
444
+ ## else
445
+ ## result.unshift(r)
446
+ ## carry = 0
447
+ ## end
448
+ ## index -= 1
449
+ ## x1 = self.digits[index]
450
+ ## x2 = other.digits[index]
451
+ ## end
452
+ ## result << carry if carry != 0
453
+ ## Radix::Integer.new(result, base)
454
+ ## end
455
+ ##
456
+ ## def convert_other(other)
457
+ ## case other
458
+ ## when Radix::Integer
459
+ ## other.convert(base)
460
+ ## when Integer
461
+ ## Radix::Integer.new(other, base)
462
+ ## when String, Array
463
+ ## Radix::Integer.new(other, base)
464
+ ## end
465
+ ## end
466
+ ##