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