ziko
Version:
A versatile JavaScript library offering a rich set of Hyperscript Based UI components, advanced mathematical utilities, interactivity ,animations, client side routing and more ...
1,702 lines (1,614 loc) • 154 kB
JavaScript
/*
Project: ziko.js
Author: Zakaria Elalaoui
Date : Thu Jun 04 2026 14:34:29 GMT+0100 (UTC+01:00)
Git-Repo : https://github.com/zakarialaoui10/ziko.js
Git-Wiki : https://github.com/zakarialaoui10/ziko.js/wiki
Released under MIT License
*/
'use strict';
const { PI: PI$1, E } = Math;
const EPSILON=Number.EPSILON;
const is_primitive = value => typeof value !== 'object' && typeof value !== 'function' || value === null;
const mapfun=(fun,...X)=>{
const Y=X.map(x=>{
if(is_primitive(x) || x?.__mapfun__) return fun(x)
if(x instanceof Array) return x.map(n=>mapfun(fun,n));
if(ArrayBuffer.isView(x)) return x.map(n=>fun(n));
if(x instanceof Set) return new Set(mapfun(fun,...[...x]));
if(x instanceof Map) return new Map([...x].map(n=>[n[0],mapfun(fun,n[1])]));
if(x.isMatrix?.()) return new x.constructor(x.rows, x.cols, mapfun(x.arr.flat(1)))
else if(x instanceof Object){
return Object.fromEntries(
Object.entries(x).map(
n=>n=[n[0],mapfun(fun,n[1])]
)
)
}
});
return Y.length==1? Y[0]: Y;
};
const apply_fun = (x, fn) => {
if (x.isComplex?.()) return new x.constructor(
fn(x.a),
fn(x.b)
)
if (x.isMatrix?.()) return new x.constructor(
x.rows,
x.cols,
x.arr.flat(1).map(fn)
)
if (x instanceof Array) mapfun(fn, ...x);
return fn(x)
};
const base2base = (value, fromBase, toBase) => {
const dec = parseInt(value, fromBase);
if (Number.isNaN(dec)) throw new TypeError('Invalid value for the given base');
return dec.toString(toBase);
};
const arithmetic_helper=(op, x, y)=>{
if(typeof x === 'number'){
if(typeof y === 'number'){
switch(op){
case 'add' : return x + y;
case 'sub' : return x - y;
case 'mul' : return x * y;
case 'div' : return x / y;
case 'modulo' : return x % y;
}
}
if(y?.isComplex?.()) x = new y.constructor(x, 0);
if(y?.isMatrix?.()) x = y.constructor.nums(y.rows, y.cols, x);
return x[op](y)
}
if(x?.isComplex?.()){
if(typeof y === 'number' || y?.isComplex?.()) return x.clone()[op](y);
if(y?.isMatrix?.()){
x = y.constructor.nums(y.rows, y.cols, x);
return x.clone()[op](y)
}
}
if(x?.isMatrix?.()){
return x.clone()[op](y)
}
};
const add=(a,...b)=>{
let res = a;
for(let i=0; i<b.length; i++)
res = arithmetic_helper('add', res, b[i]);
return res;
};
const sub=(a,...b)=>{
let res = a;
for(let i=0; i<b.length; i++)
res = arithmetic_helper('sub', res, b[i]);
return res;
};
const mul=(a,...b)=>{
let res = a;
for(let i=0; i<b.length; i++)
res = arithmetic_helper('mul', res, b[i]);
return res;
};
const div=(a,...b)=>{
let res = a;
for(let i=0; i<b.length; i++)
res = arithmetic_helper('div', res, b[i]);
return res;
};
const modulo=(a,...b)=>{
let res = a;
for(let i=0; i<b.length; i++)
res = arithmetic_helper('modulo', res, b[i]);
return res;
};
const min = (...x) => Math.min(...x);
const max = (...x) => Math.max(...x);
const binomial = (n, k) =>{
if(n !== Math.floor(n)) return TypeError('n must be an integer');
if(k !== Math.floor(k)) return TypeError('k must be an integer');
if (n < 0) return TypeError('n must be non-negative');
if (k < 0 || n < 0 || k > n) return 0;
if (k > n - k) k = n - k;
let c = 1, i;
for (i = 0; i < k; i++)
c = c * (n - i) / (i + 1);
return c;
};
const mean = (...x) => x.reduce((a, b) => a + b) / x.length;
const variance = (...x) => {
const n = x.length;
if (n === 0) return NaN;
const x_mean = mean(...x);
return x.reduce((sum, xi) => sum + (xi - x_mean) ** 2, 0) / n;
};
const std = (...x) => Math.sqrt(variance(...x));
const accum_sum = (...x) => {
let result = [];
let total = 0, i, n = x.length;
for(i = 0; i < n ; i++){
total = add(total, x[i]);
result.push(total);
}
return result;
};
const accum_prod = (...x) => {
let result = [];
let prod = 1, i, n = x.length;
for(i = 0; i < n ; i++){
prod = mul(prod, x[i]);
result.push(prod);
}
return result;
};
const percentile = (X, p) => {
if (X.length === 0)
return NaN;
let a = [...X].sort((x, y) => x - y);
let index = (p / 100) * (a.length - 1);
let i = Math.floor(index);
let f = index - i;
if (i === a.length - 1)
return a[i];
return a[i] * (1 - f) + a[i + 1] * f;
};
const median = X => percentile(X, 50);
class Random {
static int(a, b){
return Math.floor(this.float(a, b));
}
static float(a, b){
return b !== undefined
? Math.random() * (b - a) + a
: Math.random() * a;
}
static bin(){
return this.int(2);
}
static oct(){
return this.int(8);
}
static dec(){
return this.int(10);
}
static hex(){
return base2base(this.int(16), 10, 16);
}
static char(upperCase = false){
const i = upperCase
? this.int(65, 91)
: this.int(97, 123);
return String.fromCharCode(i);
}
static bool(){
return Boolean(this.int(2));
}
static get color(){
return {
hex : () =>
`#${this.int(0xffffff).toString(16).padStart(6, '0')}`,
hexa : () => {
const [r,g,b,a] = Array.from(
{length:4},
() => this.int(0xff).toString(16).padStart(2,'0')
);
return `#${r}${g}${b}${a}`;
},
rgb : () => {
const [r,g,b] = Array.from({length:3}, () => this.int(0xff));
return `rgb(${r}, ${g}, ${b})`;
},
rgba : () => {
const [r,g,b] = Array.from({length:3}, () => this.int(0xff));
const a = Math.random().toFixed(2);
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
hsl : () => {
const h = this.int(360);
const s = this.int(100);
const l = this.int(100);
return `hsl(${h}, ${s}%, ${l}%)`;
},
hsla : () => {
const h = this.int(360);
const s = this.int(100);
const l = this.int(100);
const a = Math.random().toFixed(2);
return `hsla(${h}, ${s}%, ${l}%, ${a})`;
},
gray : () => {
const g = this.int(0xff);
return `rgb(${g}, ${g}, ${g})`;
}
};
}
static get sample(){
const R = this;
return {
int : (n,a,b) => Array.from({length:n}, () => R.int(a,b)),
float : (n,a,b) => Array.from({length:n}, () => R.float(a,b)),
char : (n,upper=false) => Array.from({length:n}, () => R.char(upper)),
bool : n => Array.from({length:n}, () => R.bool()),
bin : n => Array.from({length:n}, () => R.bin()),
oct : n => Array.from({length:n}, () => R.oct()),
dec : n => Array.from({length:n}, () => R.dec()),
hex : n => Array.from({length:n}, () => R.hex()),
get color(){
return {
hex : n => Array.from({length:n}, () => R.color.hex()),
hexa : n => Array.from({length:n}, () => R.color.hexa()),
rgb : n => Array.from({length:n}, () => R.color.rgb()),
rgba : n => Array.from({length:n}, () => R.color.rgba()),
hsl : n => Array.from({length:n}, () => R.color.hsl()),
hsla : n => Array.from({length:n}, () => R.color.hsla()),
gray : n => Array.from({length:n}, () => R.color.gray())
};
},
choice : (n, choices, p) =>
Array.from({length:n}, () => R.choice(choices, p))
};
}
static shuffle(arr){
return [...arr].sort(() => 0.5 - Math.random());
}
static choice(choices = [1,2,3], p = new Array(choices.length).fill(1 / choices.length)){
const acc = accum_sum(...p).map(v => v * 100);
const pool = new Array(100);
pool.fill(choices[0], 0, acc[0]);
for(let i=1;i<choices.length;i++)
pool.fill(choices[i], acc[i-1], acc[i]);
return pool[this.int(pool.length)];
}
}
globalThis.Random = Random;
// // (upperCase) => upperCase ? : String.fromCharCode(rand_int(97,120))
// class Random {
// static string(length,upperCase){
// return length instanceof Array?
// new Array(this.int(...length)).fill(0).map(() => this.char(upperCase)).join(""):
// new Array(length).fill(0).map(() => this.char(upperCase)).join("");
// }
// }
// export{Random}
const complex_constructor = (Complex, a, b) => {
let _a, _b;
if (a instanceof Complex) {
_a = a.a;
_b = a.b;
}
else if (typeof a === "object") {
if ("a" in a && "b" in a) {
_a = a.a;
_b = a.b;
}
else if ("a" in a && "z" in a) {
_a = a.a;
_b = Math.sqrt(a.z ** 2 - a.a ** 2);
}
else if ("a" in a && "phi" in a) {
_a = a.a;
_b = a.a * Math.tan(a.phi);
}
else if ("b" in a && "z" in a) {
_b = a.b;
_a = Math.sqrt(a.z ** 2 - a.b ** 2);
}
else if ("b" in a && "phi" in a) {
_b = b;
_a = a.b / Math.tan(a.phi);
}
else if ("z" in a && "phi" in a) {
_a = +a.z * Math.cos(a.phi).toFixed(15);
_b = +a.z * Math.sin(a.phi).toFixed(15);
}
}
else if (typeof a === "number" && typeof b === "number") {
_a = +a.toFixed(32);
_b = +b.toFixed(32);
}
return [_a, _b]
};
class Complex{
constructor(a = 0, b = 0) {
[
this.a,
this.b
] = complex_constructor(Complex, a, b);
}
get __mapfun__(){
return true
}
isComplex(){
return true
}
toString(){
let str = "";
if (this.a !== 0)
this.b >= 0
? (str = `${this.a}+${this.b}*i`)
: (str = `${this.a}-${Math.abs(this.b)}*i`);
else
this.b >= 0
? (str = `${this.b}*i`)
: (str = `-${Math.abs(this.b)}*i`);
return str;
}
serialize() {
return JSON.stringify({
type : 'complex',
data : this
});
}
static deserialize(json){
if(typeof json === 'string') json = JSON.parse(json);
let {data, type} = json;
return (type === 'complex' && ('a' in data) && ('b' in data))
? new Complex(data.a, data.b)
: TypeError('Not a valid complex')
}
toFixed(n){
this.a = + this.a.toFixed(n);
this.b = + this.b.toFixed(n);
return this;
}
toPrecision(n){
this.a = + this.a.toPrecision(n);
this.b = + this.b.toPrecision(n);
return this;
}
clone() {
return new Complex(this.a, this.b);
}
get z(){
return Math.hypot(this.a,this.b);
}
get phi(){
return Math.atan2(this.b , this.a);
}
static zero() {
return new Complex(0, 0);
}
static fromPolar(z, phi) {
return new Complex(
+(z * cos(phi)).toFixed(13),
+(z * sin(phi)).toFixed(13)
);
}
static get random(){
return {
int : (a, b)=> new Complex(...Random.sample.int(2, a, b) ),
float : (a, b)=> new Complex(...Random.sample.float(2, a, b) ),
}
}
static twiddle(K, N){
const phi = -2 * Math.PI * K / N;
return new Complex(
Math.cos(phi),
Math.sin(phi)
);
}
get conj() {
return new Complex(this.a, -this.b);
}
get inv() {
return new Complex(
this.a / Math.hypot(this.a, this.b),
-this.b / Math.hypot(this.a, this.b)
);
}
add(...c) {
for (let i = 0; i < c.length; i++) {
if (typeof c[i] === "number") c[i] = new Complex(c[i], 0);
this.a += c[i].a;
this.b += c[i].b;
}
return this;
}
sub(...c) {
for (let i = 0; i < c.length; i++) {
if (typeof c[i] === "number") c[i] = new Complex(c[i], 0);
this.a -= c[i].a;
this.b -= c[i].b;
}
return this;
}
mul(...c){
let {z, phi} = this;
for (let i = 0; i < c.length; i++) {
if (typeof c[i] === "number") c[i] = new Complex(c[i], 0);
z *= c[i].z;
phi += c[i].phi;
}
this.a = z * Math.cos(phi);
this.b = z * Math.sin(phi);
return this.toFixed(8);
}
div(...c){
let {z, phi} = this;
for (let i = 0; i < c.length; i++) {
if (typeof c[i] === "number") c[i] = new Complex(c[i], 0);
z /= c[i].z;
phi -= c[i].phi;
}
this.a = z * Math.cos(phi);
this.b = z * Math.sin(phi);
return this.toFixed(8); }
modulo(...c) {
for (let i = 0; i < c.length; i++) {
if (typeof c[i] === "number") c[i] = new Complex(c[i], 0);
this.a %= c[i].a;
this.b %= c[i].b;
}
return this;
}
pow(...c){
let {z, phi} = this;
for (let i = 0; i < c.length; i++) {
if (typeof c[i] === "number") c[i] = new Complex(c[i], 0);
z *= Math.exp(c[i].a * Math.log(z) - c[i].b * phi);
phi += c[i].b * Math.log(z) + c[i].a * phi;
}
this.a = z * Math.cos(phi);
this.b = z * Math.sin(phi);
return this;
}
get expo() {
return [this.z, this.phi];
}
nthr(n=2){
return complex({z: this.z ** (1/n), phi: this.phi / n});
}
get sqrt(){
return this.nthr(2);
}
get cbrt(){
return this.nthr(3);
}
get log(){
return complex(this.z, this.phi);
}
get cos(){
return complex(
Math.cos(this.a) * Math.cosh(this.b),
Math.sin(this.a) * Math.sinh(this.b)
)
}
get sin(){
return complex(
Math.sin(this.a) * Math.cosh(this.b),
Math.cos(this.a) * Math.sinh(this.b)
)
}
get tan(){
const D=cos(this.a*2)+cosh(this.b*2);
return complex(
Math.sin(2 * this.a) / D,
Math.sinh(2 * this.b) / D
);
}
}
const complex=(a,b)=>{
if((a instanceof Array||ArrayBuffer.isView(a)) && (b instanceof Array||ArrayBuffer.isView(a)))return a.map((n,i)=>complex(a[i],b[i]));
if(a.isMatrix?.() && b.isMatrix?.()){
if((a.shape[0]!==b.shape[0])||(a.shape[1]!==b.shape[1]))return Error(0)
const arr=a.arr.map((n,i)=>complex(a.arr[i],b.arr[i]));
return new a.constructor(a.rows,a.cols,...arr)
}
return new Complex(a,b)
};
const PRECESION = 8;
const abs = (...x) => mapfun(
x =>{
if(x.isComplex?.()) return x.z;
return Math.abs(x)
},
...x
);
const pow$1 = (...x) => {
const n = x.pop();
return mapfun(
x => {
if(x.isComplex?.()) {
if(n.isComplex?.()) return new x.constructor({
z: Math.exp(n.a * Math.log(x.z) - n.b * x.phi),
phi: n.b * Math.log(x.z) + n.a * x.phi
})
return new x.constructor({z: x.z ** n, phi: x.phi * n});
}
if(n.isComplex?.()) return new x.constructor({
z: Math.exp(n.a * Math.log(x)),
phi: n.b * Math.log(x)
})
return Math.pow(x, n)
},
...x
)
};
const sqrt$2 = (...x) => mapfun(
x=>{
if(x.isComplex?.())
return new x.constructor({z: x.z**(1/2), phi: x.phi/2});
if(x < 0) return complex(0, Math.sqrt(-x)).toFixed(PRECESION)
return + Math.sqrt(x).toFixed(PRECESION);
},
...x
);
const cbrt = (...x) => mapfun(
x=>{
if(x.isComplex?.())
return new x.constructor({z: x.z**(1/3), phi: x.phi/3}).toFixed(PRECESION)
return + Math.cbrt(x).toFixed(PRECESION);
},
...x
);
const nthr = (...x) => {
const n = x.pop();
if(typeof n !== 'number') throw Error('nthr expects a real number n');
return mapfun(
x => {
if(x.isComplex?.()) return new x.constructor({z: x.z ** (1/n), phi: x.phi / n});
if(x<0) return n %2 ===2
? complex(0, (-x)**(1/n)).toFixed(PRECESION)
: + (-1 * (-x)**(1/n)).toFixed(PRECESION)
return + (x**(1/n)).toFixed(PRECESION)
},
...x
)
};
const croot = (...x) =>{
const c = x.pop();
if(!c.isComplex?.()) throw Error('croot expect Complex number as root')
return mapfun(
x => {
if(typeof x === 'number') x = new c.constructor(x, 0);
const {a : c_a, b : c_b} = c;
const {z, phi} = x;
const D = Math.hypot(c_a, c_b);
const A = Math.exp((Math.log(z)*c_a + phi*c_b)/D);
const B = (phi*c_a - Math.log(z)*c_b)/D;
return new c.constructor(
A * Math.cos(B),
A * Math.sin(B)
).toFixed(PRECESION)
},
...x
)
};
const exp$1 = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.exp(x.a) * Math.cos(x.b),
Math.exp(x.a) * Math.sin(x.b)
).toFixed(PRECESION);
return + Math.exp(x).toFixed(PRECESION)
}
,...x
);
const ln = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.log(x.z),
x.phi
).toFixed(PRECESION);
return + Math.log(x).toFixed(PRECESION)
}
,...x
);
const sign = (...x) => mapfun(
x => {
if(x.isComplex?.()){
const {z, phi} = x;
if(z===0) return new x.constructor(0, 0);
return new x.constructor({z:1, phi})
}
return Math.sign(x)
}
,...x
);
const floor = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.floor(x.a),
Math.floor(x.b)
)
return Math.floor(x)
},
...x
);
const ceil = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.ceil(x.a),
Math.ceil(x.b)
)
return Math.ceil(x)
},
...x
);
const round = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.round(x.a),
Math.round(x.b)
)
return Math.round(x)
},
...x
);
const trunc = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.trunc(x.a),
Math.trunc(x.b)
)
return Math.trunc(x)
},
...x
);
const fract = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
x.a - Math.trunc(x.a),
x.b - Math.trunc(x.b)
)
return x - Math.trunc(x)
},
...x
);
const cos$3 = (...x) => mapfun(
x => {
if(x.isComplex?.()) return new x.constructor(
Math.cos(x.a) * Math.cosh(x.b),
-Math.sin(x.a) * Math.sinh(x.b)
).toFixed(PRECESION);
return + Math.cos(x).toFixed(PRECESION)
}
,...x
);
const sin$3 = (...x) => mapfun(
x =>{
if(x?.isComplex) return new x.constructor(
Math.sin(x.a) * Math.cosh(x.b),
Math.cos(x.a) * Math.sinh(x.b)
).toFixed(PRECESION);
return + Math.sin(x).toFixed(PRECESION)
}
, ...x
);
const tan = (...x) => mapfun(
x =>{
if(x?.isComplex){
const D = Math.cos(2*x.a) + Math.cosh(2*x.b);
return new x.constructor(
Math.sin(2*x.a) / D,
Math.sinh(2*x.b) / D
).toFixed(PRECESION);
}
return + Math.tan(x).toFixed(PRECESION)
},
...x
);
const sec = (...x) => mapfun(
x => {
if(x.isComplex?.()) ;
return + (1 / Math.cos(x)).toFixed(PRECESION)
}
,...x
);
const acos$1 = (...x) => mapfun(
x =>{
if(x?.isComplex){
const { a, b } = x;
const Rp = Math.hypot(a + 1, b);
const Rm = Math.hypot(a - 1, b);
globalThis.Rp = Rp;
globalThis.Rm = Rm;
return new x.constructor(
Math.acos((Rp - Rm) / 2),
-Math.acosh((Rp + Rm) / 2),
).toFixed(PRECESION)
}
return + Math.acos(x).toFixed(PRECESION)
},
...x
);
const asin = (...x) => mapfun(
x => {
if(x?.isComplex){
const { a, b } = x;
const Rp = Math.hypot(a + 1, b);
const Rm = Math.hypot(a - 1, b);
return new x.constructor(
Math.asin((Rp - Rm) / 2),
Math.acosh((Rp + Rm) / 2)
).toFixed(PRECESION);
}
return + Math.asin(x).toFixed(PRECESION);
},
...x
);
const atan = (...x) => mapfun(
x => {
if(x?.isComplex){
const { a, b } = x;
return new x.constructor(
Math.atan((a*2/(1-a**2-b**2)))/2,
Math.log((a**2 + (1+b)**2)/(a**2 + (1-b)**2))/4
).toFixed(PRECESION)
}
return + Math.atan(x).toFixed(PRECESION);
},
...x
);
const acot = (...x) => mapfun(
x => {
if(x?.isComplex){
const { a, b } = x;
return new x.constructor(
Math.atan(2*a/(a**2+(b-1)*(b+1)))/2,
Math.log((a**2 + (b-1)**2)/(a**2 + (b+1)**2))/4
).toFixed(PRECESION)
}
return + (Math.PI/2 - Math.atan(x)).toFixed(PRECESION);
},
...x
);
const cosh$2 = (...x) => mapfun(
x =>{
if(x?.isComplex) return new x.constructor(
Math.cosh(x.a) * Math.cos(x.b),
Math.sinh(x.a) * Math.sin(x.b)
).toFixed(PRECESION);
return + Math.cosh(x).toFixed(PRECESION)
},
...x
);
const sinh$1 = (...x) => mapfun(
x =>{
if(x?.isComplex) return new x.constructor(
Math.sinh(x.a) * Math.cos(x.b),
Math.cosh(x.a) * Math.sin(x.b)
).toFixed(PRECESION);
return + Math.sinh(x).toFixed(PRECESION)
},
...x
);
const tanh = (...x) => mapfun(
x =>{
if(x?.isComplex){
const D = Math.cosh(2*a) + Math.cos(2*b);
return new x.constructor(
Math.sinh(2*a) / D,
Math.sin(2*b) / D
).toFixed(PRECESION)
}
return + Math.tanh(x).toFixed(PRECESION)
},
...x
);
const coth = (...x) => mapfun(
x =>{
if(x?.isComplex){
const {a, b} = x;
const D = (Math.sinh(a)**2)*(Math.cos(b)**2) + (Math.cosh(a)**2)*(Math.sin(b)**2);
return new x.constructor(
Math.cosh(a) * Math.sinh(a) / D,
- Math.sin(b) * Math.cos(b) / D
).toFixed(PRECESION)
}
return + (1 / Math.tanh(x)).toFixed(PRECESION)
},
...x
);
const acosh = (...x) => mapfun(
x =>{
if(x?.isComplex){
return ln(x.clone().add(sqrt$2(x.clone().mul(x.clone()).sub(1))))
}
return + Math.acosh(x).toFixed(PRECESION)
},
...x
);
const asinh = (...x) => mapfun(
x =>{
if(x?.isComplex){
return ln(x.clone().add(sqrt$2(x.clone().mul(x.clone()).add(1))))
}
return + Math.asinh(x).toFixed(PRECESION)
},
...x
);
const atanh = (...x) => mapfun(
x =>{
if(x?.isComplex);
return + Math.atanh(x).toFixed(PRECESION)
},
...x
);
const sig = (...x) => mapfun(
x =>{
if(x?.isComplex);
return 1/(1 + Math.exp(-x)).toFixed(PRECESION)
},
...x
);
const deg2rad = (...deg) => mapfun(x => x * Math.PI / 180, ...deg);
const rad2deg = (...rad) => mapfun(x => x / Math.PI * 180, ...rad);
const norm = (x, min, max) => apply_fun(
x,
v => min !== max ? (v - min) / (max - min) : 0
);
const lerp = (x, min, max) => apply_fun(
x,
v => (max - min) * v + min
);
const clamp = (x, min, max) => apply_fun(
x,
v => Math.min(Math.max(v, min), max)
);
const map$1 = (x, a, b, c, d) => apply_fun(
x,
v => lerp(norm(v, a, b), c, d)
);
const hypot = (...x) => {
const c0 = x.find(a => a.isComplex?.());
if (c0) {
const W = x.map(n => n.isComplex?.() ? n : new c0.constructor(n, 0));
return Math.hypot(...W.map(c => c.z));
}
return Math.hypot(...x);
};
const atan2 = (y, x, rad = true) => {
if (y instanceof Array && !(x instanceof Array))
return mapfun(n => atan2(n, x, rad), ...y);
if (x instanceof Array && !(y instanceof Array))
return mapfun(n => atan2(y, n, rad), ...x);
if (y instanceof Array && x instanceof Array)
return y.map((v, i) => atan2(v, x[i], rad));
const phi = Math.atan2(y, x);
return rad ? phi : phi * 180 / Math.PI;
};
const not = x => {
if(x.isComplex?.()) return new x.constructor(not(x.a), not(x.b))
if(x.isMatrix?.()) return new x.constructor(x.rows, x.cols, x.arr.flat(1).map(not))
return + !x;
};
const handle_complex_and_matrix = (x, operation) => {
if (x.every(n => n.isComplex?.())) {
const Re = x.map(n => n.a);
const Im = x.map(n => n.b);
return new x[0].constructor(
operation(...Re),
operation(...Im)
);
}
if (x.every(n => n.isMatrix?.())) {
if (!x.every(mat => mat.rows === x[0].rows && mat.cols === x[0].cols)) {
return TypeError('All matrices must have the same shape');
}
const { rows, cols } = x[0];
const Y = Array.from({ length: rows }, (_, i) =>
Array.from({ length: cols }, (_, j) =>
operation(...x.map(mat => mat.arr[i][j]))
)
);
return new x[0].constructor(Y);
}
return null; // Return null if no Complex or Matrix found
};
const and = (...x) => {
const result = handle_complex_and_matrix(x, and);
if (result !== null) return result;
return x.reduce((n, m) => (n &= m), 1);
};
const or = (...x) => {
const result = handle_complex_and_matrix(x, or);
if (result !== null) return result;
return x.reduce((n, m) => (n |= m), 0);
};
const xor = (...x) => {
const result = handle_complex_and_matrix(x, xor);
if (result !== null) return result;
return x.reduce((n, m) => (n ^= m), 0);
};
const nand = (...x) => not(and(...x));
const nor = (...x) => not(or(...x));
const xnor = (...x) => not(xor(...x));
const matrix_constructor = (Matrix, rows, cols, element) => {
if (rows instanceof Matrix) {
arr = rows.arr;
rows = rows.rows;
cols = rows.cols;
}
else {
let arr = [], i, j;
if (rows instanceof Array) {
arr = rows;
rows = arr.length;
cols = arr[0].length;
}
else {
for (i = 0; i < rows; i++) {
arr.push([]);
arr[i].push(new Array(cols));
for (j = 0; j < cols; j++) {
arr[i][j] = element[i * cols + j];
if (element[i * cols + j] == undefined) arr[i][j] = 0;
}
}
}
return [
rows,
cols,
arr
]
}
};
const maintain_indexes = (Matrix, oldRows) =>{
for (let i = 0; i < Matrix.arr.length; i++) {
Object.defineProperty(Matrix, i, {
value: Matrix.arr[i],
writable: true,
configurable: true,
enumerable: false
});
}
for (let i = Matrix.arr.length; i < oldRows; i++) {
delete Matrix[i];
}
};
function matrix_inverse(M) {
if(M.row !== M.cols) throw Error('is not a square matrix"')
if (M.det === 0) throw Error("determinant should not equal 0");
const { arr } = M;
if (arr.length !== arr[0].length) return;
var i = 0, ii = 0, j = 0, dim = arr.length, e = 0;
var I = [], C = [];
for (i = 0; i < dim; i += 1) {
I[I.length] = [];
C[C.length] = [];
for (j = 0; j < dim; j += 1) {
if (i == j) I[i][j] = 1;
else I[i][j] = 0;
C[i][j] = arr[i][j];
}
}
for (i = 0; i < dim; i += 1) {
e = C[i][i];
if (e == 0) {
for (ii = i + 1; ii < dim; ii += 1) {
if (C[ii][i] != 0) {
for (j = 0; j < dim; j++) {
e = C[i][j];
C[i][j] = C[ii][j];
C[ii][j] = e;
e = I[i][j];
I[i][j] = I[ii][j];
I[ii][j] = e;
}
break;
}
}
e = C[i][i];
if (e == 0) return;
}
for (j = 0; j < dim; j++) {
C[i][j] = C[i][j] / e;
I[i][j] = I[i][j] / e;
}
for (ii = 0; ii < dim; ii++) {
if (ii == i) {
continue;
}
e = C[ii][i];
for (j = 0; j < dim; j++) {
C[ii][j] -= e * C[i][j];
I[ii][j] -= e * I[i][j];
}
}
}
return new M.constructor(I);
}
function matrix_det(M) {
if (!M.isSquare) return new Error("is not square matrix");
if (M.rows == 1) return M.arr[0][0];
function determinat(M) {
if (M.length == 2) {
if (M.flat(1).some((n) => n?.isMatrix?.())) {
console.warn("Tensors are not completely supported yet ...");
return;
}
return sub(mul(M[0][0],M[1][1]),mul(M[0][1],M[1][0]))
}
var answer = 0;
for (var i = 0; i < M.length; i++) {
//console.log(M[0][i]);
/*answer = answer.add(
pow(-1, i)
.mul(M[0][i])
.mul(determinat(deleteRowAndColumn(M, i)))
);*/
//const to_be_added=add(mul(pow(-1, i),mul(M[0][i],determinat(deleteRowAndColumn(M, i)))));
const to_be_added=add(mul(pow$1(-1, i),mul(M[0][i],determinat(deleteRowAndColumn(M, i)))));
answer=add(answer,to_be_added);
}
return answer;
}
return determinat(M.arr);
}
function deleteRowAndColumn(M, index) {
var temp = [];
for (let i = 0; i < M.length; i++) temp.push(M[i].slice(0));
temp.splice(0, 1);
for (let i = 0; i < temp.length; i++) temp[i].splice(index, 1);
return temp;
}
function hstack(M1, M2){
M1 = M1.clone();
M2 = M2.clone();
if (M1.rows !== M2.rows) return;
let newArr = M1.arr;
for (let i = 0; i < M1.rows; i++)
for (let j = M1.cols; j < M1.cols + M2.cols; j++)
newArr[i][j] = M2.arr[i][j - M1.cols];
M1.cols += M2.cols;
return new M1.constructor(M1.rows, M1.cols, newArr.flat(1));
}
function vstack(M1, M2){
M1 = M1.clone();
M2 = M2.clone();
if (M1.cols !== M2.cols) return;
let newArr = M1.arr;
for (let i = M1.rows; i < M1.rows + M2.rows; i++) {
newArr[i] = [];
for (let j = 0; j < M1.cols; j++) newArr[i][j] = M2.arr[i - M1.rows][j];
}
M1.rows += M2.rows;
return new M1.constructor(M1.rows, M1.cols, newArr.flat(1));
}
class Matrix{
constructor(rows, cols, element = [] ) {
[
this.rows,
this.cols,
this.arr
] = matrix_constructor(Matrix, rows, cols, element);
maintain_indexes(this);
}
isMatrix(){
return true
}
clone() {
return new Matrix(this.rows, this.cols, this.arr.flat(1));
}
toComplex(){
this.arr = mapfun(
x => x?.isComplex?.() ? x : new Complex(x, 0),
...this.arr
);
maintain_indexes(this);
return this;
}
[Symbol.iterator]() {
return this.arr[Symbol.iterator]();
}
get size() {
return this.rows * this.cols;
}
get shape() {
return [this.rows, this.cols];
}
// toString(){
// return arr2str(this.arr,false);
// }
at(i = 0, j = undefined) {
if(i < 0) i += this.rows;
if(i < 0 || i >= this.rows) throw new Error('Row index out of bounds');
if(j === undefined) return this.arr[i];
if(j < 0) j += this.cols;
if(j < 0 || j >= this.cols) throw new Error('Column index out of bounds');
return this.arr[i][j];
}
slice(r0=0, c0=0, r1 = this.rows-1, c1 = this.cols-1) {
if(r1 < 0) r1 = this.rows + r1;
if(c1 < 0 ) c1 = this.cols + c1;
let newRow = r1 - r0,
newCol = c1 - c0;
let newArr = new Array(newCol);
for (let i = 0; i < newRow; i++) {
newArr[i] = [];
for (let j = 0; j < newCol; j++)
newArr[i][j] = this.arr[i + r0][j + c0];
}
this.arr = newArr;
maintain_indexes(this.rows);
this.rows = newRow;
this.cols = newCol;
return this;
}
reshape(newRows, newCols) {
if(!(newRows * newCols === this.rows * this.cols)) throw Error('size not matched');
const oldRows = this.rows;
Object.assign(this, new Matrix(newRows, newCols, this.arr.flat(1)));
maintain_indexes(oldRows);
return this;
}
get T() {
let transpose = [];
for (let i = 0; i < this.arr[0].length; i++) {
transpose[i] = [];
for (let j = 0; j < this.arr.length; j++)
transpose[i][j] = this.arr[j][i];
}
return new Matrix(this.cols, this.rows, transpose.flat(1));
}
get det() {
return matrix_det(this)
}
get inv() {
return matrix_inverse(this)
}
// normalize names
static eye(size) {
let result = new Matrix(size, size);
for (let i = 0; i < size; i++)
for (let j = 0; j < size; j++) i === j ? (result.arr[i][j] = 1) : (result.arr[i][j] = 0);
return result;
}
static zeros(rows, cols) {
let result = new Matrix(rows, cols);
for (let i = 0; i < rows; i++)
for (var j = 0; j < cols; j++) result.arr[i][j] = 0;
return result;
}
static ones(rows, cols) {
let result = new Matrix(rows, cols);
for (let i = 0; i < rows; i++)
for (let j = 0; j < cols; j++) result.arr[i][j] = 1;
return result;
}
static nums(rows, cols, number) {
let result = new Matrix(rows, cols);
for (let i = 0; i < rows; i++)
for (let j = 0; j < cols; j++) result.arr[i][j] = number;
return result;
}
static get random(){
return {
int : (r, c, a, b)=> new Matrix(
r,
c,
Random.sample.int(r*c, a, b)
),
float : (r, c, a,)=> new Matrix(
r,
c,
Random.sample.float(r*c, a, b)
),
}
}
get range(){
return {
map : (xmin, xmax, ymin, ymax) => {
this.arr = map$1(this.arr, xmin, xmax, ymin, ymax);
return this;
},
norm : (min, max) => {
this.arr = norm(this.arr, min, max);
return this;
},
lerp : (min, max) => {
this.arr = lerp(this.arr, min, max);
return this;
},
clamp : (min, max) => {
this.arr = clamp(this.arr, min, max);
return this;
},
}
}
hstack(...matrices) {
const M=[this, ...matrices].reduce((a,b)=>hstack(a, b));
Object.assign(this, M);
maintain_indexes(this);
return this;
}
vstack(...matrices){
const M=[this, ...matrices].reduce((a,b)=>vstack(a, b));
Object.assign(this, M);
maintain_indexes(this);
return this;
}
hqueue(...matrices){
const M=[this, ...matrices].reverse().reduce((a,b)=>hstack(a, b));
Object.assign(this, M);
maintain_indexes(this);
return this;
}
vqueue(...matrices){
const M=[this,...matrices].reverse().reduce((a, b)=>vstack(a, b));
Object.assign(this, M);
maintain_indexes(this);
return this;
}
forEach(fn){
this.arr.flat(1).forEach(fn);
return this;
}
forEachRow(fn){
this.arr.forEach(fn);
return this;
}
forEachCol(fn){
this.clone().T.forEachRow(fn);
return this
}
map(fn){
const arr = this.arr.flat(1).map(fn);
return new Matrix(
this.rows,
this.cols,
arr
)
}
mapRows(fn = ()=>{}){
this.arr = this.arr.map(fn);
return this;
}
mapCols(fn){
return this.clone().T.mapRows(fn).T;
}
sort(fn = ()=>{}){
const arr = this.arr.flat(1).sort(fn);
return new Matrix(
this.rows,
this.cols,
arr
)
}
shuffle(){
return this.sort(() => 0.5-Math.random())
}
sortRows(fn = ()=>{}){
this.arr = this.arr.map(row => row.sort(fn));
return this;
}
shuffleRows(){
return this.sortRows(() => 0.5-Math.random())
}
sortCols(fn){
return this.clone().T.sortRows(fn).T;
}
shuffleCols(){
return this.sortCols(() => 0.5-Math.random())
}
reduce(fn, initialValue){
const value = initialValue
? this.arr.flat(1).reduce(fn, initialValue)
: this.arr.flat(1).reduce(fn);
return new Matrix([[value]])
}
reduceRows(fn, initialValue){
const values = initialValue
? this.arr.map(row => row.reduce(fn, initialValue))
: this.arr.map(row => row.reduce(fn));
return new Matrix(1, this.cols, values)
}
reduceCols(fn, initialValue){
return this.T.reduceRows(fn, initialValue).T
}
filterRows(fn){
const mask = this.arr.map(n => n.some(m => fn(m)));
const arr = [];
let i;
for(i = 0; i < mask.length; i++)
if(mask[i]) arr.push(this.arr[i]);
return new Matrix(arr)
}
filterCols(fn){
const arr = this.T.filterRows(fn);
return new Matrix(arr).T
}
every(fn){
return this.arr.flat(1).every(fn)
}
everyRow(fn){
return this.arr.map(n => n.every(fn))
}
everyCol(fn){
return this.T.arr.map(n => n.every(fn))
}
some(fn){
return this.arr.flat(1).some(fn)
}
someRow(fn){
return this.arr.map(n => n.some(fn))
}
someCol(fn){
return this.T.arr.map(n => n.some(fn))
}
// Checkers
get isSquare() {
return this.rows === this.cols;
}
get isSym() {
if (!this.isSquare) return false;
for (let i = 0; i < this.rows; i++) {
for (let j = i + 1; j < this.cols; j++) {
if (this.arr[i][j] !== this.arr[j][i]) return false;
}
}
return true;
}
get isAntiSym() {
if (!this.isSquare) return false;
const n = this.rows;
for (let i = 0; i < n; i++) {
if (this.arr[i][i] !== 0) return false;
for (let j = i + 1; j < n; j++) {
if (this.arr[i][j] !== -this.arr[j][i]) return false;
}
}
return true;
}
get isDiag() {
if (!this.isSquare) return false;
const n = this.rows;
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) {
if (this.arr[i][j] !== 0 || this.arr[j][i] !== 0) return false;
}
}
return true;
}
get isOrtho() {
if (!this.isSquare) return false;
return this.isDiag && (this.det == 1 || this.det == -1);
}
get isIdemp() {
if (!this.isSquare) return false;
const n = this.rows;
const A = this.arr;
// Compute A * A
const MM = [];
for (let i = 0; i < n; i++) {
MM[i] = [];
for (let j = 0; j < n; j++) {
let sum = 0;
for (let k = 0; k < n; k++) {
sum += A[i][k] * A[k][j];
}
MM[i][j] = sum;
}
}
// Check if A * A == A
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (MM[i][j] !== A[i][j]) return false;
}
}
return true;
}
get isUpperTri() {
if (!this.isSquare) return false;
const n = this.rows;
for (let i = 1; i < n; i++) {
for (let j = 0; j < i; j++) {
if (this.arr[i][j] !== 0) return false;
}
}
return true;
}
get isLowerTri() {
if (!this.isSquare) return false;
const n = this.rows;
for (let i = 0; i < n - 1; i++) {
for (let j = i + 1; j < n; j++) {
if (this.arr[i][j] !== 0) return false;
}
}
return true;
}
toPrecision(p) {
for (let i = 0; i < this.cols; i++)
for (let j = 0; j < this.rows; j++)
this.arr[i][j] = +this.arr[i][j].toPrecision(p);
return this;
}
toFixed(p) {
for (let i = 0; i < this.cols; i++)
for (let j = 0; j < this.rows; j++)
this.arr[i][j] = +this.arr[i][j].toFixed(p);
return this;
}
// max2min() {
// let newArr = this.arr.flat(1).max2min;
// return new Matrix(this.rows, this.cols, newArr);
// }
// min2max() {
// let newArr = this.arr.flat(1).min2max;
// return new Matrix(this.rows, this.cols, newArr);
// }
// count(n) {
// return this.arr.flat(1).count(n);
// }
splice(r0,c0,deleteCount,...items){
}
getRows(ri, rf = ri + 1) {
return this.slice(ri, 0, rf, this.cols);
}
getCols(ci, cf = ci + 1) {
return this.slice(0, ci, this.rows, cf);
}
#arithmetic(fn, ...matr){
for (let k = 0; k < matr.length; k++) {
if (typeof matr[k] == "number" || matr[k]?.isComplex?.()) matr[k] = Matrix.nums(this.rows, this.cols, matr[k]);
for (let i = 0; i < this.rows; i++)
for (var j = 0; j < this.cols; j++)
this.arr[i][j] = fn(this.arr[i][j], matr[k].arr[i][j]);
}
return new Matrix(this.rows, this.cols, this.arr.flat(1));
}
add(...matr) {
return this.#arithmetic(add, ...matr)
}
sub(...matr) {
return this.#arithmetic(sub, ...matr)
}
mul(...matr) {
return this.#arithmetic(mul, ...matr)
}
div(...matr) {
return this.#arithmetic(div, ...matr)
}
modulo(...matr) {
return this.#arithmetic(modulo, ...matr)
}
dot(matrix) {
var res = [];
for (var i = 0; i < this.arr.length; i++) {
res[i] = [];
for (var j = 0; j < matrix.arr[0].length; j++) {
res[i][j] = 0;
for (var k = 0; k < this.arr[0].length; k++) {
res[i][j] = add(
res[i][j],
mul(this.arr[i][k],matrix.arr[k][j])
);
}
}
}
return new Matrix(this.arr.length, matrix.arr[0].length, res.flat(1));
}
pow(n) {
let a = this.clone(),
p = this.clone();
for (let i = 0; i < n - 1; i++) p = p.dot(a);
return p;
}
sum(){
let S = 0;
for (let i = 0; i < this.rows; i++)
for (let j = 0; j < this.cols; j++)
S = add(S, this.arr[i][j]);
return S;
}
prod(){
let S = 1;
for (let i = 0; i < this.rows; i++)
for (let j = 0; j < this.cols; j++)
S = mul(S, this.arr[i][j]);
return S;
}
hasComplex(){
return this.arr.flat(Infinity).some((n) => n instanceof Complex);
}
get min() {
if (this.hasComplex()) console.error("Complex numbers are not comparable");
let minRow = [];
for (let i = 0; i < this.rows; i++)
minRow.push(Math.min(...this.arr[i]));
return Math.min(...minRow);
}
get max() {
if (this.hasComplex()) console.error("Complex numbers are not comparable");
let maxRow = [];
for (let i = 0; i < this.rows; i++)
maxRow.push(Math.max(...this.arr[i]));
return Math.max(...maxRow);
}
get minRows() {
if (this.hasComplex()) console.error("Complex numbers are not comparable");
let minRow = [];
for (let i = 0; i < this.rows; i++)
minRow.push(Math.min(...this.arr[i]));
return minRow;
}
get maxRows() {
if (this.hasComplex()) console.error("Complex numbers are not comparable");
let maxRow = [];
for (let i = 0; i < this.rows; i++)
maxRow.push(Math.max(...this.arr[i]));
return maxRow;
}
get minCols() {
if (this.hasComplex()) console.error("Complex numbers are not comparable");
return this.T.minRows;
}
get maxCols() {
if (this.hasComplex()) console.error("Complex numbers are not comparable");
return this.T.maxRows;
}
static fromVector(v) {
return new Matrix(v.length, 1, v);
}
serialize() {
const arr = mapfun(x => x.serialize?.() || x, ...this.arr);
return JSON.stringify({
type : 'matrix',
data : {
rows : this.rows,
cols : this.cols,
arr,
}
});
}
static deserialize(json) {
if (typeof json == "string") json = JSON.parse(json);
const {type, data} = json;
if(type !== 'matrix') return TypeError('Not a valid Matrix')
let {arr} = data;
arr = mapfun(x => {
if(typeof x === 'string') {
const x_obj = JSON.parse(x);
const {type} = x_obj;
if(type === 'complex') return Complex.deserialize(x_obj)
}
return x
}, ...arr);
return new Matrix(arr)
}
flip(){
return this.flipeH().flipeV()
}
flipeH(){
this.arr = this.arr.map(row => [...row].reverse());
maintain_indexes(this);
return this;
}
flipeV(){
this.arr = this.arr.reverse();
maintain_indexes(this);
return this;
}
}
const matrix=(r, c, element)=>new Matrix(r, c, element);
const matrix2=(...element)=>new Matrix(2, 2, element);
const matrix3=(...element)=>new Matrix(3, 3, element);
const matrix4=(...element)=>new Matrix(4, 4, element);
const zeros=(n)=>new Array(n).fill(0);
const ones=(n)=>new Array(n).fill(1);
const nums=(num,n)=>new Array(n).fill(num);
const arange=(a, b, step , include = false)=>{
let tab = [];
if(a<b){
for (let i = a; include?i<=b:i<b; i += step) tab.push((i * 10) / 10);
}
else {
for(let i = a; include?i>=b:i>b; i -= step) tab.push((i * 10) / 10);
}
return tab;
};
const linspace=(a,b,n=abs(b-a)+1,endpoint=true)=>{
if(Math.floor(n)!==n)return;
if([a,b].every(n=>typeof n==="number")){
const [max,min]=[a,b].sort((a,b)=>b-a);
var Y = [];
let step ;
endpoint ? step = (max - min) / (n - 1) : step = (max - min) / n;
for (var i = 0; i < n; i++) {
a<b?Y.push(min+step*i):Y.push(max-step*i);
}
return Y
}
if([a,b].some(n=>n.isComplex?.())){