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          * @returns {String} Formatted string containing the complex number in human readable form (algebraic form).
103          */
104         toString: function () {
105             return this.real + " + " + this.imaginary + 'i';
106         },
107 
108         /**
109          * Add another complex number to this complex number.
110          * @param {JXG.Complex|Number} c A JavaScript number or a JXG.Complex object to be added to the current object.
111          * @returns {JXG.Complex} Reference to this complex number
112          */
113         add: function (c) {
114             if (Type.isNumber(c)) {
115                 this.real += c;
116             } else {
117                 this.real += c.real;
118                 this.imaginary += c.imaginary;
119             }
120 
121             return this;
122         },
123 
124         /**
125          * Subtract another complex number from this complex number.
126          * @param {JXG.Complex|Number} c A JavaScript number or a JXG.Complex object to subtract from the current object.
127          * @returns {JXG.Complex} Reference to this complex number
128          */
129         sub: function (c) {
130             if (Type.isNumber(c)) {
131                 this.real -= c;
132             } else {
133                 this.real -= c.real;
134                 this.imaginary -= c.imaginary;
135             }
136 
137             return this;
138         },
139 
140         /**
141          * Multiply another complex number to this complex number.
142          * @param {JXG.Complex|Number} c A JavaScript number or a JXG.Complex object to
143          * multiply with the current object.
144          * @returns {JXG.Complex} Reference to this complex number
145          */
146         mult: function (c) {
147             var re, im;
148 
149             if (Type.isNumber(c)) {
150                 this.real *= c;
151                 this.imaginary *= c;
152             } else {
153                 re = this.real;
154                 im = this.imaginary;
155 
156                 //  (a+ib)(x+iy) = ax-by + i(xb+ay)
157                 this.real = re * c.real - im * c.imaginary;
158                 this.imaginary = re * c.imaginary + im * c.real;
159             }
160 
161             return this;
162         },
163 
164         /**
165          * Divide this complex number by the given complex number.
166          * @param {JXG.Complex|Number} c A JavaScript number or a JXG.Complex object to
167          * divide the current object by.
168          * @returns {JXG.Complex} Reference to this complex number
169          */
170         div: function (c) {
171             var denom, im, re;
172 
173             if (Type.isNumber(c)) {
174                 if (Math.abs(c) < Mat.eps) {
175                     this.real = Infinity;
176                     this.imaginary = Infinity;
177 
178                     return this;
179                 }
180 
181                 this.real /= c;
182                 this.imaginary /= c;
183             } else {
184                 //  (a+ib)(x+iy) = ax-by + i(xb+ay)
185                 if (Math.abs(c.real) < Mat.eps && Math.abs(c.imaginary) < Mat.eps) {
186                     this.real = Infinity;
187                     this.imaginary = Infinity;
188 
189                     return this;
190                 }
191 
192                 denom = c.real * c.real + c.imaginary * c.imaginary;
193 
194                 re = this.real;
195                 im = this.imaginary;
196                 this.real = (re * c.real + im * c.imaginary) / denom;
197                 this.imaginary = (im * c.real - re * c.imaginary) / denom;
198             }
199 
200             return this;
201         },
202 
203         /**
204          * Conjugate a complex number in place.
205          * @returns {JXG.Complex} Reference to this complex number
206          */
207         conj: function () {
208             this.imaginary *= -1;
209 
210             return this;
211         },
212 
213         /**
214          * Absolute value in the polar form, i.e. |z| of the complex number z.
215          * @returns Number
216          */
217         abs: function() {
218             var x = this.real,
219                 y = this.imaginary;
220             return Math.sqrt(x * x + y * y);
221         },
222 
223         /**
224          * Angle value in the polar form of the complex number (in radians).
225          * @returns Number
226          */
227         angle: function() {
228             return Math.atan2(this.imaginary, this.real);
229         }
230 
231     }
232 );
233 
234 /**
235  * @namespace Namespace for the complex number arithmetic functions, see also {@link JXG.Complex}.
236  * @description
237  * JXG.C is the complex number (name)space. It provides functions to calculate with
238  * complex numbers (defined in {@link JXG.Complex}). With this namespace you don't have to modify
239  * your existing complex numbers, e.g. to add two complex numbers:
240  * <pre class="code">   var z1 = new JXG.Complex(1, 0);
241  *    var z2 = new JXG.Complex(0, 1);
242  *    z = JXG.C.add(z1, z1);</pre>
243  * z1 and z2 here remain unmodified. With the object oriented approach above this
244  * section the code would look like:
245  * <pre class="code">
246  *    var z1 = new JXG.Complex(1, 0);
247  *    var z2 = new JXG.Complex(0, 1);
248  *    var z = new JXG.Complex(z1);
249  *    z.add(z2);</pre>
250  * @see JXG.Complex
251  */
252 JXG.C = {};
253 
254 /**
255  * Add two (complex) numbers z1 and z2 and return the result as a (complex) number.
256  * @param {JXG.Complex|Number} z1 Summand
257  * @param {JXG.Complex|Number} z2 Summand
258  * @returns {JXG.Complex} A complex number equal to the sum of the given parameters.
259  */
260 JXG.C.add = function (z1, z2) {
261     var z = new JXG.Complex(z1);
262     z.add(z2);
263     return z;
264 };
265 
266 /**
267  * Subtract two (complex) numbers z1 and z2 and return the result as a (complex) number.
268  * @param {JXG.Complex|Number} z1 Minuend
269  * @param {JXG.Complex|Number} z2 Subtrahend
270  * @returns {JXG.Complex} A complex number equal to the difference of the given parameters.
271  */
272 JXG.C.sub = function (z1, z2) {
273     var z = new JXG.Complex(z1);
274     z.sub(z2);
275     return z;
276 };
277 
278 /**
279  * Multiply two (complex) numbers z1 and z2 and return the result as a (complex) number.
280  * @param {JXG.Complex|Number} z1 Factor
281  * @param {JXG.Complex|Number} z2 Factor
282  * @returns {JXG.Complex} A complex number equal to the product of the given parameters.
283  */
284 JXG.C.mult = function (z1, z2) {
285     var z = new JXG.Complex(z1);
286     z.mult(z2);
287     return z;
288 };
289 
290 /**
291  * Divide two (complex) numbers z1 and z2 and return the result as a (complex) number.
292  * @param {JXG.Complex|Number} z1 Dividend
293  * @param {JXG.Complex|Number} z2 Divisor
294  * @returns {JXG.Complex} A complex number equal to the quotient of the given parameters.
295  */
296 JXG.C.div = function (z1, z2) {
297     var z = new JXG.Complex(z1);
298     z.div(z2);
299     return z;
300 };
301 
302 /**
303  * Conjugate a complex number and return the result.
304  * @param {JXG.Complex|Number} z1 Complex number
305  * @returns {JXG.Complex} A complex number equal to the conjugate of the given parameter.
306  */
307 JXG.C.conj = function (z1) {
308     var z = new JXG.Complex(z1);
309     z.conj();
310     return z;
311 };
312 
313 /**
314  * Absolute value of a complex number.
315  * @param {JXG.Complex|Number} z1 Complex number
316  * @returns {Number} real number equal to the absolute value of the given parameter.
317  */
318 JXG.C.abs = function (z1) {
319     var z = new JXG.Complex(z1);
320     // z.conj();
321     // z.mult(z1);
322     // return Math.sqrt(z.real);
323     return z.abs();
324 };
325 
326 /**
327  * Angle of a complex number (in radians).
328  * @param {JXG.Complex|Number} z1 Complex number
329  * @returns {Number} real number equal to the angle value of the given parameter.
330  */
331 JXG.C.angle = function (z1) {
332     var z = new JXG.Complex(z1);
333     return z.angle();
334 };
335 
336 /**
337  * Create copy of complex number.
338  *
339  * @param {JXG.Complex|Number} z
340  * @returns {JXG.Complex}
341  */
342 JXG.C.copy = function(z) {
343     return new JXG.Complex(z);
344 };
345 
346 JXG.Complex.C = JXG.C;
347 
348 export default JXG.Complex;
349