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