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