1 /*
  2     Copyright 2008-2026
  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 import Mat from "./math.js";
 44 
 45 /**
 46  * Creates a new complex number. See also {@link JXG.C}.
 47  * @class This class is for calculating with complex numbers, see also {@link JXG.C} for more methods.
 48  * @constructor
 49  * @param {Number} [x=0] Real part.
 50  * @param {Number} [y=0] Imaginary part.
 51  * @see JXG.C
 52  */
 53 JXG.Complex = function (x, y) {
 54     /**
 55      * This property is only to signalize that this object is of type JXG.Complex. Only
 56      * used internally to distinguish between normal JavaScript numbers and JXG.Complex numbers.
 57      * @type Boolean
 58      * @default true
 59      * @private
 60      */
 61     this.isComplex = true;
 62 
 63     /* is the first argument a complex number? if it is,
 64      * extract real and imaginary part. */
 65     if (x && x.isComplex) {
 66         y = x.imaginary;
 67         x = x.real;
 68     }
 69 
 70     /**
 71      * Real part of the complex number.
 72      * @type Number
 73      * @default 0
 74      */
 75     this.real = x || 0;
 76 
 77     /**
 78      * Imaginary part of the complex number.
 79      * @type Number
 80      * @default 0
 81      */
 82     this.imaginary = y || 0;
 83 
 84     // /**
 85     //  * Absolute value in the polar form of the complex number. Currently unused.
 86     //  * @type Number
 87     //  */
 88     // this.absval = 0;
 89 
 90     // /**
 91     //  * Angle value in the polar form of the complex number. Currently unused.
 92     //  * @type Number
 93     //  */
 94     // this.angle = 0;
 95 };
 96 
 97 JXG.extend(
 98     JXG.Complex.prototype,
 99     /** @lends JXG.Complex.prototype */ {
100         /**
101          * Converts a complex number into a string.
102          * @param {Number} [digits=null] number of digits if not null
103          * @returns {String} Formatted string containing the complex number in human readable form (algebraic form).
104          */
105         toString: function (digits) {
106             var op = (this.imaginary < 0) ? ' - ' : ' + ',
107                 im = Math.abs(this.imaginary);
108 
109             if (digits !== null) {
110                 return this.real.toFixed(digits) + op + im.toFixed(digits) + 'i';
111             }
112             return this.real + op + im + 'i';
113         },
114 
115         /**
116          * Return real and imaginary parts of a complex number as array of length 2.
117          * @returns [complex.real,complex.imaginary];
118          */
119         toArray: function() {
120             return [this.real, this.imaginary];
121         },
122 
123         /**
124          * Add another complex number to this complex number.
125          * @param {JXG.Complex|Number} c A JavaScript number or a JXG.Complex object to be added to the current object.
126          * @returns {JXG.Complex} Reference to this complex number
127          */
128         add: 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          * Subtract another complex number from this complex number.
141          * @param {JXG.Complex|Number} c A JavaScript number or a JXG.Complex object to subtract from the current object.
142          * @returns {JXG.Complex} Reference to this complex number
143          */
144         sub: function (c) {
145             if (Type.isNumber(c)) {
146                 this.real -= c;
147             } else {
148                 this.real -= c.real;
149                 this.imaginary -= c.imaginary;
150             }
151 
152             return this;
153         },
154 
155         /**
156          * Multiply another complex number to this complex number.
157          * @param {JXG.Complex|Number} c A JavaScript number or a JXG.Complex object to
158          * multiply with the current object.
159          * @returns {JXG.Complex} Reference to this complex number
160          */
161         mult: function (c) {
162             var re, im, c_re, c_im;
163 
164             if (Type.isNumber(c)) {
165                 this.real *= c;
166                 this.imaginary *= c;
167             } else {
168                 re = this.real;
169                 im = this.imaginary;
170                 c_re = c.real;
171                 c_im = c.imaginary;
172 
173                 //  (a+ib)(x+iy) = ax-by + i(xb+ay)
174                 // this.real = re * c.real - im * c.imaginary;
175                 // this.imaginary = re * c.imaginary + im * c.real;
176                 this.real = re * c_re - im * c_im;
177                 this.imaginary = re * c_im + im * c_re;
178             }
179 
180             return this;
181         },
182 
183         /**
184          * Divide this complex number by the given complex number.
185          * @param {JXG.Complex|Number} c A JavaScript number or a JXG.Complex object to
186          * divide the current object by.
187          * @returns {JXG.Complex} Reference to this complex number
188          */
189         div: function (c) {
190             var denom, im, re, c_re, c_im,
191                 eps = Mat.eps * Mat.eps;
192 
193             if (Type.isNumber(c)) {
194                 if (Math.abs(c) < Mat.eps) {
195                     this.real = Infinity;
196                     this.imaginary = Infinity;
197 
198                     return this;
199                 }
200 
201                 this.real /= c;
202                 this.imaginary /= c;
203             } else {
204                 //  (a+ib)(x+iy) = ax-by + i(xb+ay)
205                 c_re = c.real;
206                 c_im = c.imaginary;
207                 if (Math.abs(c_re) < eps && Math.abs(c_im) < eps) {
208                     this.real = Infinity;
209                     this.imaginary = Infinity;
210 
211                     return this;
212                 }
213 
214                 denom = c_re * c_re + c_im * c_im;
215 
216                 re = this.real;
217                 im = this.imaginary;
218                 this.real = (re * c_re + im * c_im) / denom;
219                 this.imaginary = (im * c_re - re * c_im) / denom;
220             }
221 
222             return this;
223         },
224 
225         /**
226          * Conjugate a complex number in place.
227          * @returns {JXG.Complex} Reference to this complex number
228          */
229         conj: function () {
230             this.imaginary *= -1;
231 
232             return this;
233         },
234 
235         /**
236          * Absolute value in the polar form, i.e. |z| of the complex number z.
237          * @returns Number
238          */
239         abs: function() {
240             var x = this.real,
241                 y = this.imaginary;
242             return Math.sqrt(x * x + y * y);
243         },
244 
245         /**
246          * Angle value in the polar form of the complex number (in radians).
247          * @returns Number
248          */
249         angle: function() {
250             return Math.atan2(this.imaginary, this.real);
251         }
252 
253     }
254 );
255 
256 /**
257  * @namespace Namespace for the complex number arithmetic functions, see also {@link JXG.Complex}.
258  * @description
259  * JXG.C is the complex number (name)space. It provides functions to calculate with
260  * complex numbers (defined in {@link JXG.Complex}). With this namespace you don't have to modify
261  * your existing complex numbers, e.g. to add two complex numbers:
262  * <pre class="code">   var z1 = new JXG.Complex(1, 0);
263  *    var z2 = new JXG.Complex(0, 1);
264  *    z = JXG.C.add(z1, z1);</pre>
265  * z1 and z2 here remain unmodified. With the object oriented approach above this
266  * section the code would look like:
267  * <pre class="code">
268  *    var z1 = new JXG.Complex(1, 0);
269  *    var z2 = new JXG.Complex(0, 1);
270  *    var z = new JXG.Complex(z1);
271  *    z.add(z2);</pre>
272  * @see JXG.Complex
273  */
274 JXG.C = {};
275 
276 /**
277  * Add two (complex) numbers z1 and z2 and return the result as a (complex) number.
278  * @param {JXG.Complex|Number} z1 Summand
279  * @param {JXG.Complex|Number} z2 Summand
280  * @returns {JXG.Complex} A complex number equal to the sum of the given parameters.
281  */
282 JXG.C.add = function (z1, z2) {
283     var z = new JXG.Complex(z1);
284     z.add(z2);
285     return z;
286 };
287 
288 /**
289  * Subtract two (complex) numbers z1 and z2 and return the result as a (complex) number.
290  * @param {JXG.Complex|Number} z1 Minuend
291  * @param {JXG.Complex|Number} z2 Subtrahend
292  * @returns {JXG.Complex} A complex number equal to the difference of the given parameters.
293  */
294 JXG.C.sub = function (z1, z2) {
295     var z = new JXG.Complex(z1);
296     z.sub(z2);
297     return z;
298 };
299 
300 /**
301  * Multiply two (complex) numbers z1 and z2 and return the result as a (complex) number.
302  * @param {JXG.Complex|Number} z1 Factor
303  * @param {JXG.Complex|Number} z2 Factor
304  * @returns {JXG.Complex} A complex number equal to the product of the given parameters.
305  */
306 JXG.C.mult = function (z1, z2) {
307     var z = new JXG.Complex(z1);
308     z.mult(z2);
309     return z;
310 };
311 
312 /**
313  * Divide two (complex) numbers z1 and z2 and return the result as a (complex) number.
314  * @param {JXG.Complex|Number} z1 Dividend
315  * @param {JXG.Complex|Number} z2 Divisor
316  * @returns {JXG.Complex} A complex number equal to the quotient of the given parameters.
317  */
318 JXG.C.div = function (z1, z2) {
319     var z = new JXG.Complex(z1);
320     z.div(z2);
321     return z;
322 };
323 
324 /**
325  * Conjugate a complex number and return the result.
326  * @param {JXG.Complex|Number} z1 Complex number
327  * @returns {JXG.Complex} A complex number equal to the conjugate of the given parameter.
328  */
329 JXG.C.conj = function (z1) {
330     var z = new JXG.Complex(z1);
331     z.conj();
332     return z;
333 };
334 
335 /**
336  * Absolute value of a complex number.
337  * @param {JXG.Complex|Number} z1 Complex number
338  * @returns {Number} real number equal to the absolute value of the given parameter.
339  */
340 JXG.C.abs = function (z1) {
341     var z = new JXG.Complex(z1);
342     // z.conj();
343     // z.mult(z1);
344     // return Math.sqrt(z.real);
345     return z.abs();
346 };
347 
348 /**
349  * Angle of a complex number (in radians).
350  * @param {JXG.Complex|Number} z1 Complex number
351  * @returns {Number} real number equal to the angle value of the given parameter.
352  */
353 JXG.C.angle = function (z1) {
354     var z = new JXG.Complex(z1);
355     return z.angle();
356 };
357 
358 /**
359  * Create copy of complex number.
360  *
361  * @param {JXG.Complex|Number} z
362  * @returns {JXG.Complex}
363  */
364 JXG.C.copy = function(z) {
365     return new JXG.Complex(z);
366 };
367 
368 JXG.Complex.C = JXG.C;
369 
370 export default JXG.Complex;
371