PageRenderTime 16ms CodeModel.GetById 9ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib/numeric/complex_general.e

http://github.com/tybor/Liberty
Specman e | 260 lines | 174 code | 30 blank | 56 comment | 0 complexity | 530cc265ee86ad9e380a59b998a0eae0 MD5 | raw file
  1-- This file is part of a Liberty Eiffel library.
  2-- See the full copyright at the end.
  3--
  4expanded class COMPLEX_GENERAL[A_SIZE -> FLOAT]
  5   --
  6   -- Common ancestor of all complex types: COMPLEX_32, COMPLEX_64, ...
  7   --
  8
  9insert
 10   NUMERIC
 11      rename sign as real_sign
 12      redefine out, fill_tagged_out_memory
 13      end
 14   MATH_CONSTANTS
 15      -- to get Pi
 16      undefine is_equal, out, fill_tagged_out_memory
 17      end
 18   EXCEPTIONS
 19      undefine is_equal, out, fill_tagged_out_memory
 20      end
 21
 22feature {ANY}
 23   set_i
 24         -- Set Current to the imaginary unit
 25      do
 26         real := real.zero
 27         imaginary := imaginary.one
 28      end
 29
 30   set, set_cartesian (a_real_part, an_imaginary_part: A_SIZE)
 31      do
 32         real := a_real_part
 33         imaginary := an_imaginary_part
 34      end
 35
 36   set_polar (a_modulus, a_phase: A_SIZE)
 37      do
 38         real := a_modulus * a_phase.cos
 39         imaginary := a_modulus * a_phase.sin
 40         not_yet_implemented
 41      end
 42
 43feature {ANY}
 44   infix "+" (other: like Current): like Current
 45      do
 46         Result.set(real + other.real, imaginary + other.imaginary)
 47      end
 48
 49   infix "-" (other: like Current): like Current
 50      do
 51         Result.set(real - other.real, imaginary - other.imaginary)
 52      end
 53
 54   infix "*" (other: like Current): like Current
 55      do
 56         Result.set(real * other.real - imaginary * other.imaginary, imaginary * other.real + real * other.imaginary)
 57      end
 58
 59   infix "/" (other: like Current): like Current
 60      local
 61         den: A_SIZE
 62      do
 63         den := other.squared_modulus
 64         Result.set(real * other.real - imaginary * other.imaginary, imaginary * other.real + real * other.imaginary)
 65      end
 66
 67   infix "^" (e: INTEGER): like Current
 68      local
 69         ci, ni: INTEGER
 70      do
 71         -- current index and index of the next iteration
 72         from
 73            Result := Current
 74            ci := 1
 75            ni := 2
 76         until
 77            ni > e
 78         loop
 79            Result := Result * Result
 80            ci := ni
 81            ni := ni * 2
 82         end
 83
 84         from
 85         until
 86            ci = e
 87         loop
 88            Result := Result * Current
 89            ci := ci + 1
 90         end
 91      end
 92
 93   prefix "+": like Current
 94      do
 95         Result := Current
 96      end
 97
 98   prefix "-": like Current
 99      do
