1 /*
  2     Copyright 2008,2009
  3         Matthias Ehmann,
  4         Michael Gerhaeuser,
  5         Carsten Miller,
  6         Bianca Valentin,
  7         Alfred Wassermann,
  8         Peter Wilfahrt
  9 
 10     This file is part of JSXGraph.
 11 
 12     JSXGraph is free software: you can redistribute it and/or modify
 13     it under the terms of the GNU Lesser General Public License as published by
 14     the Free Software Foundation, either version 3 of the License, or
 15     (at your option) any later version.
 16 
 17     JSXGraph is distributed in the hope that it will be useful,
 18     but WITHOUT ANY WARRANTY; without even the implied warranty of
 19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20     GNU Lesser General Public License for more details.
 21 
 22     You should have received a copy of the GNU Lesser General Public License
 23     along with JSXGraph.  If not, see <http://www.gnu.org/licenses/>.
 24 */
 25 
 26 
 27 /**
 28  * @fileoverview A class for complex arithmetics JXG.Complex is defined in this
 29  * file. Also a namespace JXG.C is included to provide instance-independent
 30  * arithmetic functions.
 31  * @author graphjs
 32  */
 33 
 34 /**
 35  * Creates a new complex number.
 36  * @class This class is for calculating with complex numbers.
 37  * @param [x=0] Real part of the resulting complex number.
 38  * @param [y=0] Imaginary part of the resulting complex number.
 39  * @returns An object representing the complex number <tt>x + iy</tt>.
 40  */
 41 JXG.Complex = function(/** number */ x, /** number */ y) {
 42 	/**
 43 	 * This property is only to signalize that this object is of type JXG.Complex. Only
 44 	 * used internally to distinguish between normal JavaScript numbers and JXG.Complex numbers.
 45 	 * @type boolean
 46 	 * @default true
 47 	 * @private
 48 	 */
 49     this.isComplex = true;
 50     
 51     if (typeof x == 'undefined') {
 52         x = 0;
 53     }
 54     if (typeof y == 'undefined') {
 55         y = 0;
 56     }
 57 
 58     /* is the first argument a complex number? if it is,
 59      * extract real and imaginary part. */
 60     if (x.isComplex) {
 61         y = x.imaginary;
 62         x = x.real;
 63     }
 64 
 65     /**
 66      * Real part of the complex number.
 67      * @type number
 68      * @default 0
 69      */
 70     this.real = x;
 71 
 72     /**
 73      * Imaginary part of the complex number.
 74      * @type number
 75      * @default 0
 76      */
 77     this.imaginary = y;
 78 
 79     /**
 80      * Absolute value in the polar form of the complex number. Currently unused.
 81      * @type number
 82      */
 83     this.absval = 0;
 84 
 85     /**
 86      * Angle value in the polar form of the complex number. Currently unused.
 87      * @type number
 88      */
 89     this.angle = 0;
 90 };
 91 
 92 JXG.extend(JXG.Complex.prototype, /** @lends JXG.Complex.prototype */ {
 93     /**
 94      * Converts a complex number into a string.
 95      * @return Formatted string containing the complex number in human readable form (algebraic form).
 96      */
 97     toString: function() /** string */{
 98         return '' + this.real + ' + ' + this.imaginary + 'i';
 99     },
100 
101     /**
102      * Add another complex number to this complex number.
103      * @param c A JavaScript number or a JXG.Complex object to be added to the current object.
104      */
105     add: function(/** JXG.Complex,number */ c) /** undefined */ {
106         if(typeof c == 'number') {
107             this.real += c;
108         } else {
109             this.real += c.real;
110             this.imaginary += c.imaginary;
111         }
112     },
113 
114     /**
115      * Subtract another complex number from this complex number.
116      * @param c A JavaScript number or a JXG.Complex object to subtract from the current object.
117      */
118     sub: function(/** JXG.Complex,number */ c) /** undefined */{
119         if(typeof c == 'number') {
120             this.real -= c;
121         } else {
122             this.real -= c.real;
123             this.imaginary -= c.imaginary;
124         }
125     },
126 
127     /**
128      * Multiply another complex number to this complex number.
129      * @param c A JavaScript number or a JXG.Complex object to
130      * multiply with the current object.
131      */
132     mult: function(/** JXG.Complex,number */ c) /** undefined */{
133         var re, im;
134         if(typeof c == 'number') {
135             this.real *= c;
136             this.imaginary *= c;
137         } else {
138             re = this.real;
139             im = this.imaginary;
140             //  (a+ib)(x+iy) = ax-by + i(xb+ay)
141             this.real = re*c.real - im*c.imaginary;
142             this.imaginary = re*c.imaginary + im*c.real;
143         }
144     },
145 
146     /**
147      * Divide this complex number by the given complex number.
148      * @param c A JavaScript number or a JXG.Complex object to
149      * divide the current object by.
150      */
151     div: function(/** JXG.Complex,number */ c) /** undefined */{
152         var denom, im, re;
153 
154         if(typeof c == 'number') {
155             if(Math.abs(c) < Math.eps) {
156                 this.real = Infinity;
157                 this.imaginary = Infinity;
158                 
159                 return;
160             }
161             this.real /= c;
162             this.imaginary /= c;
163         } else {
164             //  (a+ib)(x+iy) = ax-by + i(xb+ay)
165             if( (Math.abs(c.real) < Math.eps) && (Math.abs(c.imaginary) < Math.eps) ){
166                 this.real = Infinity;
167                 this.imaginary = Infinity;
168 
169                 return;
170             }
171 
172             denom = c.real*c.real + c.imaginary*c.imaginary;
173 
174             re = this.real;
175             im = this.imaginary;
176             this.real = (re*c.real + im*c.imaginary)/denom;
177             this.imaginary = (im*c.real - re*c.imaginary)/denom;
178         }
179     },
180 
181     /**
182      * Conjugate a complex number in place.
183      * @param c A JavaScript number or a JXG.Complex object 
184      */
185     conj: function() /** undefined */ {
186         this.imaginary *= -1;
187     }
188 });
189 
190 /**
191  * @description
192  * JXG.C is the complex number (name)space. It provides functions to calculate with
193  * complex numbers (defined in {@link JXG.Complex}). With this namespace you don't have to modify
194  * your existing complex numbers, e.g. to add two complex numbers:
195  * <pre class="code">   var z1 = new JXG.Complex(1, 0);
196  *    var z2 = new JXG.Complex(0, 1);
197  *    z = JXG.C.add(z1, z1);</pre>
198  * z1 and z2 here remain unmodified. With the object oriented approach above this
199  * section the code would look like:
200  * <pre class="code">   var z1 = new JXG.Complex(1, 0);
201  *    var z2 = new JXG.Complex(0, 1);
202  *    var z = new JXG.Complex(z1);
203  *    z.add(z2);</pre>
204  * @namespace Namespace for the complex number arithmetic functions.
205  */
206 JXG.C = {};
207 
208 /**
209  * Add two (complex) numbers z1 and z2 and return the result as a (complex) number.
210  * @param z1 Summand
211  * @param z2 Summand
212  * @return A complex number equal to the sum of the given parameters.
213  */
214 JXG.C.add = function(/** JXG.Complex,number */ z1, /** JXG.Complex,number */ z2) /** JXG.Complex */{
215     var z = new JXG.Complex(z1);
216     z.add(z2);
217     return z;
218 };
219 
220 /**
221  * Subtract two (complex) numbers z1 and z2 and return the result as a (complex) number.
222  * @param z1 Minuend
223  * @param z2 Subtrahend
224  * @return A complex number equal to the difference of the given parameters.
225  */
226 JXG.C.sub = function(/** JXG.Complex,number */ z1, /** JXG.Complex,number */ z2) /** JXG.Complex */{
227     var z = new JXG.Complex(z1);
228     z.sub(z2);
229     return z;
230 };
231 
232 /**
233  * Multiply two (complex) numbers z1 and z2 and return the result as a (complex) number.
234  * @param z1 Factor
235  * @param z2 Factor
236  * @return A complex number equal to the product of the given parameters.
237  */
238 JXG.C.mult = function(/** JXG.Complex,number */ z1, /** JXG.Complex,number */ z2) /** JXG.Complex */{
239     var z = new JXG.Complex(z1);
240     z.mult(z2);
241     return z;
242 };
243 
244 /**
245  * Divide two (complex) numbers z1 and z2 and return the result as a (complex) number.
246  * @param z1 Dividend
247  * @param z2 Divisor
248  * @return A complex number equal to the quotient of the given parameters.
249  */
250 JXG.C.div = function(/** JXG.Complex,number */ z1, /** JXG.Complex,number */ z2) /** JXG.Complex */{
251     var z = new JXG.Complex(z1);
252     z.div(z2);
253     return z;
254 };
255 
256 /**
257  * Conjugate a complex number and return the result.
258  * @param z1 Complex number
259  * @return A complex number equal to the conjugate of the given parameter.
260  */
261 JXG.C.conj = function(/** JXG.Complex,number */ z1) /** JXG.Complex */{
262     var z = new JXG.Complex(z1);
263     z.conj();
264     return z;
265 };
266 
267 /**
268  * Absolute value of a complex number.
269  * @param z1 Complex number
270  * @return real number equal to the absolute value of the given parameter.
271  */
272 JXG.C.abs = function(/** JXG.Complex,number */ z1) /** JXG.Complex */{
273     var z = new JXG.Complex(z1);
274     z.conj();
275     z.mult(z1);
276     return Math.sqrt(z.real);
277 };
278 
279