rubysl-complex 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE +25 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/lib/complex.rb +1 -0
- data/lib/rubysl/complex.rb +2 -0
- data/lib/rubysl/complex/complex.rb +659 -0
- data/lib/rubysl/complex/version.rb +5 -0
- data/rubysl-complex.gemspec +23 -0
- data/spec/Complex_spec.rb +9 -0
- data/spec/abs2_spec.rb +10 -0
- data/spec/abs_spec.rb +10 -0
- data/spec/angle_spec.rb +7 -0
- data/spec/arg_spec.rb +7 -0
- data/spec/coerce_spec.rb +11 -0
- data/spec/comparison_spec.rb +23 -0
- data/spec/conj_spec.rb +7 -0
- data/spec/conjugate_spec.rb +7 -0
- data/spec/constants_spec.rb +9 -0
- data/spec/denominator_spec.rb +20 -0
- data/spec/divide_spec.rb +9 -0
- data/spec/equal_value_spec.rb +9 -0
- data/spec/exponent_spec.rb +10 -0
- data/spec/float/angle_spec.rb +9 -0
- data/spec/float/arg_spec.rb +9 -0
- data/spec/generic_spec.rb +25 -0
- data/spec/hash_spec.rb +10 -0
- data/spec/imag_spec.rb +10 -0
- data/spec/image_spec.rb +7 -0
- data/spec/inspect_spec.rb +10 -0
- data/spec/math/acos_spec.rb +30 -0
- data/spec/math/acosh_spec.rb +30 -0
- data/spec/math/asin_spec.rb +30 -0
- data/spec/math/asinh_spec.rb +30 -0
- data/spec/math/atan2_spec.rb +30 -0
- data/spec/math/atan_spec.rb +30 -0
- data/spec/math/atanh_spec.rb +34 -0
- data/spec/math/cos_spec.rb +30 -0
- data/spec/math/cosh_spec.rb +30 -0
- data/spec/math/exp_spec.rb +30 -0
- data/spec/math/fixtures/classes.rb +3 -0
- data/spec/math/log10_spec.rb +30 -0
- data/spec/math/log_spec.rb +30 -0
- data/spec/math/shared/acos.rb +41 -0
- data/spec/math/shared/acosh.rb +37 -0
- data/spec/math/shared/asin.rb +47 -0
- data/spec/math/shared/asinh.rb +32 -0
- data/spec/math/shared/atan.rb +32 -0
- data/spec/math/shared/atan2.rb +34 -0
- data/spec/math/shared/atanh.rb +30 -0
- data/spec/math/shared/cos.rb +30 -0
- data/spec/math/shared/cosh.rb +28 -0
- data/spec/math/shared/exp.rb +28 -0
- data/spec/math/shared/log.rb +39 -0
- data/spec/math/shared/log10.rb +41 -0
- data/spec/math/shared/sin.rb +30 -0
- data/spec/math/shared/sinh.rb +28 -0
- data/spec/math/shared/sqrt.rb +34 -0
- data/spec/math/shared/tan.rb +28 -0
- data/spec/math/shared/tanh.rb +32 -0
- data/spec/math/sin_spec.rb +30 -0
- data/spec/math/sinh_spec.rb +30 -0
- data/spec/math/sqrt_spec.rb +30 -0
- data/spec/math/tan_spec.rb +30 -0
- data/spec/math/tanh_spec.rb +30 -0
- data/spec/minus_spec.rb +9 -0
- data/spec/modulo_spec.rb +29 -0
- data/spec/multiply_spec.rb +9 -0
- data/spec/new_spec.rb +41 -0
- data/spec/numerator_spec.rb +12 -0
- data/spec/numeric/angle_spec.rb +11 -0
- data/spec/numeric/arg_spec.rb +11 -0
- data/spec/numeric/conj_spec.rb +11 -0
- data/spec/numeric/conjugate_spec.rb +11 -0
- data/spec/numeric/im_spec.rb +9 -0
- data/spec/numeric/imag_spec.rb +11 -0
- data/spec/numeric/image_spec.rb +11 -0
- data/spec/numeric/polar_spec.rb +11 -0
- data/spec/numeric/real_spec.rb +11 -0
- data/spec/plus_spec.rb +9 -0
- data/spec/polar_spec.rb +13 -0
- data/spec/real_spec.rb +10 -0
- data/spec/to_s_spec.rb +9 -0
- metadata +259 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 31178e7af89237346bf8e84d8110243f02b1b6a2
|
4
|
+
data.tar.gz: 7fce5e73fefcb231723503020de2438aae79956e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ff6f9d1852f6b604a631188bb9b5969979fae448526997f977a67552bbfd67c5259641d1cc7d22d4528a84a44802c435400480eeeded6651dc1aa4a4632b5048
|
7
|
+
data.tar.gz: 91e053b6c27ceacc715bbc941977c0325bea3d03130921f398fb7759e62660aed941de1e353307fca1379af4678eacdb0a012936faa102c323874f0a93a1899c
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) 2013, Brian Shirai
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
3. Neither the name of the library nor the names of its contributors may be
|
13
|
+
used to endorse or promote products derived from this software without
|
14
|
+
specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
17
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
18
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT,
|
20
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
21
|
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
22
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
23
|
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
24
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
25
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# RubySL::Complex
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'rubysl-complex'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install rubysl-complex
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/complex.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "rubysl/complex"
|
@@ -0,0 +1,659 @@
|
|
1
|
+
#
|
2
|
+
# complex.rb -
|
3
|
+
# $Release Version: 0.5 $
|
4
|
+
# $Revision: 1.3 $
|
5
|
+
# $Date: 1998/07/08 10:05:28 $
|
6
|
+
# by Keiju ISHITSUKA(SHL Japan Inc.)
|
7
|
+
#
|
8
|
+
# ----
|
9
|
+
#
|
10
|
+
# complex.rb implements the Complex class for complex numbers. Additionally,
|
11
|
+
# some methods in other Numeric classes are redefined or added to allow greater
|
12
|
+
# interoperability with Complex numbers.
|
13
|
+
#
|
14
|
+
# Complex numbers can be created in the following manner:
|
15
|
+
# - <tt>Complex(a, b)</tt>
|
16
|
+
# - <tt>Complex.polar(radius, theta)</tt>
|
17
|
+
#
|
18
|
+
# Additionally, note the following:
|
19
|
+
# - <tt>Complex::I</tt> (the mathematical constant <i>i</i>)
|
20
|
+
# - <tt>Numeric#im</tt> (e.g. <tt>5.im -> 0+5i</tt>)
|
21
|
+
#
|
22
|
+
# The following +Math+ module methods are redefined to handle Complex arguments.
|
23
|
+
# They will work as normal with non-Complex arguments.
|
24
|
+
# sqrt exp cos sin tan log log10
|
25
|
+
# cosh sinh tanh acos asin atan atan2 acosh asinh atanh
|
26
|
+
#
|
27
|
+
|
28
|
+
|
29
|
+
#
|
30
|
+
# Numeric is a built-in class on which Fixnum, Bignum, etc., are based. Here
|
31
|
+
# some methods are added so that all number types can be treated to some extent
|
32
|
+
# as Complex numbers.
|
33
|
+
#
|
34
|
+
class Numeric
|
35
|
+
#
|
36
|
+
# Returns a Complex number <tt>(0,<i>self</i>)</tt>.
|
37
|
+
#
|
38
|
+
def im
|
39
|
+
Complex(0, self)
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# The real part of a complex number, i.e. <i>self</i>.
|
44
|
+
#
|
45
|
+
def real
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# The imaginary part of a complex number, i.e. 0.
|
51
|
+
#
|
52
|
+
def image
|
53
|
+
0
|
54
|
+
end
|
55
|
+
alias imag image
|
56
|
+
|
57
|
+
#
|
58
|
+
# See Complex#arg.
|
59
|
+
#
|
60
|
+
def arg
|
61
|
+
Math.atan2!(0, self)
|
62
|
+
end
|
63
|
+
alias angle arg
|
64
|
+
|
65
|
+
#
|
66
|
+
# See Complex#polar.
|
67
|
+
#
|
68
|
+
def polar
|
69
|
+
return abs, arg
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# See Complex#conjugate (short answer: returns <i>self</i>).
|
74
|
+
#
|
75
|
+
def conjugate
|
76
|
+
self
|
77
|
+
end
|
78
|
+
alias conj conjugate
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
#
|
83
|
+
# Creates a Complex number. +a+ and +b+ should be Numeric. The result will be
|
84
|
+
# <tt>a+bi</tt>.
|
85
|
+
#
|
86
|
+
def Complex(a, b = 0)
|
87
|
+
if b == 0 and (a.kind_of?(Complex) or defined? Complex::Unify)
|
88
|
+
a
|
89
|
+
else
|
90
|
+
Complex.new( a.real-b.imag, a.imag+b.real )
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# The complex number class. See complex.rb for an overview.
|
96
|
+
#
|
97
|
+
class Complex < Numeric
|
98
|
+
@RCS_ID='-$Id: complex.rb,v 1.3 1998/07/08 10:05:28 keiju Exp keiju $-'
|
99
|
+
|
100
|
+
undef step
|
101
|
+
undef div, divmod
|
102
|
+
undef floor, truncate, ceil, round
|
103
|
+
|
104
|
+
def Complex.generic?(other) # :nodoc:
|
105
|
+
other.kind_of?(Integer) or
|
106
|
+
other.kind_of?(Float) or
|
107
|
+
(defined?(Rational) and other.kind_of?(Rational))
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
# Creates a +Complex+ number in terms of +r+ (radius) and +theta+ (angle).
|
112
|
+
#
|
113
|
+
def Complex.polar(r, theta)
|
114
|
+
Complex(r*Math.cos(theta), r*Math.sin(theta))
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Creates a +Complex+ number <tt>a</tt>+<tt>b</tt><i>i</i>.
|
119
|
+
#
|
120
|
+
def Complex.new!(a, b=0)
|
121
|
+
new(a,b)
|
122
|
+
end
|
123
|
+
|
124
|
+
def initialize(a, b)
|
125
|
+
raise TypeError, "non numeric 1st arg `#{a.inspect}'" if !a.kind_of? Numeric
|
126
|
+
raise TypeError, "`#{a.inspect}' for 1st arg" if a.kind_of? Complex
|
127
|
+
raise TypeError, "non numeric 2nd arg `#{b.inspect}'" if !b.kind_of? Numeric
|
128
|
+
raise TypeError, "`#{b.inspect}' for 2nd arg" if b.kind_of? Complex
|
129
|
+
@real = a
|
130
|
+
@image = b
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# Addition with real or complex number.
|
135
|
+
#
|
136
|
+
def + (other)
|
137
|
+
if other.kind_of?(Complex)
|
138
|
+
re = @real + other.real
|
139
|
+
im = @image + other.image
|
140
|
+
Complex(re, im)
|
141
|
+
elsif Complex.generic?(other)
|
142
|
+
Complex(@real + other, @image)
|
143
|
+
else
|
144
|
+
x , y = other.coerce(self)
|
145
|
+
x + y
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
#
|
150
|
+
# Subtraction with real or complex number.
|
151
|
+
#
|
152
|
+
def - (other)
|
153
|
+
if other.kind_of?(Complex)
|
154
|
+
re = @real - other.real
|
155
|
+
im = @image - other.image
|
156
|
+
Complex(re, im)
|
157
|
+
elsif Complex.generic?(other)
|
158
|
+
Complex(@real - other, @image)
|
159
|
+
else
|
160
|
+
x , y = other.coerce(self)
|
161
|
+
x - y
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
#
|
166
|
+
# Multiplication with real or complex number.
|
167
|
+
#
|
168
|
+
def * (other)
|
169
|
+
if other.kind_of?(Complex)
|
170
|
+
re = @real*other.real - @image*other.image
|
171
|
+
im = @real*other.image + @image*other.real
|
172
|
+
Complex(re, im)
|
173
|
+
elsif Complex.generic?(other)
|
174
|
+
Complex(@real * other, @image * other)
|
175
|
+
else
|
176
|
+
x , y = other.coerce(self)
|
177
|
+
x * y
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
#
|
182
|
+
# Division by real or complex number.
|
183
|
+
#
|
184
|
+
def / (other)
|
185
|
+
if other.kind_of?(Complex)
|
186
|
+
self*other.conjugate/other.abs2
|
187
|
+
elsif Complex.generic?(other)
|
188
|
+
Complex(@real/other, @image/other)
|
189
|
+
else
|
190
|
+
x, y = other.coerce(self)
|
191
|
+
x/y
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def quo(other)
|
196
|
+
Complex(@real.quo(1), @image.quo(1)) / other
|
197
|
+
end
|
198
|
+
|
199
|
+
#
|
200
|
+
# Raise this complex number to the given (real or complex) power.
|
201
|
+
#
|
202
|
+
def ** (other)
|
203
|
+
if other == 0
|
204
|
+
return Complex(1)
|
205
|
+
end
|
206
|
+
if other.kind_of?(Complex)
|
207
|
+
r, theta = polar
|
208
|
+
ore = other.real
|
209
|
+
oim = other.image
|
210
|
+
nr = Math.exp!(ore*Math.log!(r) - oim * theta)
|
211
|
+
ntheta = theta*ore + oim*Math.log!(r)
|
212
|
+
Complex.polar(nr, ntheta)
|
213
|
+
elsif other.kind_of?(Integer)
|
214
|
+
if other > 0
|
215
|
+
x = self
|
216
|
+
z = x
|
217
|
+
n = other - 1
|
218
|
+
while n != 0
|
219
|
+
while (div, mod = n.divmod(2)
|
220
|
+
mod == 0)
|
221
|
+
x = Complex(x.real*x.real - x.image*x.image, 2*x.real*x.image)
|
222
|
+
n = div
|
223
|
+
end
|
224
|
+
z *= x
|
225
|
+
n -= 1
|
226
|
+
end
|
227
|
+
z
|
228
|
+
else
|
229
|
+
if defined? Rational
|
230
|
+
(Rational(1) / self) ** -other
|
231
|
+
else
|
232
|
+
self ** Float(other)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
elsif Complex.generic?(other)
|
236
|
+
r, theta = polar
|
237
|
+
Complex.polar(r**other, theta*other)
|
238
|
+
else
|
239
|
+
x, y = other.coerce(self)
|
240
|
+
x**y
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
#
|
245
|
+
# Remainder after division by a real or complex number.
|
246
|
+
#
|
247
|
+
def % (other)
|
248
|
+
if other.kind_of?(Complex)
|
249
|
+
Complex(@real % other.real, @image % other.image)
|
250
|
+
elsif Complex.generic?(other)
|
251
|
+
Complex(@real % other, @image % other)
|
252
|
+
else
|
253
|
+
x , y = other.coerce(self)
|
254
|
+
x % y
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
#--
|
259
|
+
# def divmod(other)
|
260
|
+
# if other.kind_of?(Complex)
|
261
|
+
# rdiv, rmod = @real.divmod(other.real)
|
262
|
+
# idiv, imod = @image.divmod(other.image)
|
263
|
+
# return Complex(rdiv, idiv), Complex(rmod, rmod)
|
264
|
+
# elsif Complex.generic?(other)
|
265
|
+
# Complex(@real.divmod(other), @image.divmod(other))
|
266
|
+
# else
|
267
|
+
# x , y = other.coerce(self)
|
268
|
+
# x.divmod(y)
|
269
|
+
# end
|
270
|
+
# end
|
271
|
+
#++
|
272
|
+
|
273
|
+
#
|
274
|
+
# Absolute value (aka modulus): distance from the zero point on the complex
|
275
|
+
# plane.
|
276
|
+
#
|
277
|
+
def abs
|
278
|
+
Math.hypot(@real, @image)
|
279
|
+
end
|
280
|
+
|
281
|
+
#
|
282
|
+
# Square of the absolute value.
|
283
|
+
#
|
284
|
+
def abs2
|
285
|
+
@real*@real + @image*@image
|
286
|
+
end
|
287
|
+
|
288
|
+
#
|
289
|
+
# Argument (angle from (1,0) on the complex plane).
|
290
|
+
#
|
291
|
+
def arg
|
292
|
+
Math.atan2!(@image, @real)
|
293
|
+
end
|
294
|
+
alias angle arg
|
295
|
+
|
296
|
+
#
|
297
|
+
# Returns the absolute value _and_ the argument.
|
298
|
+
#
|
299
|
+
def polar
|
300
|
+
return abs, arg
|
301
|
+
end
|
302
|
+
|
303
|
+
#
|
304
|
+
# Complex conjugate (<tt>z + z.conjugate = 2 * z.real</tt>).
|
305
|
+
#
|
306
|
+
def conjugate
|
307
|
+
Complex(@real, -@image)
|
308
|
+
end
|
309
|
+
alias conj conjugate
|
310
|
+
|
311
|
+
#
|
312
|
+
# Compares the absolute values of the two numbers.
|
313
|
+
#
|
314
|
+
def <=> (other)
|
315
|
+
self.abs <=> other.abs
|
316
|
+
end
|
317
|
+
|
318
|
+
#
|
319
|
+
# Test for numerical equality (<tt>a == a + 0<i>i</i></tt>).
|
320
|
+
#
|
321
|
+
def == (other)
|
322
|
+
if other.kind_of?(Complex)
|
323
|
+
@real == other.real and @image == other.image
|
324
|
+
elsif Complex.generic?(other)
|
325
|
+
@real == other and @image == 0
|
326
|
+
else
|
327
|
+
other == self
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
#
|
332
|
+
# Attempts to coerce +other+ to a Complex number.
|
333
|
+
#
|
334
|
+
def coerce(other)
|
335
|
+
if Complex.generic?(other)
|
336
|
+
return Complex.new!(other), self
|
337
|
+
else
|
338
|
+
super
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
#
|
343
|
+
# FIXME
|
344
|
+
#
|
345
|
+
def denominator
|
346
|
+
@real.denominator.lcm(@image.denominator)
|
347
|
+
end
|
348
|
+
|
349
|
+
#
|
350
|
+
# FIXME
|
351
|
+
#
|
352
|
+
def numerator
|
353
|
+
cd = denominator
|
354
|
+
Complex(@real.numerator*(cd/@real.denominator),
|
355
|
+
@image.numerator*(cd/@image.denominator))
|
356
|
+
end
|
357
|
+
|
358
|
+
#
|
359
|
+
# Standard string representation of the complex number.
|
360
|
+
#
|
361
|
+
def to_s
|
362
|
+
if @real != 0
|
363
|
+
if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
|
364
|
+
if @image >= 0
|
365
|
+
@real.to_s+"+("+@image.to_s+")i"
|
366
|
+
else
|
367
|
+
@real.to_s+"-("+(-@image).to_s+")i"
|
368
|
+
end
|
369
|
+
else
|
370
|
+
if @image >= 0
|
371
|
+
@real.to_s+"+"+@image.to_s+"i"
|
372
|
+
else
|
373
|
+
@real.to_s+"-"+(-@image).to_s+"i"
|
374
|
+
end
|
375
|
+
end
|
376
|
+
else
|
377
|
+
if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
|
378
|
+
"("+@image.to_s+")i"
|
379
|
+
else
|
380
|
+
@image.to_s+"i"
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
#
|
386
|
+
# Returns a hash code for the complex number.
|
387
|
+
#
|
388
|
+
def hash
|
389
|
+
@real.hash ^ @image.hash
|
390
|
+
end
|
391
|
+
|
392
|
+
#
|
393
|
+
# Returns "<tt>Complex(<i>real</i>, <i>image</i>)</tt>".
|
394
|
+
#
|
395
|
+
def inspect
|
396
|
+
sprintf("Complex(%s, %s)", @real.inspect, @image.inspect)
|
397
|
+
end
|
398
|
+
|
399
|
+
|
400
|
+
#
|
401
|
+
# +I+ is the imaginary number. It exists at point (0,1) on the complex plane.
|
402
|
+
#
|
403
|
+
I = Complex(0,1)
|
404
|
+
|
405
|
+
# The real part of a complex number.
|
406
|
+
attr :real
|
407
|
+
|
408
|
+
# The imaginary part of a complex number.
|
409
|
+
attr :image
|
410
|
+
alias imag image
|
411
|
+
|
412
|
+
end
|
413
|
+
|
414
|
+
class Integer
|
415
|
+
|
416
|
+
unless defined?(1.numerator)
|
417
|
+
def numerator() self end
|
418
|
+
def denominator() 1 end
|
419
|
+
|
420
|
+
def gcd(other)
|
421
|
+
min = self.abs
|
422
|
+
max = other.abs
|
423
|
+
while min > 0
|
424
|
+
tmp = min
|
425
|
+
min = max % min
|
426
|
+
max = tmp
|
427
|
+
end
|
428
|
+
max
|
429
|
+
end
|
430
|
+
|
431
|
+
def lcm(other)
|
432
|
+
if self.zero? or other.zero?
|
433
|
+
0
|
434
|
+
else
|
435
|
+
(self.div(self.gcd(other)) * other).abs
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
end
|
440
|
+
|
441
|
+
end
|
442
|
+
|
443
|
+
module Math
|
444
|
+
alias sqrt! sqrt
|
445
|
+
alias exp! exp
|
446
|
+
alias log! log
|
447
|
+
alias log10! log10
|
448
|
+
alias cos! cos
|
449
|
+
alias sin! sin
|
450
|
+
alias tan! tan
|
451
|
+
alias cosh! cosh
|
452
|
+
alias sinh! sinh
|
453
|
+
alias tanh! tanh
|
454
|
+
alias acos! acos
|
455
|
+
alias asin! asin
|
456
|
+
alias atan! atan
|
457
|
+
alias atan2! atan2
|
458
|
+
alias acosh! acosh
|
459
|
+
alias asinh! asinh
|
460
|
+
alias atanh! atanh
|
461
|
+
|
462
|
+
# Redefined to handle a Complex argument.
|
463
|
+
def sqrt(z)
|
464
|
+
if Complex.generic?(z)
|
465
|
+
if z >= 0
|
466
|
+
sqrt!(z)
|
467
|
+
else
|
468
|
+
Complex(0,sqrt!(-z))
|
469
|
+
end
|
470
|
+
else
|
471
|
+
if z.image < 0
|
472
|
+
sqrt(z.conjugate).conjugate
|
473
|
+
else
|
474
|
+
r = z.abs
|
475
|
+
x = z.real
|
476
|
+
Complex( sqrt!((r+x)/2), sqrt!((r-x)/2) )
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
# Redefined to handle a Complex argument.
|
482
|
+
def exp(z)
|
483
|
+
if Complex.generic?(z)
|
484
|
+
exp!(z)
|
485
|
+
else
|
486
|
+
Complex(exp!(z.real) * cos!(z.image), exp!(z.real) * sin!(z.image))
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
# Redefined to handle a Complex argument.
|
491
|
+
def cos(z)
|
492
|
+
if Complex.generic?(z)
|
493
|
+
cos!(z)
|
494
|
+
else
|
495
|
+
Complex(cos!(z.real)*cosh!(z.image),
|
496
|
+
-sin!(z.real)*sinh!(z.image))
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
# Redefined to handle a Complex argument.
|
501
|
+
def sin(z)
|
502
|
+
if Complex.generic?(z)
|
503
|
+
sin!(z)
|
504
|
+
else
|
505
|
+
Complex(sin!(z.real)*cosh!(z.image),
|
506
|
+
cos!(z.real)*sinh!(z.image))
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
# Redefined to handle a Complex argument.
|
511
|
+
def tan(z)
|
512
|
+
if Complex.generic?(z)
|
513
|
+
tan!(z)
|
514
|
+
else
|
515
|
+
sin(z)/cos(z)
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
def sinh(z)
|
520
|
+
if Complex.generic?(z)
|
521
|
+
sinh!(z)
|
522
|
+
else
|
523
|
+
Complex( sinh!(z.real)*cos!(z.image), cosh!(z.real)*sin!(z.image) )
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
def cosh(z)
|
528
|
+
if Complex.generic?(z)
|
529
|
+
cosh!(z)
|
530
|
+
else
|
531
|
+
Complex( cosh!(z.real)*cos!(z.image), sinh!(z.real)*sin!(z.image) )
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
def tanh(z)
|
536
|
+
if Complex.generic?(z)
|
537
|
+
tanh!(z)
|
538
|
+
else
|
539
|
+
sinh(z)/cosh(z)
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
# Redefined to handle a Complex argument.
|
544
|
+
def log(z)
|
545
|
+
if Complex.generic?(z) and z >= 0
|
546
|
+
log!(z)
|
547
|
+
else
|
548
|
+
r, theta = z.polar
|
549
|
+
Complex(log!(r.abs), theta)
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
# Redefined to handle a Complex argument.
|
554
|
+
def log10(z)
|
555
|
+
if Complex.generic?(z)
|
556
|
+
log10!(z)
|
557
|
+
else
|
558
|
+
log(z)/log!(10)
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
def acos(z)
|
563
|
+
if Complex.generic?(z) and z >= -1 and z <= 1
|
564
|
+
acos!(z)
|
565
|
+
else
|
566
|
+
-1.0.im * log( z + 1.0.im * sqrt(1.0-z*z) )
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
def asin(z)
|
571
|
+
if Complex.generic?(z) and z >= -1 and z <= 1
|
572
|
+
asin!(z)
|
573
|
+
else
|
574
|
+
-1.0.im * log( 1.0.im * z + sqrt(1.0-z*z) )
|
575
|
+
end
|
576
|
+
end
|
577
|
+
|
578
|
+
def atan(z)
|
579
|
+
if Complex.generic?(z)
|
580
|
+
atan!(z)
|
581
|
+
else
|
582
|
+
1.0.im * log( (1.0.im+z) / (1.0.im-z) ) / 2.0
|
583
|
+
end
|
584
|
+
end
|
585
|
+
|
586
|
+
def atan2(y,x)
|
587
|
+
if Complex.generic?(y) and Complex.generic?(x)
|
588
|
+
atan2!(y,x)
|
589
|
+
else
|
590
|
+
-1.0.im * log( (x+1.0.im*y) / sqrt(x*x+y*y) )
|
591
|
+
end
|
592
|
+
end
|
593
|
+
|
594
|
+
def acosh(z)
|
595
|
+
if Complex.generic?(z) and z >= 1
|
596
|
+
acosh!(z)
|
597
|
+
else
|
598
|
+
log( z + sqrt(z*z-1.0) )
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
def asinh(z)
|
603
|
+
if Complex.generic?(z)
|
604
|
+
asinh!(z)
|
605
|
+
else
|
606
|
+
log( z + sqrt(1.0+z*z) )
|
607
|
+
end
|
608
|
+
end
|
609
|
+
|
610
|
+
def atanh(z)
|
611
|
+
if Complex.generic?(z) and z >= -1 and z <= 1
|
612
|
+
atanh!(z)
|
613
|
+
else
|
614
|
+
log( (1.0+z) / (1.0-z) ) / 2.0
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
module_function :sqrt!
|
619
|
+
module_function :sqrt
|
620
|
+
module_function :exp!
|
621
|
+
module_function :exp
|
622
|
+
module_function :log!
|
623
|
+
module_function :log
|
624
|
+
module_function :log10!
|
625
|
+
module_function :log10
|
626
|
+
module_function :cosh!
|
627
|
+
module_function :cosh
|
628
|
+
module_function :cos!
|
629
|
+
module_function :cos
|
630
|
+
module_function :sinh!
|
631
|
+
module_function :sinh
|
632
|
+
module_function :sin!
|
633
|
+
module_function :sin
|
634
|
+
module_function :tan!
|
635
|
+
module_function :tan
|
636
|
+
module_function :tanh!
|
637
|
+
module_function :tanh
|
638
|
+
module_function :acos!
|
639
|
+
module_function :acos
|
640
|
+
module_function :asin!
|
641
|
+
module_function :asin
|
642
|
+
module_function :atan!
|
643
|
+
module_function :atan
|
644
|
+
module_function :atan2!
|
645
|
+
module_function :atan2
|
646
|
+
module_function :acosh!
|
647
|
+
module_function :acosh
|
648
|
+
module_function :asinh!
|
649
|
+
module_function :asinh
|
650
|
+
module_function :atanh!
|
651
|
+
module_function :atanh
|
652
|
+
|
653
|
+
end
|
654
|
+
|
655
|
+
# Documentation comments:
|
656
|
+
# - source: original (researched from pickaxe)
|
657
|
+
# - a couple of fixme's
|
658
|
+
# - RDoc output for Bignum etc. is a bit short, with nothing but an
|
659
|
+
# (undocumented) alias. No big deal.
|