100         Result.set(-real, -imaginary)
101      end
102
103   divisible (other: like Current): BOOLEAN
104      do
105         Result := other /= zero
106      end
107
108   hash_code: INTEGER
109      do
110         Result := (real + imaginary).hash_code
111         -- Note: it is debatable if such an hash code implementation is actually useful.
112      end
113
114   real_sign: INTEGER_8
115      do
116         Result := real.sign
117      end
118
119   sign: like Current
120      require
121         not is_zero
122      local
123         coeff: A_SIZE
124      do
125         -- See http://en.wikipedia.org/wiki/Sign_function sign is NOT an INTEGER_8 for a complex but like Current!
126         -- It could be naively implemented with
127         Result.set_polar(coeff.one, phase)
128         -- but it may be implemented in a better way.
129      end
130
131   is_zero: BOOLEAN
132      do
133         Result := real ~= real.zero and imaginary ~= real.zero
134      end
135
136   zero: like Current
137      do
138         Result.set(real.zero, imaginary.zero)
139      end
140
141   one: like Current
142      do
143         Result.set(real.one, imaginary.zero)
144      end
145
146   i: like Current
147         -- Imaginary unit
148      do
149         Result.set_i
150      end
151
152   is_equal (other: like Current): BOOLEAN
153      do
154         Result := real = other.real and then imaginary = other.imaginary
155      end
156
157   is_near_equal, infix "~=" (other: like Current): BOOLEAN
158      do
159         debug
160            print(&Current + " ~= " + &other + "%N")
161         end
162         Result := real ~= other.real and imaginary ~= other.imaginary
163      end
164
165   conjugate: like Current
166      do
167         Result.set(real, -imaginary)
168      end
169
170feature {ANY} -- Cartesian representation
171   real, imaginary: A_SIZE
172
173feature {ANY} -- Polar representation
174   modulus: A_SIZE
175      do
176         Result := squared_modulus.sqrt
177      ensure
178         non_negative: Result.sign /= -1
179      end
180
181   phase: A_SIZE
182      require
183         not is_zero
184      do
185         not_yet_implemented
186         -- Pi is not converted automatically to A_SIZE
187         -- inspect real.sign
188         -- when  1 then Result := imaginary.atan2(real) -- same as (imaginary/real).atan
189         -- when -1 then
190         --     if imaginary.sign = -1 then Result := imaginary.atan2(real) + Pi
191         --     else Result := imaginary.atan2(real) - Pi
192         --     end
193         -- else
194         --     inspect imaginary.sign
195         --     when  1 then Result :=  Pi/2.0
196         --     when -1 then Result := -Pi/2.0
197         --     when  0 then raise_exception(Precondition)
198         --     end
199         -- end
200      end
201
202   squared_modulus: A_SIZE
203      do
204         Result := real * real + imaginary * imaginary
205         -- Note: NUMERIC does not have infix "^" (an_exponent: INTEGER): like Current...
206      ensure
207         non_negative: Result.sign /= -1
208      end
209
210feature {ANY} -- Object Printing:
211   out: STRING
212         -- do
213         --    Result := "("
214         --    real.append_in(Result)
215         --    Result.append(once ", ")
216         --    imaginary.append_in(Result)
217         --    Result.append_character(')')
218      local
219         real_digits, imaginary_digits: INTEGER
220      do
221         -- This is a far and large heuristic way to compute significant decimal digits of floating point number
222         real_digits := real.mantissa_bits.to_integer_32 // 3
223         imaginary_digits := imaginary.mantissa_bits.to_integer_32 // 3
224         create Result.with_capacity(real_digits + imaginary_digits + 6)
225         Result.append(once "(")
226         real.append_in_scientific(Result, real_digits)
227         Result.append(once ", ")
228         imaginary.append_in_scientific(Result, imaginary_digits)
229         Result.append(once ")")
230      end
231
232   fill_tagged_out_memory
233      do
234         tagged_out_memory.append("real, ")
235         real.fill_tagged_out_memory
236         tagged_out_memory.append(" imaginary, ")
237         imaginary.fill_tagged_out_memory
238      end
239
240end -- class COMPLEX_GENERAL
241--
242-- Copyright (C) 2011-2017: by all the people cited in the AUTHORS file.
243--
244-- Permission is hereby granted, free of charge, to any person obtaining a copy
245-- of this software and associated documentation files (the "Software"), to deal
246-- in the Software without restriction, including without limitation the rights
247-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
248-- copies of the Software, and to permit persons to whom the Software is
249-- furnished to do so, subject to the following conditions:
250--
251-- The above copyright notice and this permission notice shall be included in
252-- all copies or substantial portions of the Software.
253--
254-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
255-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
256-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
257-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
258-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
259-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
260-- THE SOFTWARE.