bigcomplex 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/bigcomplex.rb +188 -0
  2. metadata +48 -0
@@ -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: