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
JavaScript
"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;