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.
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: