radix-firstbanco 2.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.
@@ -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
+ ##