ruby-calc 0.1.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,6 @@
1
+ require "forwardable"
2
+
3
+ module Kernel
4
+ extend Forwardable
5
+ def_delegators Calc, *Calc::ALL_BUILTINS
6
+ end
@@ -0,0 +1,208 @@
1
+ module Calc
2
+ class Numeric
3
+ # Modulo operator
4
+ #
5
+ # x % y is equivalent to x.mod(y). Rounding mode is determined by
6
+ # Calc.config(:mod).
7
+ #
8
+ # @param y [Integer]
9
+ # @return [Calc::Numeric]
10
+ # @example
11
+ # Calc::Q(11).mod(5) #=> Calc::Q(1)
12
+ # Calc::C(11, 11).mod(5) #=> Calc::C(1+1i)
13
+ def %(other)
14
+ mod other
15
+ end
16
+
17
+ # Unary plus. Returns the receiver's value.
18
+ #
19
+ # @return [Calc::Numeric]
20
+ # @example
21
+ # +Calc::C(1,1) #=> Calc::C(1,1)
22
+ # +Calc::Q(1) #=> Calc::Q(1)
23
+ def +@
24
+ self
25
+ end
26
+
27
+ # Returns the square of the absolute value
28
+ #
29
+ # This method exists for compatibility with ruby Complex/Numeric.
30
+ #
31
+ # @return [Calc::C,Calc::Q]
32
+ # @example
33
+ # Calc::Q(5).abs2 #=> Calc::Q(25)
34
+ # Calc::C(3, -4).abs2 #=> Calc:c::Q(25)
35
+ def abs2
36
+ abs * abs
37
+ end
38
+
39
+ # Ceiling
40
+ #
41
+ # For real self, returns the least integer not less than self.
42
+ #
43
+ # For complex self, returns a complex number composed of the ceiling
44
+ # of the real and imaginary parts separately.
45
+ #
46
+ # @return [Calc::Q,Calc::C]
47
+ # @example
48
+ # Calc::Q(1.23).ceil #=> Calc::Q(2)
49
+ # Calc::C(7.8, 9.1).ceil #=> Calc::C(8+10i)
50
+ def ceil
51
+ appr(1, 1)
52
+ end
53
+
54
+ # Division
55
+ #
56
+ # This method exists for ruby compatibility. Note that Fixnum#fdiv will
57
+ # return a Float, however Q#div returns another Q.
58
+ #
59
+ # @param y [Numeric]
60
+ # @return [Calc::C,Calc::Q]
61
+ # @raise [Calc::MathError] if y is 0
62
+ # @example
63
+ # Calc::Q(2, 3).fdiv(0.5) #=> Calc::Q(~1.33333333333333333333)
64
+ # Calc::C(11, 22).fdiv(3) #=> Calc::C(~3.66666666666666666667+~7.33333333333333333333i)
65
+ def fdiv(y)
66
+ self / y
67
+ end
68
+
69
+ # Floor
70
+ #
71
+ # For real self, returns the greatest integer not greater than self.
72
+ #
73
+ # For complex self, returns a complex number composed of the floor of the
74
+ # real and imaginary parts separately.
75
+ #
76
+ # @return [Calc::Q,Calc::C]
77
+ # @example
78
+ # Calc::Q(1.23).floor #=> Calc::Q(1)
79
+ # Calc::C(7.8, 9.1).floor #=> Calc::C(7+9i)
80
+ def floor
81
+ appr(1, 0)
82
+ end
83
+
84
+ # Floor of logarithm to base 10
85
+ #
86
+ # Returns the greatest integer n for which 10^n <= self.
87
+ #
88
+ # @return [Calc::Q]
89
+ # @raise [Calc::MathError] if self is zero
90
+ # @example
91
+ # Calc::Q("1/15").ilog10 #=> Calc::Q(-2)
92
+ # Calc::Q(777).ilog10 #=> Calc::Q(2)
93
+ # Calc::C(10, 10).ilog10 #=> Calc::Q(1)
94
+ def ilog10
95
+ ilog 10
96
+ end
97
+
98
+ # Floor of logarithm to base 2
99
+ #
100
+ # Returns the greatest integer n for which 2^n <= self
101
+ #
102
+ # @return [Calc::Q]
103
+ # @raise [Calc::MathError] if self is zero
104
+ # @example
105
+ # Calc::Q("1/15").ilog2 #=> Calc::Q(-4)
106
+ # Calc::Q(777).ilog2 #=> Calc::Q(9)
107
+ # Calc::C(10, 10).ilog2 #=> Calc::Q(3)
108
+ def ilog2
109
+ ilog 2
110
+ end
111
+
112
+ # Returns 1 if self is an integer, otherwise 0.
113
+ #
114
+ # @return [Calc::Q]
115
+ # @example
116
+ # Calc::Q(1).isint #=> Calc::Q(1)
117
+ # Calc::Q(0.5).isint #=> Calc::Q(0)
118
+ def isint
119
+ int? ? Q::ONE : Q::ZERO
120
+ end
121
+
122
+ # Base 2 logarithm
123
+ #
124
+ # @return [Calc::Q]
125
+ # @example
126
+ # Calc::Q(1).log2 #=> Calc::Q(0)
127
+ # Calc::Q(2).log2 #=> Calc::Q(1)
128
+ # Calc::Q(10).log2 #=> Calc::Q(~3.32192809488736234786)
129
+ # Calc::Q(-2).log2 #=> Calc::C(1+~4.53236014182719380961i)
130
+ # Calc::C(1, 2).log2 #=> Calc::C(~1.16096404744368117393+~1.59727796468810880664i)
131
+ def log2(*args)
132
+ ln(*args) / Q::TWO.ln(*args)
133
+ end
134
+
135
+ # least-absol;ute-value residues modulo a specified number
136
+ #
137
+ # x.mmin(md) is equivalent to x.mod(md, 16)
138
+ #
139
+ # @param md [Numeric]
140
+ # @return [Calc::Numeric]
141
+ # @example
142
+ # Calc::Q(3).mmin(6) #=> Calc::Q(3)
143
+ # Calc::C(0, 3).mmin(6) #=> Calc::C(3i)
144
+ def mmin(md)
145
+ mod md, 16
146
+ end
147
+
148
+ # Returns true if the number is not zero. For complex `self`, this means
149
+ # that either the real or imaginary parts are not zero.
150
+ #
151
+ # @return [Boolean]
152
+ # @example
153
+ # Calc::Q(0).nonzero? #=> false
154
+ # Calc::Q(1).nonzero? #=> true
155
+ # Calc::C(0, 0).nonzero? #=> false
156
+ # Calc::C(1, 0).nonzero? #=> true
157
+ # Calc::C(0, 1).nonzero? #=> true
158
+ def nonzero?
159
+ !zero?
160
+ end
161
+
162
+ # Returns an array containing the absolute value and the argument (angle).
163
+ # This method exists for compatiblity with ruby's Numeric class.
164
+ #
165
+ # Note that: Calc.polar(a, b).polar == [a, b]
166
+ #
167
+ # @return [Array]
168
+ # @example
169
+ # Calc::Q(2).polar #=> [Calc::Q(2), Calc::Q(0)]
170
+ # Calc::C(1, 2).polar #=> [Calc::Q(2.23606797749978969641), Calc::Q(1.10714871779409050302)]
171
+ # Calc.polar(1, 2).polar #=> [Calc::Q(1), Calc::Q(2)]
172
+ def polar
173
+ [abs, arg]
174
+ end
175
+
176
+ # Rerurns an array containing the real and imaginary parts as elements.
177
+ # This method exists for compatibility with ruby's Numeric class.
178
+ #
179
+ # @return [Array]
180
+ # @example
181
+ # Calc::Q(2).rectangular #=> [Calc::Q(2), Calc::Q(0)]
182
+ # Calc::C(1, 2).rectangular #=> [Calc::Q(1), Calc::Q(2)]
183
+ def rectangular
184
+ [re, im]
185
+ end
186
+ alias rect rectangular
187
+
188
+ # Invokes the child class's `to_i` method to convert self to an integer.
189
+ #
190
+ # Note that the return value is a ruby Fixnum or Bignum. If you want to
191
+ # convert to an integer but have the result be a `Calc::Q` object, use
192
+ # `trunc` or `round`.
193
+ #
194
+ # @return [Fixnum,Bignum]
195
+ # @raise [RangeError] if self is complex with non-zero imaginary part
196
+ # @example
197
+ # Calc::Q("5/2").to_int #=> 2
198
+ # Calc::C(2, 0).to_int #=> 2
199
+ def to_int
200
+ to_i
201
+ end
202
+
203
+ # Provides support for Ruby type coercion.
204
+ def coerce(other)
205
+ [self.class.new(other), self]
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,628 @@
1
+ module Calc
2
+ class Q
3
+ NEGONE = new(-1)
4
+ ZERO = new(0)
5
+ ONE = new(1)
6
+ TWO = new(2)
7
+
8
+ def **(other)
9
+ power(other)
10
+ end
11
+
12
+ # Inverse gudermannian function
13
+ #
14
+ # @param eps [Calc::Q] (optional) calculation accuracy
15
+ # @return [Calc::Q,Calc::C]
16
+ # @example
17
+ # Calc::Q(1).agd #=> Calc::Q(1.22619117088351707081)
18
+ # Calc::Q(2).agd #=> Calc::C(1.5234524435626735209-3.14159265358979323846i)
19
+ def agd(*args)
20
+ r = Calc::C(self).agd(*args)
21
+ r.real? ? r.re : r
22
+ end
23
+
24
+ # Returns the argument (the angle or phase) of a complex number in radians
25
+ #
26
+ # This method is used by non-complex classes, it will be 0 for positive
27
+ # values, pi() otherwise.
28
+ #
29
+ # @param eps [Calc::Q] (optional) calculation accuracy
30
+ # @return [Calc::Q]
31
+ # @example
32
+ # Calc::Q(-1).arg #=> Calc::Q(3.14159265358979323846)
33
+ # Calc::Q(1).arg #=> Calc::Q(0)
34
+ def arg(*args)
35
+ if self < 0
36
+ Calc.pi(*args)
37
+ else
38
+ ZERO
39
+ end
40
+ end
41
+ alias angle arg
42
+ alias phase arg
43
+
44
+ # Returns 1 if binary bit y is set in self, otherwise 0.
45
+ #
46
+ # @param y [Numeric] bit position
47
+ # @return [Calc::Q]
48
+ # @example
49
+ # Calc::Q(9).bit(0) #=> Calc::Q(1)
50
+ # Calc::Q(9).bit(1) #=> Calc::Q(0)
51
+ # @see bit?
52
+ def bit(y)
53
+ bit?(y) ? ONE : ZERO
54
+ end
55
+ alias [] bit
56
+
57
+ # Returns the number of bits in the integer part of `self`
58
+ #
59
+ # Note that this is compatible with ruby's Fixnum#bit_length. Libcalc
60
+ # provides a similar function called `highbit` with different semantics.
61
+ #
62
+ # This returns the bit position of the highest bit which is different to
63
+ # the sign bit. If there is no such bit (zero or -1), zero is returned.
64
+ #
65
+ # @return [Calc::Q]
66
+ # @example
67
+ # Calc::Q(0xff).bit_length #=> Calc::Q(8)
68
+ def bit_length
69
+ (negative? ? -self : self + ONE).log2.ceil
70
+ end
71
+
72
+ # Returns a string containing the character corresponding to a value
73
+ #
74
+ # Note that this is for compatibility with calc, normally in ruby you
75
+ # should just #chr
76
+ #
77
+ # @return [String]
78
+ # @example
79
+ # Calc::Q(88).char #=> "X"
80
+ def char
81
+ raise MathError, "Non-integer for char" unless int?
82
+ raise MathError, "Out of range for char" unless between?(0, 255)
83
+ if zero?
84
+ ""
85
+ else
86
+ to_i.chr
87
+ end
88
+ end
89
+
90
+ # Returns a string containing the character represented by `self` value
91
+ # according to encoding.
92
+ #
93
+ # Unlike the calc version (`char`), this allows numbers greater than 255
94
+ # if an encoding is specified.
95
+ #
96
+ # @return [String]
97
+ # @param encoding [Encoding]
98
+ # @example
99
+ # Calc::Q(88).chr #=> "X"
100
+ # Calc::Q(300).chr(Encoding::UTF_8) #=> Unicode I-breve
101
+ def chr(*args)
102
+ to_i.chr(*args)
103
+ end
104
+
105
+ # Complex conjugate
106
+ #
107
+ # As the conjugate of real x is x, this method returns self.
108
+ #
109
+ # @return [Calc::Q]
110
+ # @example
111
+ # Calc::Q(3).conj #=> 3
112
+ def conj
113
+ self
114
+ end
115
+ alias conjugate conj
116
+
117
+ # Ruby compatible integer division
118
+ #
119
+ # Calls `quo` to get the quotient of integer division, with rounding mode
120
+ # which specifies behaviour compatible with ruby's Numeric#div
121
+ #
122
+ # @param y [Numeric]
123
+ # @example
124
+ # Calc::Q(13).div(4) #=> Calc::Q(3)
125
+ # Calc::Q("11.5").div(4) #=> Calc::Q(2)
126
+ # @see Calc::Q#quo
127
+ def div(y)
128
+ quo(y, ZERO)
129
+ end
130
+
131
+ # Ruby compatible quotient/modulus
132
+ #
133
+ # Returns an array containing the quotient and modulus by dividing `self`
134
+ # by `y`. Rounding is compatible with the ruby method `Numeric#divmod`.
135
+ #
136
+ # Unlike `quomod`, this is not affected by `Calc.config(:quomod)`.
137
+ #
138
+ # @param y [Numeric]
139
+ # @example
140
+ # Calc::Q(11).divmod(3) #=> [Calc::Q(3), Calc::Q(2)]
141
+ # Calc::Q(11).divmod(-3) #=> [Calc::Q(-4), Calc::Q(-1)]
142
+ def divmod(y)
143
+ quomod(y, ZERO)
144
+ end
145
+
146
+ # Iterates the given block, yielding values from `self` decreasing by 1
147
+ # down to and including `limit`
148
+ #
149
+ # x.downto(limit) is equivalent to x.step(by: -1, to: limit)
150
+ #
151
+ # If no block is given, an Enumerator is returned instead.
152
+ #
153
+ # @return [Enumerator,nil]
154
+ # @param limit [Numeric] lowest value to return
155
+ # @example
156
+ # Calc::Q(10).downto(5) { |i| print i, " " } #=> 10 9 8 7 6 5
157
+ def downto(limit, &block)
158
+ step(limit, NEGONE, &block)
159
+ end
160
+
161
+ # Returns a string which if evaluated creates a new object with the original value
162
+ #
163
+ # @return [String]
164
+ # @example
165
+ # Calc::Q(0.5).estr #=> "Calc::Q(1,2)"
166
+ def estr
167
+ s = self.class.name
168
+ s << "("
169
+ s << (int? ? num.to_s : "#{ num },#{ den }")
170
+ s << ")"
171
+ s
172
+ end
173
+
174
+ # Returns an array; [gcd, lcm]
175
+ #
176
+ # This method exists for compatibility with ruby's Integer class, however
177
+ # note that the libcalc version works on rational numbers and the lcm can
178
+ # be negative. You can also pass more than one value.
179
+ #
180
+ # @return [Array]
181
+ # @example
182
+ # Calc::Q(2).gcdlcm(2) #=> [Calc::Q(2), Calc::Q(2)]
183
+ # Calc::Q(3).gcdlcm(-7) #=> [Calc::Q(1), Calc::Q(-21)]
184
+ def gcdlcm(*args)
185
+ [gcd(*args), lcm(*args)]
186
+ end
187
+
188
+ # Gudermannian function
189
+ #
190
+ # @param eps [Calc::Q] (optional) calculation accuracy
191
+ # @return [Calc::Q]
192
+ # @example
193
+ # Calc::Q(1).gd #=> Calc::Q(0.86576948323965862429)
194
+ def gd(*args)
195
+ r = Calc::C(self).gd(*args)
196
+ r.real? ? r.re : r
197
+ end
198
+
199
+ # Returns the corresponding imaginary number
200
+ #
201
+ # @return [Calc::C]
202
+ # @example
203
+ # Calc::Q(1).i #=> Calc::C(1i)
204
+ def i
205
+ Calc::C(ZERO, self)
206
+ end
207
+
208
+ def im
209
+ ZERO
210
+ end
211
+ alias imaginary im
212
+
213
+ # Returns true if the number is imaginary. Instances of this class always
214
+ # return false.
215
+ #
216
+ # @return [Boolean]
217
+ # @example
218
+ # Calc::Q(1).imag? #=> false
219
+ def imag?
220
+ false
221
+ end
222
+
223
+ def inspect
224
+ "Calc::Q(#{ self })"
225
+ end
226
+
227
+ def iseven
228
+ even? ? ONE : ZERO
229
+ end
230
+
231
+ # Returns 1 if the number is imaginary, otherwise returns 0. Instance of
232
+ # this class always return 0.
233
+ #
234
+ # @return [Calc::Q]
235
+ # @example
236
+ # Calc::Q(1).isimag #=> Calc::Q(0)
237
+ def isimag
238
+ ZERO
239
+ end
240
+
241
+ # Returns 1 if self exactly divides y, otherwise return 0.
242
+ #
243
+ # @return [Calc::Q]
244
+ # @example
245
+ # Calc::Q(6).ismult(2) #=> Calc::Q(1)
246
+ # Calc::Q(2).ismult(6) #=> Calc::Q(0)
247
+ # @see Calc::Q#mult?
248
+ def ismult(y)
249
+ mult?(y) ? ONE : ZERO
250
+ end
251
+
252
+ def isodd
253
+ odd? ? ONE : ZERO
254
+ end
255
+
256
+ # Returns 1 if self is prime, 0 if it is not prime. This function can't
257
+ # be used for odd numbers > 2^32.
258
+ #
259
+ # @return [Calc::Q]
260
+ # @raise [Calc::MathError] if self is odd and > 2^32
261
+ # @example
262
+ # Calc::Q(2**31 - 9).isprime #=> Calc::Q(0)
263
+ # Calc::Q(2**31 - 1).isprime #=> Calc::Q(1)
264
+ def isprime
265
+ prime? ? ONE : ZERO
266
+ end
267
+
268
+ # Returns 1 if this number has zero imaginary part, otherwise returns 0.
269
+ # Instances of this class always return 1.
270
+ #
271
+ # @return [Calc::Q]
272
+ # @example
273
+ # Calc::Q(1).isreal #=> Calc::Q(1)
274
+ def isreal
275
+ ONE
276
+ end
277
+
278
+ # Returns 1 if both values are relatively prime
279
+ #
280
+ # @param other [Integer]
281
+ # @return [Calc::Q]
282
+ # @raise [Calc::MathError] if either values are non-integers
283
+ # @example
284
+ # Calc::Q(6).isrel(5) #=> Calc::Q(1)
285
+ # Calc::Q(6).isrel(2) #=> Calc::Q(0)
286
+ # @see Calc::Q#rel?
287
+ def isrel(y)
288
+ rel?(y) ? ONE : ZERO
289
+ end
290
+
291
+ # Returns 1 if this value is a square
292
+ #
293
+ # @return [Calc::Q]
294
+ # @example
295
+ # Calc::Q(25).issq #=> Calc::Q(1)
296
+ # Calc::Q(3).issq #=> Calc::Q(0)
297
+ # Calc::Q("4/25").issq #=> Calc::Q(1)
298
+ # @see Calc::Q#sq?
299
+ def issq
300
+ sq? ? ONE : ZERO
301
+ end
302
+
303
+ # test for equaility modulo a specific number
304
+ #
305
+ # Returns 1 if self is congruent to y modulo md, otherwise 0.
306
+ #
307
+ # @param y [Numeric]
308
+ # @param md [Numeric]
309
+ # @return [Calc::Q]
310
+ # @example
311
+ # Calc::Q(5).meq(33, 7) #=> Calc::Q(1)
312
+ # Calc::Q(5).meq(32, 7) #=> Calc::Q(0)
313
+ # @see Calc::Q#meq?
314
+ def meq(y, md)
315
+ meq?(y, md) ? ONE : ZERO
316
+ end
317
+
318
+ # test for inequality modulo a specific number
319
+ #
320
+ # Reurns 1 if self is not congruent to y modulo md, otherwise 0.
321
+ # This is the opposite of #meq.
322
+ #
323
+ # @param y [Numeric]
324
+ # @param md [Numeric]
325
+ # @return [Calc::Q]
326
+ # @example
327
+ # Calc::Q(5).mne(33, 7) #=> Calc::Q(0)
328
+ # Calc::Q(5).mne(32, 7) #=> Calc::Q(1)
329
+ # @see Calc::Q#mne?
330
+ def mne(y, md)
331
+ meq?(y, md) ? ZERO : ONE
332
+ end
333
+
334
+ # test for inequality modulo a specific number
335
+ #
336
+ # Returns true of self is not congruent to y modulo md.
337
+ # This is the opposiute of #meq?.
338
+ #
339
+ # @param y [Numeric]
340
+ # @param md [Numeric]
341
+ # @return [Boolean]
342
+ # @example
343
+ # Calc::Q(5).mne?(33, 7) #=> false
344
+ # Calc::Q(5).mne?(32, 6) #=> true
345
+ def mne?(y, md)
346
+ !meq?(y, md)
347
+ end
348
+
349
+ # Ruby compatible modulus
350
+ #
351
+ # Returns the modulus of `self` divided by `y`.
352
+ #
353
+ # Rounding is compatible with the ruby method Numeric#modulo. Unlike
354
+ # `mod`, this is not affected by `Calc.confg(:mod)`.
355
+ #
356
+ # @param y [Numeric]
357
+ # @example
358
+ # Calc::Q(13).modulo(4) #=> Calc::Q(1)
359
+ # Calc::Q(13).modulo(-4) #=> Calc::Q(-3)
360
+ def modulo(y)
361
+ mod(y, ZERO)
362
+ end
363
+
364
+ # Return true if `self` is less than zero.
365
+ #
366
+ # This method exists for ruby Fixnum/Rational compatibility
367
+ #
368
+ # @return [Boolean]
369
+ # @example
370
+ # Calc::Q(-1).negative? #=> true
371
+ # Calc::Q(0).negative? #=> false
372
+ # Calc::Q(1).negative? #=> false
373
+ def negative?
374
+ self < ZERO
375
+ end
376
+
377
+ # Returns self.
378
+ #
379
+ # This method is for ruby Integer compatibility
380
+ #
381
+ # @return [Calc::Q]
382
+ def ord
383
+ self
384
+ end
385
+
386
+ # Return true if `self` is greater than zero.
387
+ #
388
+ # This method exists for ruby Fixnum/Rational compatibility
389
+ #
390
+ # @return [Boolean]
391
+ # @example
392
+ # Calc::Q(-1).positive? #=> false
393
+ # Calc::Q(0).positive? #=> false
394
+ # Calc::Q(1).positive? #=> true
395
+ def positive?
396
+ self > ZERO
397
+ end
398
+
399
+ # Returns one less than self.
400
+ #
401
+ # This method exists for ruby Fixnum/Integer compatibility.
402
+ #
403
+ # @return [Calc::Q]
404
+ # @example
405
+ # Calc::Q(1).pred #=> Calc::Q(0)
406
+ def pred
407
+ self - ONE
408
+ end
409
+
410
+ # Probabilistic primacy test
411
+ #
412
+ # Returns 1 if ptest? would have returned true, otherwise 0.
413
+ #
414
+ # @param count [Integer]
415
+ # @param skip [Integer]
416
+ # @return [Calc::Q]
417
+ # @see Calc::Q#ptest?
418
+ def ptest(*args)
419
+ ptest?(*args) ? ONE : ZERO
420
+ end
421
+
422
+ # Returns a simpler approximation of the value if the optional argument eps
423
+ # is given (rat-|eps| <= result <= rat+|eps|), self otherwise.
424
+ #
425
+ # Note that this method exists for ruby Numeric compatibility. Libcalc has
426
+ # an alternative approximation method with different semantics, see `appr`.
427
+ #
428
+ # @param eps [Float,Rational]
429
+ # @return [Calc::Q]
430
+ # @example
431
+ # Calc::Q(5033165, 16777216).rationalize #=> Calc::Q(5033165/16777216)
432
+ # Calc::Q(5033165, 16777216).rationalize(Rational('0.01')) #=> Calc::Q(3/10)
433
+ # Calc::Q(5033165, 16777216).rationalize(Rational('0.1')) #=> Calc::Q(1/3)
434
+ def rationalize(eps = nil)
435
+ eps ? Q.new(to_r.rationalize(eps)) : self
436
+ end
437
+
438
+ def re
439
+ self
440
+ end
441
+
442
+ # Returns true if this number has zero imaginary part. Instances of this
443
+ # class always return true.
444
+ #
445
+ # @return [Boolean]
446
+ # @example
447
+ # Calc::Q(1).real? #=> true
448
+ def real?
449
+ true
450
+ end
451
+
452
+ # Remainder of `self` divided by `y`
453
+ #
454
+ # This method is provided for compatibility with ruby's
455
+ # `Numeric#remainder`. Unlike `%` and `mod`, this method behaves the same
456
+ # as the ruby version, unaffected by `Calc.config(:mod).
457
+ #
458
+ # @param y [Numeric]
459
+ # @return [Calc::C,Calc::Q]
460
+ # @example
461
+ # Calc::Q(13).remainder(4) #=> Calc::Q(1)
462
+ def remainder(y)
463
+ z = modulo(y)
464
+ if !z.zero? && ((self < 0 && y > 0) || (self > 0 && y < 0))
465
+ z - y
466
+ else
467
+ z
468
+ end
469
+ end
470
+
471
+ # Invokes the given block with the sequence of numbers starting at self
472
+ # incrementing by step (default 1) on each call.
473
+ #
474
+ # In the first format, uses keyword parameters:
475
+ # x.step(by: step, to: limit)
476
+ #
477
+ # In the second format, uses positional parameters:
478
+ # x.step(limit = nil, step = 1)
479
+ #
480
+ # If step is negative, the sequence decrements instead of incrementing.
481
+ # If step is zero, the sequence will yield self forever.
482
+ #
483
+ # If limit exists, the sequence will stop once the next item yielded would
484
+ # be higher than limit (if step is positive) or lower than limit (if step
485
+ # is negative). If limit is nil, the sequence never stops.
486
+ #
487
+ # If no block is givem, an Enumerator is returned instead.
488
+ #
489
+ # This method was added for ruby Numeric compatibiliy; unlike Numeric#step,
490
+ # it is not an error for step to be zero in the positional format.
491
+ #
492
+ # @param by [Numeric] amount to add to sequence each iteration
493
+ # @param to [Numeric] end of sequence value
494
+ # @return [Enumerator,nil]
495
+ # @example
496
+ # Calc::Q(1).step(10, 3).to_a #=> [Calc::Q(1), Calc::Q(4), Calc::Q(7), Calc::Q(10)]
497
+ # Calc::Q(10).step(by: -2).take(4) #=> [Calc::Q(10), Calc::Q(8), Calc::Q(6), Calc::Q(4)]
498
+ # Calc::Q(1).exp.step(to: Calc.pi, by: "0.2") { |q| print q, " " } #=> nil
499
+ # prints:
500
+ # 2.71828182845904523536 2.91828182845904523536 3.11828182845904523536
501
+ def step(a1 = nil, a2 = ONE)
502
+ return to_enum(:step, a1, a2) unless block_given?
503
+ to, by = step_args(a1, a2)
504
+ loop { yield self } if by.zero?
505
+ i = self
506
+ loop do
507
+ break if to && ((by.positive? && i > to) || (by.negative? && i < to))
508
+ yield i
509
+ i += by
510
+ end
511
+ end
512
+
513
+ # work out what the caller meant with their args to #step
514
+ # returns an array of [to, by] parameters
515
+ def step_args(a1, a2)
516
+ if a1.is_a?(Hash)
517
+ # fake keywords style
518
+ badkeys = a1.keys - %i(to by)
519
+ raise ArgumentError, "Unknown keywords: #{ badkeys.join(", ") }" if badkeys.any?
520
+ to = a1.fetch(:to, nil)
521
+ by = a1.fetch(:by, ONE)
522
+ else
523
+ # positional style (limit, step)
524
+ to = a1
525
+ by = a2
526
+ end
527
+ [to ? Q.new(to) : nil, Q.new(by)]
528
+ end
529
+ private :step_args
530
+
531
+ # Returns one more than self.
532
+ #
533
+ # This method exists for ruby Fixnum/Integer compatibility.
534
+ #
535
+ # @return [Calc::Q]
536
+ # @example
537
+ # Calc::Q(1).pred #=> Calc::Q(2)
538
+ def succ
539
+ self + ONE
540
+ end
541
+ alias next succ
542
+
543
+ # Iterates the given block `self` times, passing in values from zero to
544
+ # self - 1
545
+ #
546
+ # If no block is given, an Enumerator is returned instead.
547
+ #
548
+ # @return [Enumerator,nil]
549
+ # @example
550
+ # Calc::Q(5).times { |i| print i, " " }
551
+ # #=> 0 1 2 3 4
552
+ def times
553
+ return to_enum(:times) unless block_given?
554
+ i = ZERO
555
+ while i < self
556
+ yield i
557
+ i += ONE
558
+ end
559
+ end
560
+
561
+ # Returns a ruby Complex number with self as the real part and zero
562
+ # imaginary part.
563
+ #
564
+ # @return [Complex]
565
+ # @example
566
+ # Calc::Q(2).to_c #=> (2+0i)
567
+ # Calc::Q(2.5).to_c #=> ((5/2)+0i)
568
+ def to_c
569
+ Complex(int? ? to_i : to_r, 0)
570
+ end
571
+
572
+ # Returns a Calc::C complex number with self as the real part and zero
573
+ # imaginary part.
574
+ #
575
+ # @return [Calc::C]
576
+ # @example
577
+ # Calc::Q(2).to_complex #=> Calc::C(2)
578
+ def to_complex
579
+ C.new(self, 0)
580
+ end
581
+
582
+ # libcalc has no concept of floating point numbers. so we use ruby's
583
+ # Rational#to_f
584
+ def to_f
585
+ to_r.to_f
586
+ end
587
+
588
+ # convert to a core ruby Rational
589
+ def to_r
590
+ Rational(numerator.to_i, denominator.to_i)
591
+ end
592
+
593
+ alias truncate trunc
594
+
595
+ # Iterates the given block, yielding values from `self` increasing by 1
596
+ # up to and including `limit`
597
+ #
598
+ # x.upto(limit) is equivalent to x.step(by: 1, to: limit)
599
+ #
600
+ # If no block is given, an Enumerator is returned instead.
601
+ #
602
+ # @return [Enumerator,nil]
603
+ # @param limit [Numeric] highest value to return
604
+ # @example
605
+ # Calc::Q(5).upto(10) { |i| print i, " " } #=> 5 6 7 8 9 10
606
+ def upto(limit, &block)
607
+ step(limit, ONE, &block)
608
+ end
609
+
610
+ # Bitwise exclusive or of a set of integers
611
+ #
612
+ # xor(a, b, c, ...) is equivalent to (((a ^ b) ^ c) ... )
613
+ # note that ^ is the ruby xor operator, not the calc power operator.
614
+ #
615
+ # @return [Calc::Q]
616
+ # @example
617
+ # Calc::Q(3).xor(5) #=> Calc::Q(6)
618
+ # Calc::Q(5).xor(3, -7, 2, 9) #=> Calc::Q(-12)
619
+ def xor(*args)
620
+ args.inject(self, :^)
621
+ end
622
+
623
+ # aliases for compatibility with ruby Fixnum/Bignum/Rational
624
+ alias imag im
625
+ alias integer? int?
626
+ alias real re
627
+ end
628
+ end