UNPKG

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
/* 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?.())){