UNPKG

nowjs-core

Version:

NowCanDo Javascript Core [nowjs-core] is a library written by TypeScript code maintains under Apache 2.0 licence

569 lines (568 loc) 17.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const index_1 = require("./index"); function cosh(x) { return (Math.exp(x) + Math.exp(-x)) * 0.5; } function sinh(x) { return (Math.exp(x) - Math.exp(-x)) * 0.5; } function hypot(x, y) { let a = Math.abs(x); let b = Math.abs(y); if (a < 3000 && b < 3000) { return Math.sqrt(a * a + b * b); } if (a < b) { a = b; b = x / y; } else { b = y / x; } return a * Math.sqrt(1 + b * b); } function logHypot(a, b) { const _a = Math.abs(a); const _b = Math.abs(b); if (a === 0) { return Math.log(_b); } if (b === 0) { return Math.log(_a); } if (_a < 3000 && _b < 3000) { return Math.log(a * a + b * b) * 0.5; } return Math.log(a / Math.cos(Math.atan2(b, a))); } function parser_exit() { throw SyntaxError('Invalid Param'); } class ComplexNumber { constructor(a, b) { this.re = 0; this.im = 0; this.abss = 0; this.arg = 0; this.r = 0; this.phi = 0; if (typeof a === 'number') { this.re = a; this.im = b; } else if (!(a instanceof ComplexNumber)) { const compl = ComplexNumber.parse(a, b); this.re = compl.re; this.im = compl.im; } else if (a instanceof ComplexNumber) { this.re = a.re; this.im = a.im; } } static parse(a, b) { const result = new ComplexNumber(0, 0); if (a === undefined || a === null) { result.re = 0; result.im = 0; } else if (b !== undefined && typeof a === 'number') { result.re = a; result.im = b; } else { if (a instanceof ComplexNumber) { if (a.re && a.im) { result.re = a.re; result.im = a.im; } else if (a.abs !== undefined && a.arg !== undefined) { result.re = a.abss * Math.cos(a.arg); result.im = a.abss * Math.sin(a.arg); } else if (a.r !== undefined && a.phi !== undefined) { result.re = a.r * Math.cos(a.phi); result.im = a.r * Math.sin(a.phi); } else if (Array.isArray(a) && a.length === 2) { result.re = a[0]; result.im = a[1]; } else { parser_exit(); } } else if (typeof a === 'number') { result.im = 0; result.re = a; } if (typeof a === 'string') { result.im = result.re = 0; const tokens = a.match(/\d+\.?\d*e[+-]?\d+|\d+\.?\d*|\.\d+|./g); let plus = 1; let minus = 0; if (tokens === null) { parser_exit(); } for (let i = 0; i < tokens.length; i++) { const c = tokens[i]; if (c === ' ' || c === '\t' || c === '\n') { } else if (c === '+') { plus++; } else if (c === '-') { minus++; } else if (c === 'i' || c === 'I') { if (plus + minus === 0) { parser_exit(); } if (tokens[i + 1] !== ' ' && !isNaN(tokens[i + 1])) { result.im += parseFloat((minus % 2 ? '-' : '') + tokens[i + 1]); i++; } else { result.im += parseFloat((minus % 2 ? '-' : '') + '1'); } plus = minus = 0; } else { if (plus + minus === 0 || isNaN(c)) { parser_exit(); } if (tokens[i + 1] === 'i' || tokens[i + 1] === 'I') { result.im += parseFloat((minus % 2 ? '-' : '') + c); i++; } else { result.re += parseFloat((minus % 2 ? '-' : '') + c); } plus = minus = 0; } } if (plus + minus > 0) { parser_exit(); } } } return result; } get Real() { return this.re; } get Imaginary() { return this.im; } sign() { const abs = this.magnitude(); return new ComplexNumber(this.re / abs, this.im / abs); } add(a, b) { const P = ComplexNumber.parse(a, b); return new ComplexNumber(this.re + P.re, this.im + P.im); } subtract(a, b) { const P = ComplexNumber.parse(a, b); return new ComplexNumber(this.re - P.re, this.im - P.im); } multiply(a, b) { const P = ComplexNumber.parse(a, b); if (P.im === 0 && this.im === 0) { return new ComplexNumber(this.re * P.re, 0); } return new ComplexNumber(this.re * P.re - this.im * P.im, this.re * P.im + this.im * P.re); } divide(aa, bb) { const P = ComplexNumber.parse(aa, bb); const a = this.re; const b = this.im; const c = P.re; const d = P.im; let t, x; if (0 === d) { if (0 === c) { return new ComplexNumber(a !== 0 ? a / 0 : 0, b !== 0 ? b / 0 : 0); } else { return new ComplexNumber(a / c, b / c); } } if (Math.abs(c) < Math.abs(d)) { x = c / d; t = c * x + d; return new ComplexNumber((a * x + b) / t, (b * x - a) / t); } else { x = d / c; t = d * x + c; return new ComplexNumber((a + b * x) / t, (b - a * x) / t); } } pow(aa, bb) { const P = ComplexNumber.parse(aa, bb); let a = this.re; let b = this.im; if (a === 0 && b === 0) { return ComplexNumber.ZERO; } if (P.im === 0) { if (b === 0 && a >= 0) { return new ComplexNumber(Math.pow(a, P.re), 0); } else if (a === 0) { switch (((P.re % 4) + 4) % 4) { case 0: return new ComplexNumber(Math.pow(b, P.re), 0); case 1: return new ComplexNumber(0, Math.pow(b, P.re)); case 2: return new ComplexNumber(-Math.pow(b, P.re), 0); case 3: return new ComplexNumber(0, -Math.pow(b, P.re)); } } } const arg = Math.atan2(b, a); const loh = logHypot(a, b); a = Math.exp(P.re * loh - P.im * arg); b = P.im * loh + P.re * arg; return new ComplexNumber(Math.floor(a * Math.cos(b)), Math.floor(a * Math.sin(b))); } sqrt() { const a = this.re; const b = this.im; const r = this.magnitude(); let re, im; if (a >= 0) { if (b === 0) { return new ComplexNumber(Math.sqrt(a), 0); } re = 0.5 * Math.sqrt(2.0 * (r + a)); } else { re = Math.abs(b) / Math.sqrt(2 * (r - a)); } if (a <= 0) { im = 0.5 * Math.sqrt(2.0 * (r - a)); } else { im = Math.abs(b) / Math.sqrt(2 * (r + a)); } return new ComplexNumber(re, b < 0 ? -im : im); } exp() { const tmp = Math.exp(this.re); if (this.im === 0) { } return new ComplexNumber(tmp * Math.cos(this.im), tmp * Math.sin(this.im)); } log() { const a = this.re; const b = this.im; if (b === 0 && a > 0) { } return new ComplexNumber(logHypot(a, b), Math.atan2(b, a)); } abs() { return hypot(this.re, this.im); } magnitude() { return hypot(this.re, this.im); } angle() { return Math.atan2(this.im, this.re); } sin() { const a = this.re; const b = this.im; return new ComplexNumber(Math.sin(a) * cosh(b), Math.cos(a) * sinh(b)); } cos() { const a = this.re; const b = this.im; return new ComplexNumber(Math.cos(a) * cosh(b), -Math.sin(a) * sinh(b)); } tan() { const a = 2 * this.re; const b = 2 * this.im; const d = Math.cos(a) + cosh(b); return new ComplexNumber(Math.sin(a) / d, sinh(b) / d); } cot() { const a = 2 * this.re; const b = 2 * this.im; const d = Math.cos(a) - cosh(b); return new ComplexNumber(-Math.sin(a) / d, sinh(b) / d); } sec() { const a = this.re; const b = this.im; const d = 0.5 * cosh(2 * b) + 0.5 * Math.cos(2 * a); return new ComplexNumber((Math.cos(a) * cosh(b)) / d, (Math.sin(a) * sinh(b)) / d); } csc() { const a = this.re; const b = this.im; const d = 0.5 * cosh(2 * b) - 0.5 * Math.cos(2 * a); return new ComplexNumber((Math.sin(a) * cosh(b)) / d, (-Math.cos(a) * sinh(b)) / d); } asin() { const a = this.re; const b = this.im; const t1 = new ComplexNumber(b * b - a * a + 1, -2 * a * b).sqrt(); const t2 = new ComplexNumber(t1.re - b, t1.im + a).log(); return new ComplexNumber(t2.im, -t2.re); } acos() { const a = this.re; const b = this.im; const t1 = new ComplexNumber(b * b - a * a + 1, -2 * a * b).sqrt(); const t2 = new ComplexNumber(t1.re - b, t1.im + a).log(); return new ComplexNumber(Math.PI / 2 - t2.im, t2.re); } atan() { const a = this.re; const b = this.im; if (a === 0) { if (b === 1) { return new ComplexNumber(0, Infinity); } if (b === -1) { return new ComplexNumber(0, -Infinity); } } const d = a * a + (1.0 - b) * (1.0 - b); const t1 = new ComplexNumber((1 - b * b - a * a) / d, (-2 * a) / d).log(); return new ComplexNumber(-0.5 * t1.im, 0.5 * t1.re); } acot() { const a = this.re; const b = this.im; if (b === 0) { return new ComplexNumber(Math.atan2(1, a), 0); } const d = a * a + b * b; return d !== 0 ? new ComplexNumber(a / d, -b / d).atan() : new ComplexNumber(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).atan(); } asec() { const a = this.re; const b = this.im; if (a === 0 && b === 0) { return new ComplexNumber(0, Infinity); } const d = a * a + b * b; return d !== 0 ? new ComplexNumber(a / d, -b / d).acos() : new ComplexNumber(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).acos(); } acsc() { const a = this.re; const b = this.im; if (a === 0 && b === 0) { return new ComplexNumber(Math.PI / 2, Infinity); } const d = a * a + b * b; return d !== 0 ? new ComplexNumber(a / d, -b / d).asin() : new ComplexNumber(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).asin(); } sinh() { const a = this.re; const b = this.im; return new ComplexNumber(sinh(a) * Math.cos(b), cosh(a) * Math.sin(b)); } cosh() { const a = this.re; const b = this.im; return new ComplexNumber(cosh(a) * Math.cos(b), sinh(a) * Math.sin(b)); } tanh() { const a = 2 * this.re; const b = 2 * this.im; const d = cosh(a) + Math.cos(b); return new ComplexNumber(sinh(a) / d, Math.sin(b) / d); } coth() { const a = 2 * this.re; const b = 2 * this.im; const d = cosh(a) - Math.cos(b); return new ComplexNumber(sinh(a) / d, -Math.sin(b) / d); } sech() { const a = this.re; const b = this.im; const d = Math.cos(2 * b) + cosh(2 * a); return new ComplexNumber((2 * cosh(a) * Math.cos(b)) / d, (-2 * sinh(a) * Math.sin(b)) / d); } csch() { const a = this.re; const b = this.im; const d = Math.cos(2 * b) - cosh(2 * a); return new ComplexNumber((-2 * sinh(a) * Math.cos(b)) / d, (2 * cosh(a) * Math.sin(b)) / d); } asinh() { let tmp = this.im; this.im = -this.re; this.re = tmp; const res = this.asin(); this.re = -this.im; this.im = tmp; tmp = res.re; res.re = -res.im; res.im = tmp; return res; } acosh() { let tmp; const res = this.acos(); if (res.im <= 0) { tmp = res.re; res.re = -res.im; res.im = tmp; } else { tmp = res.im; res.im = -res.re; res.re = tmp; } return res; } atanh() { const a = this.re; const b = this.im; const noIM = a > 1 && b === 0; const oneMinus = 1 - a; const onePlus = 1 + a; const d = oneMinus * oneMinus + b * b; const x = d !== 0 ? new ComplexNumber((onePlus * oneMinus - b * b) / d, (b * oneMinus + onePlus * b) / d) : new ComplexNumber(a !== -1 ? a / 0 : 0, b !== 0 ? b / 0 : 0); const temp = x.re; x.re = logHypot(x.re, x.im) / 2; x.im = Math.atan2(x.im, temp) / 2; if (noIM) { x.im = -x.im; } return x; } acoth() { const a = this.re; const b = this.im; if (a === 0 && b === 0) { return new ComplexNumber(0, Math.PI / 2); } const d = a * a + b * b; return d !== 0 ? new ComplexNumber(a / d, -b / d).atanh() : new ComplexNumber(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).atanh(); } asech() { const a = this.re; const b = this.im; if (a === 0 && b === 0) { return new ComplexNumber(Infinity, 0); } const d = a * a + b * b; return d !== 0 ? new ComplexNumber(a / d, -b / d).acosh() : new ComplexNumber(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).acosh(); } acsch() { const a = this.re; const b = this.im; if (b === 0) { return new ComplexNumber(a !== 0 ? Math.log(a + Math.sqrt(a * a + 1)) : Infinity, 0); } const d = a * a + b * b; return d !== 0 ? new ComplexNumber(a / d, -b / d).asinh() : new ComplexNumber(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).asinh(); } inverse() { const a = this.re; const b = this.im; const d = a * a + b * b; return new ComplexNumber(a !== 0 ? a / d : 0, b !== 0 ? -b / d : 0); } conjugate() { return new ComplexNumber(this.re, -this.im); } neg() { return new ComplexNumber(-this.re, -this.im); } ceil(places) { places = Math.pow(10, places || 0); return new ComplexNumber(Math.ceil(this.re * places) / places, Math.ceil(this.im * places) / places); } floor(places) { places = Math.pow(10, places || 0); return new ComplexNumber(Math.floor(this.re * places) / places, Math.floor(this.im * places) / places); } round(places) { places = Math.pow(10, places || 0); return new ComplexNumber(Math.round(this.re * places) / places, Math.round(this.im * places) / places); } equals(a, b) { const P = ComplexNumber.parse(a, b); return Math.abs(P.re - this.re) <= ComplexNumber.EPSILON && Math.abs(P.im - this.im) <= ComplexNumber.EPSILON; } clone() { return new ComplexNumber(this.re, this.im); } valueOf() { if (this.im === 0) { return this.re; } return null; } isNaN() { return isNaN(this.re) || isNaN(this.im); } isFinite() { return isFinite(this.re) && isFinite(this.im); } toString() { const a = this.re; let b = this.im; let ret = ''; if (isNaN(a) || isNaN(b)) { return 'NaN'; } if (a !== 0) { ret += a; } if (b !== 0) { if (a !== 0) { ret += b < 0 ? ' - ' : ' + '; } else if (b < 0) { ret += '-'; } b = Math.abs(b); if (1 !== b) { ret += b; } ret += 'i'; } if (!ret) return '0'; return ret; } toVector() { return [this.re, this.im]; } toVector2D() { return new index_1.Vector2D(this.re, this.im); } } exports.ComplexNumber = ComplexNumber; ComplexNumber.ZERO = new ComplexNumber(0, 0); ComplexNumber.ONE = new ComplexNumber(1, 0); ComplexNumber.I = new ComplexNumber(0, 1); ComplexNumber.PI = new ComplexNumber(Math.PI, 0); ComplexNumber.E = new ComplexNumber(Math.E, 0); ComplexNumber.EPSILON = 1e-16;