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