      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