bigcomplex 0.1
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.
- data/lib/bigcomplex.rb +188 -0
- metadata +48 -0
data/lib/bigcomplex.rb
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
# @author {https://github.com/karatedog karatedog}
|
2
|
+
class BigComplex
|
3
|
+
require 'bigdecimal'
|
4
|
+
@real, @imag = BigDecimal("0.0"), BigDecimal("0.0")
|
5
|
+
|
6
|
+
# @return [Boolean]
|
7
|
+
# @param [Fixnum, Bignum, String, Float, BigDecimal]
|
8
|
+
# Checks if _class_type_ is among the acceptable class types for creating a BigComplex object
|
9
|
+
def acceptable_class_type?(class_type)
|
10
|
+
return [Fixnum, Bignum, String, Float, BigDecimal].include?(class_type)
|
11
|
+
end
|
12
|
+
# for lazy typers
|
13
|
+
alias :act? :acceptable_class_type?
|
14
|
+
|
15
|
+
# @return [BigComplex]
|
16
|
+
# @param [Fixnum, Bignum, String, Float, BigDecimal, BigComplex] real_part,imag_part
|
17
|
+
# @raise TypeError If input is not one of the acceptable class types (acceptable_class_type?(type) == false)
|
18
|
+
# Creates a new BigComplex object.
|
19
|
+
def initialize(real_part=BigDecimal("0.0"), imag_part=BigDecimal("0.0"))
|
20
|
+
|
21
|
+
# If input is BigComplex, split the object to parts and return them as new objects
|
22
|
+
if real_part.class == BigComplex then
|
23
|
+
real_part = BigDecimal(real_part.real)
|
24
|
+
end
|
25
|
+
if imag_part.class == BigComplex then
|
26
|
+
imag_part = BigDecimal(imag_part.imag)
|
27
|
+
end
|
28
|
+
|
29
|
+
if real_part.class == Complex then
|
30
|
+
real_part = BigDecimal(real_part.real)
|
31
|
+
end
|
32
|
+
if imag_part.class == Complex then
|
33
|
+
imag_part = BigDecimal(imag_part.imag)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [BigDecimal]
|
37
|
+
# @param [Fixnum, Bignum, String, Float, BigDecimal]
|
38
|
+
# Converts values to BigDecimal to use for creating BigComplex objects. If input is a String and starts with letter, the converted value will be 0.
|
39
|
+
def convert_values(val)
|
40
|
+
case val
|
41
|
+
when Fixnum, Bignum, Float then BigDecimal(val.to_s) # Ruby 1.9.3< does not accept Integer, but 1.9.3+ does
|
42
|
+
when String then BigDecimal(val)
|
43
|
+
when BigDecimal then val
|
44
|
+
else return nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
raise(TypeError, "Not a Fixnum/Bignum, String, Float or BigDecimal!") unless acceptable_class_type?(real_part.class) and acceptable_class_type?(imag_part.class)
|
48
|
+
self.real = real_part
|
49
|
+
self.imag = imag_part
|
50
|
+
end
|
51
|
+
|
52
|
+
# @param [Fixnum, String, Float, BigDecimal, BigComplex]
|
53
|
+
# @return [BigDecimal]
|
54
|
+
# Returns the _real_ part of _self_
|
55
|
+
def real; @real; end
|
56
|
+
|
57
|
+
# @param [Fixnum, String, Float, BigDecimal, BigComplex] val
|
58
|
+
# @return [BigDecimal]
|
59
|
+
# Modifies _self.real_
|
60
|
+
# @raise TypeError
|
61
|
+
def real=(val); return @real = convert_values(val); end
|
62
|
+
|
63
|
+
# @return [BigDecimal]
|
64
|
+
def imag; return @imag; end
|
65
|
+
|
66
|
+
# @return [BigDecimal] Modifies _self.imaginary_
|
67
|
+
# @raise TypeError
|
68
|
+
# @param [Fixnum, String, Float, BigDecimal, BigComplex] val
|
69
|
+
def imag=(val); return @imag = convert_values(val); end
|
70
|
+
|
71
|
+
# @return [BigDecimal] the _imaginary_ part of _self_
|
72
|
+
alias :imaginary :imag
|
73
|
+
|
74
|
+
# (see #imag=)
|
75
|
+
# Alias for imag_
|
76
|
+
alias :imaginary= :imag=
|
77
|
+
|
78
|
+
# @return [Boolean]
|
79
|
+
# @param [Fixnum, String, Float, BigDecimal, BigComplex] other
|
80
|
+
# Returns _true_ if _other_.real == _self_.real and _other_.imag == _self_.imag (no type checking).
|
81
|
+
def ==(other)
|
82
|
+
self.real == other.real and self.imag == other.imag
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [BigComplex]
|
86
|
+
# @param [Fixnum, String, Float, BigDecimal, BigComplex] other The multiplicand
|
87
|
+
# Multiplies _self_ with _other_ and returns a new object.
|
88
|
+
def *(other)
|
89
|
+
case other
|
90
|
+
when Fixnum, Float, Bignum, BigDecimal
|
91
|
+
return BigComplex.new(self.real * other, self.imag * other)
|
92
|
+
when BigComplex
|
93
|
+
return BigComplex.new((self.real*other.real - self.imag*other.imag), (self.real*other.imag + self.imag*other.real))
|
94
|
+
else raise TypeError, "Not a Fixnum/Bignum, Float, BigDecimal or BigComplex!"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# @return [BigComplex]
|
99
|
+
# @param [Fixnum, String, Float, BigDecimal, BigComplex] other The addend
|
100
|
+
# Adds _other_ to _self_ and returns a new object.
|
101
|
+
def +(other)
|
102
|
+
# format the object
|
103
|
+
# @todo Check if input is String and if it can be converted. Automatic coerce somewhere?
|
104
|
+
case other
|
105
|
+
when Fixnum, Float, Bignum, BigDecimal
|
106
|
+
return BigComplex.new(self.real + other, self.imag)
|
107
|
+
when BigComplex
|
108
|
+
return BigComplex.new(self.real + other.real, self.real + other.imag)
|
109
|
+
else raise TypeError, "Not a Fixnum/Bignum, Float, BigDecimal or BigComplex!"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# @return [BigComplex]
|
114
|
+
# @param [Fixnum, String, Float, BigDecimal, BigComplex] other The subtrahend
|
115
|
+
# Subtracts _other_ from _self_ and returns a new object.
|
116
|
+
def -(other)
|
117
|
+
case other
|
118
|
+
when Fixnum, Float, Bignum, BigDecimal
|
119
|
+
return BigComplex.new(self.real - other, self.imag)
|
120
|
+
when BigComplex
|
121
|
+
return BigComplex.new(self.real - other.real, self.imag - other.imag)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# @return [BigComplex]
|
126
|
+
# @param [Fixnum, String, Float, BigDecimal, BigComplex] other The exponent
|
127
|
+
# Raises _self_ to the power of _other_ and returns a new object. Works well for huge exponents.
|
128
|
+
def **(other)
|
129
|
+
case other
|
130
|
+
when Fixnum, Bignum, BigDecimal
|
131
|
+
if other == 0 then
|
132
|
+
return BigComplex.new(1.0, 0.0)
|
133
|
+
fail "This line should not be reached" # being over-paranoid here
|
134
|
+
end
|
135
|
+
|
136
|
+
if other == 1 then
|
137
|
+
return self
|
138
|
+
fail "This line should not be reached"
|
139
|
+
end
|
140
|
+
|
141
|
+
if other < 0 then
|
142
|
+
return BigComplex.new
|
143
|
+
fail "This line should not be reached"
|
144
|
+
end
|
145
|
+
|
146
|
+
if (other.class == BigDecimal) && (other.to_i != other) then
|
147
|
+
raise TypeError, 'BigDecimal with a Rational value'
|
148
|
+
else
|
149
|
+
other = other.to_i
|
150
|
+
end
|
151
|
+
|
152
|
+
binary_repr_of_exponent = other.to_s(2).reverse.split('').map { |x| x.to_i }
|
153
|
+
base = self
|
154
|
+
result = binary_repr_of_exponent.reduce(BigComplex.new(1,0)) do | memo, value |
|
155
|
+
memo *= (value == 1 ? base : 1)
|
156
|
+
base = base * base
|
157
|
+
memo
|
158
|
+
end
|
159
|
+
return result # explicit return, just for visibility
|
160
|
+
else raise TypeError, 'Not a Fixnum, Bignum or BigDecimal for exponent'
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# Returns the conjugate of _self_ as new object
|
165
|
+
# @return [BigComplex]
|
166
|
+
def conjugate
|
167
|
+
BigComplex.new(self.real, -self.imag)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Returns the magnitude of _self_. It can be calculation heavy for large numbers
|
171
|
+
# @return [BigDecimal]
|
172
|
+
def magnitude
|
173
|
+
(self.real**2 + self.imag**2).sqrt(12) # uhh-ohh, need to ditch sqrt as of now, it is imprecise as well.
|
174
|
+
end
|
175
|
+
|
176
|
+
# @return [Complex, BigComplex]
|
177
|
+
# Converts _self_ to Complex if it fits Complex' boundaries. The method _will_ _not_ require the Complex library and if no Complex class is available, returns _self_. Some rubies contain Complex class by default, some not (ie: MRI 1.8.7)
|
178
|
+
def to_c
|
179
|
+
begin
|
180
|
+
dmy = Complex(1,2) # dummy Complex value
|
181
|
+
rescue NoMethodError
|
182
|
+
return self # Complex class is not available
|
183
|
+
rescue
|
184
|
+
return self # some other thing hit the fan
|
185
|
+
end
|
186
|
+
return Complex(self.real.to_i, self.imag.to_i) # there is no type/size check yet. Converting with to_i loses fractional part but keeps magnitude.
|
187
|
+
end
|
188
|
+
end
|
metadata
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bigcomplex
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Földes László
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-30 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A replacement of the standard Complex class for better precision for
|
15
|
+
certain operations (addition, subtraction, multiplication, power)
|
16
|
+
email: foldes.laszlo2@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/bigcomplex.rb
|
22
|
+
homepage: ''
|
23
|
+
licenses: []
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubyforge_project:
|
42
|
+
rubygems_version: 1.8.17
|
43
|
+
signing_key:
|
44
|
+
specification_version: 3
|
45
|
+
summary: A replacement of the standard Complex class for better precision for certain
|
46
|
+
operations
|
47
|
+
test_files: []
|
48
|
+
has_rdoc:
|