UNPKG

rlab

Version:

Javascript scientific library like R

1,865 lines (1,629 loc) 1.24 MB
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ var O = require("./field"); var acc = { sum:{init:0,op:'+'}, product:{init:1,op:'*'}, min:{init:Number.MAX_VALUE,op:'min'}, max:{init:-Number.MAX_VALUE,op:'max'}, } O.vfill=function(size, value) { var v=[]; for (var i=0; i<size; i++) v[i] = value; return v; } O.vextend=function(a, size) { var v = a.slice(); for (var i=a.length; i<size; i++) { v.push(0); } return v; } O.vdot=function(x,y) { var sum = 0; for (var i=0; i<x.length; i++) { sum = sum.add(x[i].mul(y[i])); } return sum; } O.vop=function(op,x,y) { var c=[],result=(O.isUndefined(acc[op]))?undefined:acc[op].init; if (O.isArray(x)) { for (var i=0; i<x.length; i++) { if (!O.isUndefined(result)) { var xi = x[i]; if (O.isArray(x[i])) // x[i] is subArray xi = O.op(op, x[i]); else { if (!O.isUndefined(y)) xi = y(x[i]); // y should be a function } result = O.op(acc[op].op, xi, result); // if (op==='min') console.log("xi=%d result=%d", xi, result); } else { var yi = O.isArray(y)?y[i]:y; c[i] = O.op(op, x[i], yi); } } } else { throw Error('vop fail:op,x,y=', op, x, y); } if (x.length === c.length) return c; else return result; } O.op = function(op,x,y) { if (O.isField(x)) { if (!O.isUndefined(acc[op])) { switch (op) { case 'max': return Math.max(x,y); case 'min': return Math.min(x,y); default:return x; } } else if (x instanceof O.FieldObj || (O.isNumber(x) && y instanceof O.FieldObj)) { x = O.Complex.toComplex(x); y = O.isNumber(y)?O.Complex.toComplex(y):y; switch (op) { case 'eval': var exp = y; return exp(x); case 'neg':return x.neg(); case 'inv':return x.inv(); case 'bnot':return x.bnot(); case '+':return x.add(y); case '-':return x.sub(y); case '*':return x.mul(y); case '/':return x.div(y); case 'power':return x.power(y); case 'sqrt':return x.sqrt(); case 'eq':return x.eq(y); case 'neq':return x.neq(y); case 'geq':return x.geq(y); case 'leq':return x.leq(y); case 'gt':return x.gt(y); case 'lt':return x.lt(y); } } else if (O.isBool(x) || O.isNumber(x)) { switch (op) { case 'eval': var exp = y; return exp(x); case 'not':return !x; case 'neg':return -x; case 'inv':return 1/x; case 'bnot':return ~x; case 'and':return x&&y; case 'or':return x||y; case 'xor':return x!==y; case '+':return x+y; case '-':return x-y; case '*':return x*y; case '/':return x/y; case '%':return x%y; case 'eq':return x===y; case 'neq':return x!==y; case 'geq':return x>=y; case 'leq':return x<=y; case 'gt':return x>y; case 'lt':return x<y; case '&':return x&y; case '|':return x|y; case 'bxor':return x^y; case '<<':return x<<y; case '>>':return x>>y; case 'and':return x&&y; case 'or':return x||y; case 'xor':return x!==y; case 'sqrt': if (x>=0) return Math.sqrt(x); else { var c = new O.Complex(x,0); return c.sqrt(); } case 'power': if (x>=0 || O.isInteger(y)) return Math.pow(x,y); else return new O.Complex(x,0).power(y); case 'log':return Math.log(x); case 'exp':return Math.exp(x); case 'abs':return Math.abs(x);; case 'sin':return Math.sin(x); case 'cos':return Math.cos(x); case 'tan':return Math.tan(x); case 'asin':return Math.asin(x); case 'acos':return Math.acos(x); case 'atan':return Math.atan(x); case 'sinh':return Math.sinh(x); case 'cosh':return Math.cosh(x); case 'tanh':return Math.tanh(x); case 'ceil':return Math.ceil(x); case 'floor':return Math.floor(x); case 'round':return Math.round(x); case 'log1p':return Math.log1p(x); case 'log10':return Math.log10(x); case 'log2':return Math.log2(x); case 'random':return Math.random(); case 'sign':return Math.sign(x); case 'abs':return Math.abs(x); case 'cbrt':return Math.cbrt(x); // cubic root } } } else if (O.isFunction(x)) { if (O.isFunction(y)) { switch (op) { case 'neg':return O.fneg(x); case 'inv':return O.finv(x); case '+':return O.fadd(x,y); case '-':return O.fsub(x,y); case '*':return O.fmul(x,y); case '/':return O.fdiv(x,y); case 'compose':return O.fcompose(x,y); } } else { switch (op) { case 'eval':return x(y); } } } else if (O.isArray(x)) { return O.vop(op,x,y); } throw Error('op fail:op,x,y=', op, x, y); } O.sum=function(x) { return O.vop('sum', x) } O.product=function(x) { return O.vop('product', x) } O.max=function(x) { return O.vop('max', x) } O.min=function(x) { return O.vop('min', x) } O.eval=function(x,y) { return O.op('eval', x,y) } O.norm=function(x) { var norm2 = O.vop('sum', x, (x)=>x*x); return Math.sqrt(norm2); } // +-*/%^ O.add=function(x,y) { return O.op('+',x,y) } O.sub=function(x,y) { return O.op('-',x,y) } O.mul=function(x,y) { return O.op('*',x,y) } O.div=function(x,y) { return O.op('/',x,y) } O.mod=function(x,y) { return O.op('%',x,y) } O.power=function(x,y) { return O.op('power', x, y) } O.neg=function(x) { return O.op('neg', x) } O.inv=function(x) { return O.op('inv', x) } // logical O.not=function(x) { return O.op('not', x) } O.and=function(x,y) { return O.op('&&', x, y) } O.or=function(x,y) { return O.op('||', x, y) } O.xor=function(x,y) { return O.op('xor', x, y) } O.bnot=function(x) { return O.op('bnot', x) } O.band=function(x,y) { return O.op('&', x, y) } O.bor=function(x,y) { return O.op('|', x, y) } O.bxor=function(x,y) { return O.op('bxor', x, y) } O.lshift=function(x,y) { return O.op('<<', x, y) } O.rshift=function(x,y) { return O.op('>>', x, y) } // compare O.eq=function(x,y) { return O.op('eq', x, y) } O.neq=function(x,y) { return O.op('neq', x, y) } O.geq=function(x,y) { return O.op('geq', x, y) } O.leq=function(x,y) { return O.op('leq', x, y) } O.gt=function(x,y) { return O.op('gt', x, y) } O.lt=function(x,y) { return O.op('lt', x, y) } // number function O.sqrt=function(x) { return O.op('sqrt', x) } O.log=function(x) { return O.op('log', x) } O.exp=function(x) { return O.op('exp', x) } O.abs=function(x) { return O.op('abs', x) } O.sin=function(x) { return O.op('sin', x) } O.cos=function(x) { return O.op('cos', x) } O.tan=function(x) { return O.op('tan', x) } O.asin=function(x) { return O.op('asin', x) } O.acos=function(x) { return O.op('acos', x) } O.atan=function(x) { return O.op('atan', x) } O.atan2=function(x) { return O.op('atan2', x) } O.ceil=function(x) { return O.op('ceil', x) } O.floor=function(x) { return O.op('floor', x) } O.round=function(x) { return O.op('round', x) } O.parse = function(s) { if (s.indexOf(';')>=0) { var m = split(s, ";"), matrix; for (var i=0; i<m.length; i++) { matrix[i] = O.parse(m[i]); } return matrix; } if (s.indexOf(',')>=0) { var a = split(s, ","), array; for (var i=0; i<a.length; i++) { array[i] = O.parse(a[i]); } return array; } else if (s.indexOf('/')>=0) return O.Ratio.parse(s); else if (s.indexOf('i')>=0) return O.Complex.parse(s); else { return parseFloat(s); } } // =========== Polynomial Ring ============== O.PolynomialRing=extend({}, O.Field); class Polynomial extends O.FieldObj { constructor(c) { super(O.PolynomialRing); this.c = c; // sum(ci x^i) } eval(x) { var c = this.c, i=c.length-1, sum=c[i]; for (i--;i>=0; i--) { sum = c[i].add(x.mul(sum)); } return sum; } size() { return this.c.length } toString() { var s = [], c=this.c; for (var i=c.length-1; i>=0; i--) { s.push(c[i]+'x^'+i); } return s.join('+'); } root() { var p = this.normalize(); // 正規化 switch (this.size()) { case 2:return p.c[0].neg(); case 3:return p.root2(p.c[1], p.c[0]); case 4:return p.root3(p.c[2], p.c[1], p.c[0]); default:throw Error('root() fail'); } } root2(b,c) { // x^2 + bx + c =0 var d = b.mul(b).sub(c.mul(4)).sqrt(); return [b.neg().add(d), b.neg().sub(d)]; } root3(a,b,c) { // x^3+ax^2+bx+c=0 var q=((2*a*a*a/27)-(a*b/3)+c)/2; var p=(b-a*a/3)/3; var D=p*p*p+q*q; var Dsqrt = D.sqrt(), _q=q.neg(); var u_p=_q.add(Dsqrt).power(1/3); // (-q+sqrt(D))^1/3 var u_m=_q.sub(Dsqrt).power(1/3); // (-q-sqrt(D))^1/3 console.log("q=%s p=%s D=%s u+=%s u-=%s", q, p, D, u_p, u_m); var rho_p = (1/2).mul(O.parse('-1+3i')); var rho_m = (1/2).mul(O.parse('-1-3i')); console.log("rho_p=%s rho_m=%s", rho_p, rho_m); var y1=u_p.add(u_m); var y2=rho_p.add(u_p).add(rho_m.mul(u_m)); var y3=rho_p.sub(u_p).add(rho_p.mul(u_m)); return [y1, y2, y3]; } normalize() { var a = this.c[this.size()-1]; var nc = this.c.div(a); return new Polynomial(nc); } } O.Polynomial = Polynomial; /* function root3(a,b,c) { // x^3+ax^2+bx+c=0 var q=((2*a*a*a/27)-(a*b/3)+c/2); var p=(b-a*a/3)/3; var D=p*p*p+q*q; var u_p=Math.sqrt(3, -q+Math.sqrt(D)); var u_m=Math.sqrt(3, -q-Math.sqrt(D)); var rho_p = 1/2*(-1+3i); var rho_m = 1/2*(-1-3i); var y1=u_p+u_m; var y2=rho_p+u_p+ rho_m*u_m; var y3=rho_p-u_p+ rho_p*u_m; } */ O.PolynomialAddGroup={ e:new Polynomial([0]), // 到底應該設幾個? op:function(x,y) { var size = Math.max(x.size(), y.size()); var a=O.vextend(x.c,size), b=O.vextend(y.c,size); var c=O.add(a,b); return new Polynomial(c); }, inv:function(x) { var c = O.neg(x.c); return new Polynomial(c); }, } extend(O.PolynomialAddGroup, O.Group); O.PolynomialMulSemiGroup={ e:new Polynomial([1]), op:function(x,y) { var c=[]; for (var xi=0; xi<x.c.length; xi++) { for (var yi=0; yi<y.c.length; yi++) { var cxy = (typeof c[xi+yi]==='undefined')?0:c[xi+yi]; c[xi+yi] = cxy+x.c[xi]*y.c[yi]; } } return new Polynomial(c); }, inv:function(x) { throw Error('PolynomialMulSemiGroup.inv not defined') }, } extend(O.PolynomialMulSemiGroup, O.Group); O.PolynomialRing.init(O.PolynomialAddGroup, O.PolynomialMulSemiGroup); module.exports = O; },{"./field":4}],2:[function(require,module,exports){ // http://blog.smartbear.com/testing/four-serious-math-libraries-for-javascript/ // Four Serious Math Libraries for JavaScript var B = {}; B.slice = function(a) { return Array.prototype.slice.call(a); } B.bind=function(o, member) { if (typeof o[member]==='Function') return o[member].bind(o); else return o[member]; } B.ncall = function() { var args = B.slice(arguments); var n = args[0]; var o = args[1]; var fname = args[2]; var params = args.slice(3); var a=[]; for (var i=0; i<n; i++) a.push(o[fname].apply(o, params)); return a; } B.mapFunctions=function(host, obj, pairs) { for (var h in pairs) { var o = pairs[h]; if (typeof host[h] !=='undefined') console.log('mapBind: error!', h, ' has been defined!'); host[h]=B.bind(obj, o); } } B.copyFunctions=function(host, obj, names) { for (var name of names) { if (typeof host[name] !=='undefined') console.log('namesBind: error!', name, ' has been defined!'); host[name]=B.bind(obj, name); } } B.mix=function(self, members) { for (var name in members) { var member = members[name]; if (typeof self[name] === 'undefined') { Object.defineProperty(self, name, { enumerable: true, writable: true, value: member, }); } else { console.log("B.mix fail:", name, " already exists!"); } } } B.arg1this = function(f,obj) { // 傳回一個已經綁定 f, obj 的函數 return function() { var args = B.slice(arguments); return f.apply(obj, [this].concat(args)); // 效果相當於 obj.f(this, args) } } B.mixThis=function(proto, obj, fmembers) { for (var fname of fmembers) { var f = obj[fname]; if (typeof proto[fname] === 'undefined') { Object.defineProperty(proto, fname, { enumerable: false, writable: true, value: B.arg1this(f,obj), // proto.f(args) => obj.f(this, args) , 這行盡量不要動,除非想得很清楚了! }); } else { console.log("B.mixThis:", fname, " fail!"); } } } B.mixThisMap=function(proto, obj, poMap) { for (var pname in poMap) { var oname = poMap[pname]; var f = obj[oname]; if (typeof proto[pname] === 'undefined') { Object.defineProperty(proto, pname, { enumerable: false, writable: true, value: B.arg1this(f,obj), // proto.f(args) = f(this, args) , 這行盡量不要動,除非想得很清楚了! }); } else { console.log('pname=', pname, 'proto[pname]=', proto[pname]); console.log("B.mixThisMap:", oname, " fail!"); } } } B.ctrim=function(s, set, side) { side = side||"both"; for (var b=0; b<s.length; b++) if (set.indexOf(s[b])<0) break; for (var e=s.length-1; e>=0; e--) if (set.indexOf(s[e])<0) break; if (side === "right") b=0; if (side === "left") e=s.length-1; return s.substring(b, e+1); } B.lpad=function(s, width, ch) { return s.length >= width ? s : new Array(width - s.length + 1).join(ch) + s; } B.def = function(x, value) { return (typeof x !== 'undefined')?x:value; } B.precision=2; B.nstr = function(n, precision=B.precision) { if (n % 1 === 0) return n.toString(); return n.toFixed(precision); } B.astr = function(a, precision=B.precision) { var s=[]; for (var i in a) { s.push(a[i].str(precision)); } return "["+s.join(', ')+"]"; } B.sstr = function(s) { return s.toString(); } B.ostr = function(o, precision=B.precision) { var s = []; for (var k in o) s.push(k+":"+B.str(o[k], precision)); return "{"+s.join(", ")+"}"; } B.str = function(o, precision=B.precision) { if (typeof o ==='undefined') return 'undefined'; else return o.str(precision); } module.exports = B; /* B.calls = function() { var args = B.slice(arguments); var n = args[0]; var f = args[1]; var params = args.slice(2); var a=[]; for (var i=0; i<n; i++) a.push(f.apply(null, params)); return a; } */ /* B.slice = function(a) { return Array.prototype.slice.call(a); } B.curry = function(f,o) { return function() { var args = Array.prototype.slice.call(arguments); return f.apply(null, [o].concat(args)); } } B.mixThis=function(proto, fmap) { for (var name in fmap) { var f = fmap[name]; if (typeof proto[name] === 'undefined') { Object.defineProperty(proto, name, { enumerable: false, writable: true, value: B.arg1this(f), // proto.f(args) = f(this, args) }); } else { console.log("B.mixThis:", name, " fail!"); } } } B.thisAsArg1 = function(f) { return function() { var args = B.slice(arguments); return f.apply(null, [this].concat(args)); } } */ /* B.mixThis=function(proto, obj, fmembers) { for (var fname of fmembers) { // var f = B.bind(obj, fname); var f = obj[fname]; if (typeof proto[fname] === 'undefined') { Object.defineProperty(proto, fname, { enumerable: false, writable: true, value: B.arg1this(f,obj), // proto.f(args) = f(this, args) }); } else { console.log("B.mixThis:", fname, " fail!"); } } } */ },{}],3:[function(require,module,exports){ module.exports = O = require("./matrix"); // =========== Calculus ================= O.dx = 0.01; // 微分 differential calculus O.fdiff = O.fdifferential = function(f, x, dx) { dx = dx || O.dx; var dy = f(x.add(dx)).sub(f(x.sub(dx))); return dy.div(dx.mul(2)); } // 積分 integral calculus O.fint = O.fintegral = function(f, a, b, dx) { dx = dx || O.dx; var area = 0.0; for (var x=a; x<b; x=x+dx) { area = area + f(x).mul(dx); } return area; } // 偏微分 partial differential calculus // f=[f1,f2,....] , x=[x1,x2,...] , dx=[dx1,dx2,....] O.pdiff = O.pdifferential = function(f, x, i) { f = O.fa(f); var dx = O.vfill(x.length, 0); dx[i] = O.dx; // var df = f.apply(null, x.add(dx)).sub(f.apply(null, x.sub(dx))); var df = f(x.add(dx)).sub(f(x.sub(dx))); return df.div(dx.norm().mul(2)); } // multidimensional integral calculus // f=[f1,f2,....] , a=[a1,a2,...] , b=[b1,b2,....] O.pint = O.pintegral = function(f, a, b) { } // 梯度 gradient : grad(f,x)=[pdiff(f,x,0), .., pdiff(f,x,n)] O.fgrad = O.fgradient = function(f, x) { var gf = []; for (var i=0; i<x.length; i++) { gf[i] = O.pdiff(f, x, i); } return gf; } // 散度 divergence : div(F,x) = sum(pdiff(F[i],x,i)) O.fdiv = O.fdivergence = function(F, x) { var Fx = F(x); var f=[], d=[]; for (var i=0; i<x.length; i++) { f[i] = (xt)=>F(xt)[i]; d[i] = O.pdiff(f[i],x,i); } return d.sum(); } // 旋度 curl : curl(F) = div(F)xF O.fcurl = O.fcurlance = function(F, x) { } // 線積分: int F●dr = int F(r(t))●r'(t) dt O.vint = O.vintegral = function(F, r, a, b, dt) { dt = dt||O.dx; var sum = 0; for (var t=a; t<b; t+=dt) { sum += F(r(t)).dot(r.diff(t)); } return sum; } // 定理:int F●dr = int(sum(Qxi dxi)) // 向量保守場: F=grad(f) ==> int F●dr = f(B)-f(A) // 定理: 向量保守場 F, pdiff(Qxi,xj) == pdiff(Qxj,xi) for any i, j // ex: F=[x^2y, x^3] 中, grad(F)=[x^2, 3x^2] 兩者不相等,所以不是保守場 // 格林定理:保守場中 《線積分=微分後的區域積分》 // int P dx + Q dy = int int pdiff(Q,x) - pdiff(P, y) dx dy // 散度定理:通量 = 散度的區域積分 // 2D : int F●n ds = int int div F dx dy // 3D : int int F●n dS = int int int div F dV // 史托克定理: F 在曲面 S 上的旋度總和 = F 沿著邊界曲線 C 的線積分 // int int_D curl(F)●n dS = int_C F●dr },{"./matrix":8}],4:[function(require,module,exports){ // module : Field & Group Theory var F = require("./set"); F.Integer=require("./integer"); var eq = F.eq; // ========== Group ================= // 注意: 箭頭函數會自動將 this 變數綁定到其定義時所在的物件,因此以下很多地方不能用箭頭函數。 // 參考: https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Functions/Arrow_functions F.Group={ invOp:function(x,y) { return this.op(x,this.inv(y)); }, power:function(x,n) { var p=this.e; for (var i=0;i<n;i++) { p=this.op(p,x); } return p; }, leftCoset:function(g, H) { var set = new F.Set(); for (var i in H) set.add(this.op(g,H[i])); return set; }, rightCoset:function(H, g) { var set = new F.Set(); for (var i in H) set.add(this.op(g,H[i])); return set; }, // ref:https://en.wikipedia.org/wiki/Group_(mathematics) // 封閉性:For all a, b in G, a • b, is also in G closability:function(a,b) { var ab = this.op(a,b); var close=this.has(ab); return this.has(this.op(a,b)); }, // 結合性:For all a, b and c in G, (a • b) • c = a • (b • c). associativity:function(a,b,c) { var op = this.op.bind(this); return eq(op(op(a,b),c), op(a,op(b,c))) }, // 單位元素:Identity element identity:function(a) { return eq(this.op(this.e,a),a) }, // 反元素:Inverse element inversability:function(a) { return eq(this.op(a,this.inv(a)),this.e); }, } // PermutationGroup F.PermutationGroup={ op:function(x,y) { var z = []; for (var i in x) z[i] = y[x[i]]; return z; }, inv:function(x) { var nx = []; for (var i in x) { nx[x[i]] = i; } return nx; }, } extend(F.PermutationGroup, F.Group); // Cyclic Group : a group that is generated by a single element (g) F.CyclicGroup={ G:[], // g:g, op:function(x,y) { }, inv:function(x) { }, create(g) { var t = e; for (var i=0; !t.eq(e); i++) { G[i]=t; t=op(g,G[i]); } } } extend(F.CyclicGroup, F.Group); // NormalSubGroup : 正規子群 F.NormalSubGroup={ op:function(x,y) { }, inv:function(x) { }, normality(g,n) { return this.has(g.op(n).op(g.inv())); }, } extend(F.NormalSubGroup, F.Group); // Quotent Group : aggregating similar elements of a larger group using an equivalence relation that preserves the group structure F.QuotentGroup={ eq:function(x,y) { }, op:function(x,y) { }, inv:function(x) { }, } extend(F.QuotentGroup, F.Group); // Normal SubGroup : gH = Hg // https://en.wikipedia.org/wiki/Normal_subgroup F.NormalSubGroup={ op:function(x,y) { }, inv:function(x) { }, } extend(F.NormalSubGroup, F.Group); // 群同構第一定理: 給定 GG和 G ′ 兩個群,和 f : G → G ′ 群同態。則 Ker ⁡ f 是一個 G 的正規子群。 // 群同構第二定理:給定群 G 、其正規子群 N、其子群 H,則 N ∩ H 是 H 的正規子群,且我們有群同構如下: H / ( H ∩ N ) ≃ H N / N // 群同構第三定理: 給定群 G, N 和 M,M 為 G 的正規子群,滿足 M 包含於 N ,則 N / M 是 G / M 的正規子群,且有如下的群同構: ( G / M ) / ( N / M ) ≃ G / N . // ========== Field ================= F.Field={ sub:function(x,y) { return this.addGroup.invOp(x,y) }, div:function(x,y) { return this.mulGroup.invOp(x,y) }, // mod:function(x,y) { return x.sub(x.div(y).mul(y)) }, power:function(x,n) { return this.mulGroup.power(x,n) }, init:function(addGroup, mulGroup) { this.addGroup = addGroup; this.mulGroup = mulGroup; this.zero = addGroup.e; this.add = function(x,y) { return this.addGroup.op(x,y) } this.neg = function(x) { return this.addGroup.inv(x) } this.one = mulGroup.e; this.mul = function(x,y) { return this.mulGroup.op(x,y) } this.inv = function(x) { return this.mulGroup.inv(x) } this.power= function(x,n) { return this.mulGroup.power(x,n) } this.eq = function(x,y) { return F.eq(x,y); } this.neq = function(x,y) { return !this.eq(x,y); } this.isZero = function(x) { return this.field.eq(this, F.proto(this).zero) } this.isOne = function(x) { return this.field.eq(this, F.proto(this).one) } this.gcd = function(x,y) { if (y.isZero()) return x; return gcd(y, mod(x,y)); } }, ldistribute:function(a,b,c) { return this.mul(a, this.add(b,c)).eq(this.add(this.mul(a,b), this.mul(a,c))); }, rdistribute:function(a,b,c) { return this.ldistribute(b,c,a); }, associativity:function(a,b,c) { return this.mul(a,this.mul(b,c)).eq(this.mul(this.mul(a,b),c)); }, } F.Ring = F.Field; // Ring (環) : 可能沒有乘法單位元素和反元素的 Field F.Module = F.Field;// Module(模) : (R +) is Ring, (R × M → M) F.Ideal = F.Field; // Ideal (理想): 子環,且 i·r ∈ I (左理想), r·i ∈ I (右理想) // ref : https://en.wikipedia.org/wiki/Group_homomorphism // https://en.wikipedia.org/wiki/Fundamental_theorem_on_homomorphisms // 同態:h(a • b) = h(a) x h(b) F.homomorphism=function(h, g1, g2) { var a=g1.random(), b=g2.random(); return eq(h(group1.op(a,b)), group2.op(h(a), h(b))) } // ref : https://en.wikipedia.org/wiki/Isomorphism // https://en.wikipedia.org/wiki/Isomorphism_theorem // 同構:h(a • b) = h(a) • h(b) F.isomorphism=function(h1, h2, g1, g2) { var a1=g1.random(), b1=g2.random(); var a2=g1.random(), b2=g2.random(); return homorphism(h1,g1,g2)&&homorphism(h2,g2,g1); } // ========== Float Field ================= F.FloatAddGroup={ e:0, op:function(x,y) { return x+y }, inv:function(x) { return -x}, } extend(F.FloatAddGroup, F.Group, F.Set.Float); F.FloatMulGroup={ e:1, op:function(x,y) { return x*y }, inv:function(x) { return 1/x}, } extend(F.FloatMulGroup, F.Group, F.Set.Float); F.FloatField=extend({}, F.Field, F.Set.Float); F.FloatField.init(F.FloatAddGroup, F.FloatMulGroup); // ========== Finite Field ================= F.FiniteAddGroup={ e:0, op:function(x,y) { return (x+y)%this.n }, inv:function(x) { return (this.n-x) } } extend(F.FiniteAddGroup, F.Group); F.FiniteMulGroup={ e:1, op:function(x,y) { return (x*y)%this.n }, inv:function(x) { return this.invMap[x] }, setOrder:function(n) { this.n = n; let invMap = new Map(); for (var x=1; x<n; x++) { var y = this.op(x,x); invMap.set(x,y); } this.invMap = invMap; } } extend(F.FiniteMulGroup, F.Group); F.FiniteField=extend({}, F.Field); F.FiniteField.create=function(n) { var finiteField = extend(F.Finite(n), F.FiniteField); var addGroup = extend(F.Finite(n), {n:n}, F.FiniteAddGroup); var mulGroup = extend(F.Finite(n), {n:n}, F.FiniteMulGroup); finiteField.init(addGroup, mulGroup); mulGroup.setOrder(n); return finiteField; } class MathObj { constructor() {} str() { return this.toString() } } F.MathObj = MathObj; // =========== Field Object ============== class FieldObj extends MathObj { constructor(field) { super(); this.field = field; var p = Object.getPrototypeOf(this); p.zero = field.zero; p.one = field.one; } add(y) { return this.field.add(this,y) } mul(y) { return this.field.mul(this,y) } neg() { return this.field.neg(this) } inv() { return this.field.inv(this) } div(y) { return this.field.div(this,y) } sub(y) { return this.field.sub(this,y) } power(n) { return this.field.power(this,n) } isZero(x) { return this.field.isZero(this) } isOne(x) { return this.field.isOne(this) } eq(y) { return this.field.eq(this, y) } neq(y) { return this.field.neq(this, y) } mod(y) { return this.field.mod(this, y) } gcd(y) { return this.field.gcd(this, y) } } F.FieldObj = FieldObj; // =========== Complex Field ============== F.ComplexField=extend({}, F.Field); class Complex extends FieldObj { constructor(a,b) { super(F.ComplexField); this.a = a; this.b = b; } conj() { return new Complex(this.a, -1*this.b); } str() { var op = (this.b<0)?'':'+'; return this.a.str()+op+this.b.str()+'i'; } toString() { return this.str() } toPolar() { var a=this.a, b=this.b, r=Math.sqrt(a*a+b*b); var theta = Math.acos(a/r); return {r:r, theta:theta} } power(k) { var p = this.toPolar(); return Complex.polarToComplex(Math.pow(p.r,k), k*p.theta); } sqrt() { return this.power(1/2); } static toComplex(o) { if (F.isFloat(o)) return new Complex(o, 0); else if (o instanceof Complex) return o; console.log('o=', o); throw Error('toComplex fail'); } static polarToComplex(r,theta) { var a=r*Math.cos(theta), b=r*Math.sin(theta); return new Complex(a, b); } static parse(s) { var m = s.match(/^([^\+]*)(\+(.*))?$/); var a = parseFloat(m[1]); var b = typeof m[3]==='undefined'?1:parseFloat(m[3]); return new Complex(a, b) } } F.Complex = Complex; var C = (a,b)=>new Complex(a,b); var enumComplex=[C(1,0),C(0,1),C(0,0),C(2,3),C(-5,4),C(-10,-7)]; F.ComplexSet=new F.Set(enumComplex); F.ComplexSet.has = (a)=>a instanceof Complex; F.ComplexAddGroup={ e:new Complex(0,0), op:function(x,y) { x = Complex.toComplex(x), y=Complex.toComplex(y); return new Complex(x.a+y.a, x.b+y.b) }, inv:function(x) { x = Complex.toComplex(x); return new Complex(-x.a, -x.b) } } extend(F.ComplexAddGroup, F.Group, F.ComplexSet); F.ComplexMulGroup={ e:new Complex(1,0), op:function(x,y) { x = Complex.toComplex(x), y=Complex.toComplex(y); return new Complex(x.a*y.a-x.b*y.b, x.a*y.b+x.b*y.a); }, inv:function(x) { x = Complex.toComplex(x); var a=x.a,b=x.b, r=(a*a+b*b); return new Complex(a/r, -b/r); } } extend(F.ComplexMulGroup, F.Group, F.ComplexSet); extend(F.ComplexField, F.ComplexSet); F.ComplexField.init(F.ComplexAddGroup, F.ComplexMulGroup); // =========== Ratio Field ============== F.RatioField=extend({}, F.Field); class Ratio extends FieldObj { constructor(a,b) { super(F.RatioField); this.a = a; this.b = b; } reduce() { var a = this.a, b=this.b; var c = F.Integer.gcd(a, b); return new Ratio(a/c, b/c); } toString() { return this.a+'/'+this.b; } static parse(s) { var m = s.match(/^(\d+)(\/(\d+))?$/); var a = parseInt(m[1]); var b = typeof m[3]==='undefined'?1:parseInt(m[3]); return new Ratio(a, b) } } F.Ratio = Ratio; F.RatioAddGroup={ e:new Ratio(0,1), op:function(x,y) { return new Ratio(x.a*y.b+x.b*y.a, x.b*y.b) }, inv:function(x) { return new Ratio(-x.a, x.b); }, } extend(F.RatioAddGroup, F.Group); F.RatioMulGroup={ e:new Ratio(1,1), op:function(x,y) { return new Ratio(x.a*y.a, x.b*y.b) }, inv:function(x) { return new Ratio(x.b, x.a) }, } extend(F.RatioMulGroup, F.Group); F.RatioField.init(F.RatioAddGroup, F.RatioMulGroup); // =========== Function Operation ============== F.fneg=function(fx) { return function(v) { return -1*fx(v); }} F.finv=function(fx) { return function(v) { return 1/fx(v); }} F.fadd=function(fx,fy) { return function(v) { return fx(v).add(fy(v)); }} F.fsub=function(fx,fy) { return function(v) { return fx(v).sub(fy(v)); }} F.fmul=function(fx,fy) { return function(v) { return fx(v).mul(fy(v)); }} F.fdiv=function(fx,fy) { return function(v) { return fx(v).div(fy(v)); }} F.fcompose=function(fx,fy) { return function(v) { return fx(fy(v)); }} F.feval=function(f,x) { return f(x) } // f=(x,y)=>x*y+x*x; // f0=fa(f); f0([x,y]); F.fa=function(f) { return function(x) { return f.apply(null, x); } } // =========== Function Field ============== F.FunctionField=extend({}, F.Field); F.FunctionAddGroup={ e:function(x) { return 0 }, op:function(x,y) { return F.fadd(x,y) }, inv:function(x) { return F.fneg(x) }, } extend(F.FunctionAddGroup, F.Group); F.FunctionMulGroup={ e:function(x) { return f(x) }, op:function(x,y) { return F.fsub(x,y) }, inv:function(x) { return F.finv(x) }, } extend(F.FunctionMulGroup, F.Group); F.FunctionField.init(F.FunctionAddGroup, F.FunctionMulGroup); // Function F.isField=function(x) { return F.isBool(x) || F.isNumber(x) || x instanceof F.FieldObj; } module.exports = F; },{"./integer":6,"./set":9}],5:[function(require,module,exports){ var G = require("./statistics"); // 各種 space : https://en.wikipedia.org/wiki/Space_(mathematics)#/media/File:Mathematical_implication_diagram_eng.jpg G.Space={} // Space = HllbertSpace + BanachSpace + Manifold (流形) G.HilbertSpace={} // HilbertSpace => InnerProductSpace => LocallyConvaxSpace => VectorSpace (LinearSpace) G.InnerProductSpace={} G.LocallyConvaxSpace={} G.LinearSpace=G.VectorSpace={} // (Algebraic) G.BanachSpace={} // BanachSpace => NormedVectorSpace => MetricSpace => TopologicalSpace G.NormedVectorSpace={} G.MetricSpace={} G.TopologicalSpace={} // (Analytic) G.Manifold={} G.Rn = {} // (R,R,....) G.steps = function(from, to, step) { step=step || 1; var a=[]; for (var t=from; t<=to; t+=step) a.push(t); return a; } G.curve=function(f, from=-10, to=10, step=0.1) { var x=G.steps(from, to, step); var y=x.map(f); return { type:"curve", x:x, y:y }; } G.hist=function(a, from, to, step=1) { // console.log("from=%d to=%d step=%d", from, to, step); from = from||a.min(); to = to||a.max(); var n = Math.ceil((to-from+G.EPSILON)/step); var xc = G.steps(from+step/2.0, to, step); // console.log("from=%d to=%d step=%d xc=%j", from, to, step, xc); var bins = G.newV(n, 0); for (var i in a) { var slot=Math.floor((a[i]-from)/step); if (slot>=0 && slot < n) bins[slot]++; } return { type:'histogram', xc:xc, bins:bins, from:from, to:to, step:step}; } /* G.ihist=function(a) { console.log("a.min()=%d a.max()=%d", a.min(), a.max()); return G.hist(a, a.min()-0.5, a.max()+0.5, 1); } */ module.exports=G; },{"./statistics":10}],6:[function(require,module,exports){ var I = {}; I.gcd = function(a, b) { if (!b) return a; return I.gcd(b, a % b); } I.lcm = function(a, b) { return (a * b) / gcd(a, b); } I.isPrime=function(n) { for (var i=2; i<=Math.sqrt(n); i++) if (n%i===0) return false; return n%1===0; } module.exports = I; },{}],7:[function(require,module,exports){ // var M = require("./calculus"); var M = require("./geometry"); module.exports=M; },{"./geometry":5}],8:[function(require,module,exports){ var N = require("numeric"); var M = require("./algebra"); // var M = N; // Advance mathematics M.ode=N.dopri; // dopri(x0,x1,y0,f,tol,maxit,event) #Ordinary Diff Eq M.minimize=N.uncmin; // uncmin(f,x0,tol,gradient,maxit,callback,options) # Unconstrained optimization M.sparse=N.ccsSparse; // Matrix => Sparse M.sparse2full=N.ccsFull; // Sparse => Matrix // M.complex=N.t; // matrix M.svd = N.svd; M.det = N.det; M.inv = N.inv; M.lu = N.cLU; M.luSolve = N.cLUsolve; M.dot = N.dot; M.rep = N.rep; M.tr = N.transpose; M.diag = N.diag; M.mstr = M.strM = N.prettyPrint; // M.sumM = N.sum; M.rows=function(m) { return m.length; } M.cols=function(m) { return m[0].length; } M.row =function(m,i) { return m[i]; } M.col =function(m,j) { var cols = m.cols(); var c = M.vnew(cols); for (var i=0;i<cols;i++) { c[i] = m[i][j]; } return c; } M.newV = function(n, value) { return M.rep([n], value||0); } M.newM = function(rows, cols, value) { return M.rep([rows, cols], value||0); } M.randomV = function(n, a, b) { return N.random([n]).mul(b-a).add(a); } M.randomM = function(rows, cols, a, b) { return N.random([rows, cols]).mul(b-a).add(a); } M.rowSum = function(m) { var rows = M.rows(m); var s=M.newV(rows, 0); for (var i=0; i<rows; i++) { s[i] = m[i].sum(); } return s; } M.colSum = function(m) { var mt = M.tr(m); return M.rowSum(mt); } M.rowMean = function(m) { return M.rowSum(m).div(m.cols()); } M.colMean = function(m) { return M.colSum(m).div(m.rows()); } M.addMV = function(m,v) { var result = []; for(var i=0;i<m.length;i++) { result.push(m[i].add(v)); } return result; } M.mapM = function(m, f) { var fm = M.clone(m); var rows = M.rows(m), cols=M.cols(m); for(i=0;i<rows;i++) { for(j=0;j<cols;j++) fm[i][j]=f(m[i][j]); } return fm; } M.mapMM = function(m1,m2,f) { var fm = M.clone(m1); var rows = m1.rows(), cols=m1.cols(); for(i=0;i<rows;i++) { for(j=0;j<cols;j++) fm[i][j]=f(m1[i][j],m2[i][j]); } return fm; } M.flatM=function(m) { var a=[]; var ai = 0; for (var i=0; i<m.length;i++) for (var j=0; j<m[i].length; j++) a[ai++] = m[i][j]; return a; } M.fillVM=function(v,rows,cols) { var m = M.newM(rows,cols); for (var r=0; r<rows; r++) { for (var c=0; c<cols; c++) { m[r][c] = v[r*cols+c]; } } return m; } M.fillMM=function(m,rows,cols) { var v = M.flatM(m); return M.fillVM(m,rows,cols); } M.eig=function(m) { var E = N.eig(m); return {lambda:E.lambda.x, E:E.E.x}; } module.exports = M; },{"./algebra":1,"numeric":16}],9:[function(require,module,exports){ var S = {} var I = require("./integer"); S.PI = Math.PI; S.E = Math.E; extend = S.extend = Object.assign; // ================= Rule ===================== var check = S.check = S.assert = function(cond, msg) { if (cond) console.log("O:"+msg); else { console.log("X:"+msg); if (S.throwError) throw Error('check fail!'); } } be = S.be =function(msg,cond) { return check(cond, msg) } S.proto=function(o) { return Object.getPrototypeOf(o) } // relation var eq=S.eq=function(a,b) { return (typeof a === typeof b) && a.toString()===b.toString() } S.neq=function(a,b) { return !S.eq(a,b) } S.leq=function(a,b) { return a<=b } S.geq=function(a,b) { return a>=b } S.lt =function(a,b) { return a<b } S.gt =function(a,b) { return a>b } // ========= type checking ================= S.yes=function(a) { return true } S.no=function(a) {return false } S.isBool=function(a) { return typeof a === 'boolean' || a instanceof Boolean } S.isFunction=function(a) { return typeof a==='function' || a instanceof Function } S.isString=function(a) { return typeof a==='string' || a instanceof String } S.isObject=function(a) { return typeof a==='object' || a instanceof Object } S.isArray=function(a) { return a instanceof Array } S.isUndefined=function(a) { return typeof a === 'undefined' } S.isSet=function(a) { return a instanceof Set } S.isFloat=S.isNumber=function(a) { return typeof a === 'number' || a instanceof Number } S.isInteger=function(a) { return S.isFloat(a) && a%1===0 } S.isZero=function(a) { return a===0 } S.isPositive=function(a) { return a>0 } S.isNegative=function(a) { return a<0 } S.isEven=function(a) { return (S.isInteger(a) && a%2===0) } S.isOdd=function(a) { return (S.isInteger(a) && a%2===1) } // ========== Random ============== S.random=function(a,b) { return a+Math.random()*(b-a); } S.randomInt=function(a,b) { return Math.floor(S.random(a,b)); } S.sample=function(a) { return a[S.randomInt(0,a.length)]; } // ========= Set =================== Set.prototype.union = function(setB) { var union = new Set(this); for (var elem of setB) { union.add(elem); } return union; } Set.prototype.intersection = function(setB) { var intersection = new Set(); for (var elem of setB) { if (this.has(elem)) { intersection.add(elem); } } return intersection; } Set.prototype.difference = function(setB) { var difference = new Set(this); for (var elem of setB) { difference.delete(elem); } return difference; } Set.prototype.enumerate = function(n) { var array=[], values = this.values(); for (var i=0; i<n; i++) { array.push(values.next().value); } return array; } class EnumSet { constructor(enumHead) { this.set = new Set(enumHead); this.enumHead = S.isUndefined(enumHead)?[]:enumHead; } add(e) { this.set.add(e) } has(e) { return this.set.has(e) } sample(n) { if (S.isUndefined(n)) return S.sample(this.enumHead); else { var a=[]; for (var i=0; i<n; i++) a.push(this.sample()); return a; } } enumerate() { return this.enumHead } intersection(y) { var x=this, xy=new EnumSet(); xy.has=function(e) { return x.has(e)&&y.has(e) } return xy; } union(y) { var x=this, xy=new EnumSet(); xy.has=function(e) { return x.has(e)||y.has(e) } return xy; } difference(y) { var x=this, xy=new EnumSet(); xy.has=function(e) { return x.has(e)&&!y.has(e) } return xy; } symmetricDifference(y) { var x=this; return x.union(y).difference(x.intersection(y)); } cartesianProduct(y) { var x=this, xy=new EnumSet(); xy.has=function(e) { return x.has(e[0]) && y.has(e[1]) } return xy; } } S.Set = EnumSet function steps(a,b,step) { var array=[]; for (var i=a; i<=b; i+=step) array.push(i); return array; } var enumFloat = [-3.2,-1, 0, 1, 2.3, 4.7]; var enumInt = [-10,-5,-1,0,1,3,5,6]; var enumN0 = steps(0,10,1); var enumN1 = steps(1,10,1); var enumOdd = steps(1,15,2); var enumEven = steps(2,15,2); var enumPrime = [2,3,5,7,11,13,17,19,23,29,31,37]; var enumAll = ["hi", 5, Math.PI, EnumSet, S.isBool, enumPrime, new Set() ]; // 全體集合 S.All = new EnumSet(enumAll); S.All.has = S.yes; // 空集合 S.Empty = new EnumSet([]); S.Empty.has = S.no; // 浮點數集合 S.Float=new EnumSet(enumFloat); S.Float.has=S.isFloat; // 整數集合 S.Z=S.Integer=new EnumSet(enumInt); S.Z.has=S.isInteger; // 自然數集合 N0 S.N0=new EnumSet(enumN0); S.N0.has=(e)=>S.isInteger(e)&&e>=0; // 自然數集合 N1 S.N1=new EnumSet(enumN1); S.N1.has=(e)=>S.isInteger(e)&&e>1; // 偶數集合 S.Even=new EnumSet(enumEven); S.Even.has=S.isEven; // 奇數集合 S.Odd=new EnumSet(enumOdd); S.Odd.has=S.isOdd; // 質數集合 S.Prime=new EnumSet(enumPrime) S.Prime.has=I.isPrime; // 有限集合 0...n-1 S.Finite=(n)=>new EnumSet(steps(0,n-1,1)); // 羅素集合悖論 S.RussellSet=new EnumSet(enumAll); S.RussellSet.has=function(e) { return !e.has(e) } module.exports=S; },{"./integer":6}],10:[function(require,module,exports){ var B = require('./base'); var J = require('jStat').jStat; var S = require('./calculus'); var ncall = B.ncall; // var T, R; // ========== 離散分佈的 r, q 函數 ============ S.qcdf=function(cdf, q, N, p) { for (var i=0; i<=N; i++) { if (cdf(i, N, p) > q) return i; } return N; } S.rcdf=function(cdf, n, N, p) { var a = []; for (var i=0; i<n; i++) { var q = Math.random(); a.push(cdf(q, N, p)); } return a; } S.EPSILON=0.0000000001; // 均等分布 : jStat.uniform( a, b ) S.dunif=(x,a=0,b=1)=>J.uniform.pdf(x,a,b); S.punif=(q,a=0,b=1)=>J.uniform.cdf(q,a,b); S.qunif=(p,a=0,b=1)=>J.uniform.inv(p,a,b); S.runif=(n,a=0,b=1)=>ncall(n, J.uniform, 'sample', a, b); // 常態分布 : jStat.normal( mean, sd ) S.dnorm=(x,mean=0,sd=1)=>J.normal.pdf(x,mean,sd); S.pnorm=(q,mean=0,sd=1)=>J.normal.cdf(q,mean,sd); S.qnorm=(p,mean=0,sd=1)=>J.normal.inv(p,mean,sd); S.rnorm=(n,mean=0,sd=1)=>ncall(n, J.normal, 'sample', mean, sd); // F 分布 : jStat.centralF( df1, df2 ) S.df=(x,df1,df2)=>J.centralF.pdf(x,df1,df2); S.pf=(q,df1,df2)=>J.centralF.cdf(q,df1,df2); S.qf=(p,df1,df2)=>J.centralF.inv(p,df1,df2); S.rf=(n,df1,df2)=>ncall(n, J.centralF, 'sample', df1, df2); // T 分布 : jStat.studentt( dof ) S.dt=(x,dof)=>J.studentt.pdf(x,dof); S.pt=(q,dof)=>J.studentt.cdf(q,dof); S.qt=(p,dof)=>J.studentt.inv(p,dof); S.rt=(n,dof)=>ncall(n, J.studentt, 'sample', dof); // Beta 分布 : jStat.beta( alpha, beta ) S.dbeta=(x,alpha,beta)=>J.beta.pdf(x,alpha,beta); S.pbeta=(q,alpha,beta)=>J.beta.cdf(q,alpha,beta); S.qbeta=(p,alpha,beta)=>J.beta.inv(p,alpha,beta); S.rbeta=(n,alpha,beta)=>ncalls(n, J.beta, 'sample', alpha, beta); // 柯西分布 : jStat.cauchy( local, scale ) S.dcauchy=(x,local,scale)=>J.cauchy.pdf(x,local,scale); S.pcauchy=(q,local,scale)=>J.cauchy.cdf(q,local,scale); S.qcauchy=(p,local,scale)=>J.cauchy.inv(q,local,scale); S.rcauchy=(n,local,scale)=>ncall(n, J.cauchy, 'sample', local, scale); // chisquare 分布 : jStat.chisquare( dof ) S.dchisq=(x,dof)=>J.chisquare.pdf(x,dof); S.pchisq=(q,dof)=>J.chisquare.cdf(q,dof); S.qchisq=(p,dof)=>J.chisquare.inv(p,dof); S.rchisq=(n,dof)=>ncall(n, J.chisquare, 'sample', dof); // 指數分布 : jStat.exponential( rate ) S.dexp=(x,rate)=>J.exponential.pdf(x,rate); S.pexp=(q,rate)=>J.exponential.cdf(q,rate); S.qexp=(p,rate)=>J.exponential.inv(p,rate); S.rexp=(n,rate)=>ncall(n, J.exponential, 'sample', rate); // Gamma 分布 : jStat.gamma( shape, scale ) S.dgamma=(x,shape,scale)=>J.gamma.pdf(x,shape,scale); S.pgamma=(q,shape,scale)=>J.gamma.cdf(q,shape,scale); S.qgamma=(p,shape,scale)=>J.gamma.inv(p,shape,scale); S.rgamma=(n,shape,scale)=>ncall(n, J.gamma, 'sample', shape, scale); // 反 Gamma 分布 : jStat.invgamma( shape, scale ) S.rinvgamma=(n,shape,scale)=>ncall(n, J.invgamma, 'sample', shape, scale); S.dinvgamma=(x,shape,scale)=>J.invgamma.pdf(x,shape,scale); S.pinvgamma=(q,shape,scale)=>J.invgamma.cdf(q,shape,scale); S.qinvgamma=(p,shape,scale)=>J.invgamma.inv(p,shape,scale); // 對數常態分布 : jStat.lognormal( mu, sigma ) S.dlognormal=(n, mu, sigma)=>J.lognormal.pdf(x,sigma); S.plognormal=(n, mu, sigma)=>J.lognormal.cdf(q,sigma); S.qlognormal=(n, mu, sigma)=>J.lognormal.inv(p,sigma); S.rlognormal=(n, mu, sigma)=>ncall(n, J.dlognormal, 'sample', mu, sigma); // Pareto 分布 : jStat.pareto( scale, shape ) S.dpareto=(n, scale, shape)=>J.pareto.pdf(x,scale,shape); S.ppareto=(n, scale, shape)=>J.pareto.cdf(q,scale,shape); S.qpareto=(n, scale, shape)=>J.pareto.inv(p,scale,shape); S.rpareto=(n, scale, shape)=>ncall(n, J.pareto, 'sample', scale, shape); // Weibull 分布 jStat.weibull(scale, shape) S.dweibull=(n, scale, shape)=>J.weibull.pdf(x,scale,shape); S.pweibull=(n, scale, shape)=>J.weibull.cdf(q,scale,shape); S.qweibull=(n, scale, shape)=>J.weibull.inv(p,scale,shape); S.rweibull=(n, scale, shape)=>ncall(n, J.weibull, 'sample', scale, shape); // 三角分布 : jStat.triangular(a, b, c) S.dtriangular=(n, a, b, c)=>J.triangular.pdf(x,a,b,c); S.ptriangular=(n, a, b, c)=>J.triangular.cdf(q,a,b,c); S.qtriangular=(n, a, b, c)=>J.triangular.inv(p,a,b,c); S.rtriangular=(n, a, b, c)=>ncall(n, J.triangular, 'sample', a, b, c); // 類似 Beta 分布,但計算更簡單 : jStat.kumaraswamy(alpha, beta) S.dkumaraswamy=(n, alpha, beta)=>J.kumaraswamy.pdf(x,alpha,beta); S.pkumaraswamy=(n, alpha, beta)=>J.kumaraswamy.cdf(q,alpha,beta); S.qkumaraswamy=(n, alpha, beta)=>J.kumaraswamy.inv(p,alpha,beta); S.rkumaraswamy=(n, alpha, beta)=>ncalls(n, J.kumaraswamy, 'sample', alpha, beta); // ========== 離散分佈的 r, q 函數 ============ // 二項分布 : jStat.binomial(n, p0) S.dbinom=(x, size, prob)=>J.binomial.pdf(x, size, prob); S.pbinom=(q, size, prob)=>J.binomial.cdf(q, size, prob); S.qbinom=(p, size, prob)=>S.qcdf(S.pbinom, p, size, prob); S.rbinom=(n, size, prob)=>S.rcdf(S.qbinom, n, size, prob); // 負二項分布 : jStat.negbin(r, p) S.dnbinom=(x, size, prob)=>J.negbin.pdf(x, size, prob); S.pnbinom=(q, size, prob)=>J.negbin.cdf(q, size, prob); S.qnbinom=(p, size, prob)=>S.qcdf(S.pnbinom, p, size, prob); S.rnbinom=(n, size, prob)=>S.rcdf(S.qnbinom, n, size, prob); // 超幾何分布 : jStat.hypgeom(N, m, n) S.dhyper=(x, m, n, k)=>J.hypgeom.pdf(k, m, n, k); S.phyper=(q, m, n, k)=>J.hypgeom.cdf(q, m, n, k); S.qhyper=(p, m, n, k)=>S.qcdf(S.phyper, p, m, n, k); S.rhyper=(nn,m, n, k)=>S.rcdf(S.qhyper, nn, m, n, k); // 布瓦松分布 : jStat.poisson(l) S.dpois=(x, lambda)=>J.poisson.pdf(x, lambda); S.ppois=(q, lambda)=>J.poisson.cdf(q, lambda); S.qpois=(p, lambda)=>S.qcdf(S.ppois, p, lambda); S.rpois=(n, lambda)=>S.rcdf(S.qpois, n, lambda); // ====================== statistics ================================= // extend function S.normalize=function(a) { var sum = S.sum(a); return a.map(function(x) { return x/sum}); } // Vector Functionality B.copyFunctions(S, J, "sumsqrt,sumsqerr,sumrow,mean,meansqerr,geomean,median,cumsum,cumprod,diff,mode,range,variance,stdev,meandev,meddev,skewness,kurtosis,coeffvar,quartiles,quantiles,percentile,percentileOfScore,histogram,covariance,corrcoeff,calcRdx,betafn,betacf,ibetainv,ibeta,gammafn,gammaln,gammap,lowRegGamma,gammapinv,factorialln,factorial,combination,combinationln,permutation,erf,erfc,erfcinv,randn,randg".split(",")); B.mapFunctions(S, J, { C:'combination',// C(n,m) choose:'combination',// C(n,m) lchoose:'combinationln',// log C(n,m) P:'permutation', // P(n,m) sd:'stdev', cov:'covariance', cor:'corrcoeff', }); // =============== 檢定 ============================== B.mix(S, B); var T = S; T.test = function(o) { // name, D, x, mu, sd, y, alpha, op Object.assign(o, {alpha:0.05, op:"="}); var alpha = o.alpha; var pvalue, interval; var D = o.D; var q1 = D.o2q(o); // 單尾檢定的 pvalue if (o.op === "=") { if (q1>0.5) q1 = 1-q1; // (q1>0.5) 取右尾,否則取左尾。 pvalue= 2*q1; // 對稱情況:雙尾檢定的 p 值是單尾的兩倍。 interval = [D.q2p(alpha/2, o, "L"), D.q2p(1-alpha/2, o, "R")]; } else { if (o.op === "<") { // 右尾檢定 H0: q < 1-alpha, interval = [ D.q2p(alpha, o, "L"), Infinity ]; pvalue = 1-q1; } if (o.op === ">") { // 左尾檢定 H0: q > alpha interval=[-Infinity, D.q2p(1-alpha, o, "R")]; pvalue = q1; } } return { name: o.name, h: D.h(o), alpha: alpha, op: o.op, pvalue: pvalue, ci : interval, df : D.df(o), report: function() { S.report(this) } }; } T.report = function(o) { console.log("=========== report =========="); for (var k in o) { if (typeof o[k] !== "function") console.log(k+"\t: "+S.str(o[k])); } } var t1 = { // 單樣本 T 檢定 t = (X-mu)/(S/sqrt(n)) h:function(o) { return "H0:mu"+o.op+o.mu; }, o2q:function(o) { var x = o.x, n = x.length; var t = (S.mean(x)-o.mu)/(S.sd(x)/Math.sqrt(n)); return S.pt(t, n-1); }, // P(X-mu/(S/sqrt(n))<t) = q ; 信賴區間 P(T<q) // P(mu > X-t*S/sqrt(n)) = q ; 這反而成了右尾檢定,所以左尾與右尾確實會反過來 q2p:function(q, o) { var x = o.x, n = x.length; return S.mean(x) + S.qt(q, n-1) * S.sd(x) / Math.sqrt(n); }, df:function(o) { return o.x.length-1; } } var t2vareq = { // σ1=σ2, 合併 T 檢定 (雙樣本) h:function(o) { return "H0:mu1"+o.op+"mu2" }, // S^2 = (n1-1)*S1^2+(n2-1)*S2^2)/(n1-1+n2-1) sd:function(o) { var x = o.x, n1 = x.length, y=o.y, n2=y.length; var S1= S.sd(x), S2 = S.sd(y); var S = Math.sqrt(((n1-1)*S1*S1+(n2-1)*S2*S2)/(n1-1+n2-1)); return S; }, // T = ((X-Y)-(mu1-mu2))/(sqrt(1/n1+1/n2)*S) o2q:function(o) { var x = o.x, n1 = x.length, y=o.y, n2=y.length; var S = this.sd(o); var t = (S.mean(x)-S.mean(y)-o.mu)/(Math.sqrt(1/n1+1/n2)*S); return S.pt(t, n1+n2-2); }, // t=((X-Y)-mu)/(sqrt(1/n1+1/n2)*S), (X-Y)-t*sqrt(1/n1+1/n2)*S = mu q2p:function(q, o) { var x = o.x, n1 = x.length, y=o.y, n2=y.length; var S = this.sd(o); return S.mean(x)-S.mean(y)+ S.qt(q, n1+n2-2)*Math.sqrt(1/n1+1/n2)*S; }, df:function(o) { var x = o.x, n1 = x.length, y=o.y, n2=y.length; return n1+n2-2; } } var t2paired = { // 成對 T 檢定 T = (X-Y-mu)/(S/sqrt(n)) (雙樣本) h:function(o) { return "H0:mu1"+o.op+"mu2" }, sd:function(o) { // S = sd(x-y) var x = o.x, n = x.length, y=o.y; var S= S.sd(S.sub(x,y)); return S; }, o2q:function(o) { var x = o.x, n = x.length, y=o.y; var S = this.sd(o); var t = (S.mean(S.sub(x,y))-o.mu)/(S/Math.sqrt(n)); return S.pt(t, n-1); }, // mean(x-y)+t*S/sqrt(n) q2p:function(q, o) { var x = o.x, n = x.length, y=o.y; var S = this.sd(o);