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