Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
| var iota = require("iota-array") | |
| var isBuffer = require("is-buffer") | |
| var hasTypedArrays = ((typeof Float64Array) !== "undefined") | |
| function compare1st(a, b) { | |
| return a[0] - b[0] | |
| } | |
| function order() { | |
| var stride = this.stride | |
| var terms = new Array(stride.length) | |
| var i | |
| for(i=0; i<terms.length; ++i) { | |
| terms[i] = [Math.abs(stride[i]), i] | |
| } | |
| terms.sort(compare1st) | |
| var result = new Array(terms.length) | |
| for(i=0; i<result.length; ++i) { | |
| result[i] = terms[i][1] | |
| } | |
| return result | |
| } | |
| function compileConstructor(dtype, dimension) { | |
| var className = ["View", dimension, "d", dtype].join("") | |
| if(dimension < 0) { | |
| className = "View_Nil" + dtype | |
| } | |
| var useGetters = (dtype === "generic") | |
| if(dimension === -1) { | |
| //Special case for trivial arrays | |
| var code = | |
| "function "+className+"(a){this.data=a;};\ | |
| var proto="+className+".prototype;\ | |
| proto.dtype='"+dtype+"';\ | |
| proto.index=function(){return -1};\ | |
| proto.size=0;\ | |
| proto.dimension=-1;\ | |
| proto.shape=proto.stride=proto.order=[];\ | |
| proto.lo=proto.hi=proto.transpose=proto.step=\ | |
| function(){return new "+className+"(this.data);};\ | |
| proto.get=proto.set=function(){};\ | |
| proto.pick=function(){return null};\ | |
| return function construct_"+className+"(a){return new "+className+"(a);}" | |
| var procedure = new Function(code) | |
| return procedure() | |
| } else if(dimension === 0) { | |
| //Special case for 0d arrays | |
| var code = | |
| "function "+className+"(a,d) {\ | |
| this.data = a;\ | |
| this.offset = d\ | |
| };\ | |
| var proto="+className+".prototype;\ | |
| proto.dtype='"+dtype+"';\ | |
| proto.index=function(){return this.offset};\ | |
| proto.dimension=0;\ | |
| proto.size=1;\ | |
| proto.shape=\ | |
| proto.stride=\ | |
| proto.order=[];\ | |
| proto.lo=\ | |
| proto.hi=\ | |
| proto.transpose=\ | |
| proto.step=function "+className+"_copy() {\ | |
| return new "+className+"(this.data,this.offset)\ | |
| };\ | |
| proto.pick=function "+className+"_pick(){\ | |
| return TrivialArray(this.data);\ | |
| };\ | |
| proto.valueOf=proto.get=function "+className+"_get(){\ | |
| return "+(useGetters ? "this.data.get(this.offset)" : "this.data[this.offset]")+ | |
| "};\ | |
| proto.set=function "+className+"_set(v){\ | |
| return "+(useGetters ? "this.data.set(this.offset,v)" : "this.data[this.offset]=v")+"\ | |
| };\ | |
| return function construct_"+className+"(a,b,c,d){return new "+className+"(a,d)}" | |
| var procedure = new Function("TrivialArray", code) | |
| return procedure(CACHED_CONSTRUCTORS[dtype][0]) | |
| } | |
| var code = ["'use strict'"] | |
| //Create constructor for view | |
| var indices = iota(dimension) | |
| var args = indices.map(function(i) { return "i"+i }) | |
| var index_str = "this.offset+" + indices.map(function(i) { | |
| return "this.stride[" + i + "]*i" + i | |
| }).join("+") | |
| var shapeArg = indices.map(function(i) { | |
| return "b"+i | |
| }).join(",") | |
| var strideArg = indices.map(function(i) { | |
| return "c"+i | |
| }).join(",") | |
| code.push( | |
| "function "+className+"(a," + shapeArg + "," + strideArg + ",d){this.data=a", | |
| "this.shape=[" + shapeArg + "]", | |
| "this.stride=[" + strideArg + "]", | |
| "this.offset=d|0}", | |
| "var proto="+className+".prototype", | |
| "proto.dtype='"+dtype+"'", | |
| "proto.dimension="+dimension) | |
| //view.size: | |
| code.push("Object.defineProperty(proto,'size',{get:function "+className+"_size(){\ | |
| return "+indices.map(function(i) { return "this.shape["+i+"]" }).join("*"), | |
| "}})") | |
| //view.order: | |
| if(dimension === 1) { | |
| code.push("proto.order=[0]") | |
| } else { | |
| code.push("Object.defineProperty(proto,'order',{get:") | |
| if(dimension < 4) { | |
| code.push("function "+className+"_order(){") | |
| if(dimension === 2) { | |
| code.push("return (Math.abs(this.stride[0])>Math.abs(this.stride[1]))?[1,0]:[0,1]}})") | |
| } else if(dimension === 3) { | |
| code.push( | |
| "var s0=Math.abs(this.stride[0]),s1=Math.abs(this.stride[1]),s2=Math.abs(this.stride[2]);\ | |
| if(s0>s1){\ | |
| if(s1>s2){\ | |
| return [2,1,0];\ | |
| }else if(s0>s2){\ | |
| return [1,2,0];\ | |
| }else{\ | |
| return [1,0,2];\ | |
| }\ | |
| }else if(s0>s2){\ | |
| return [2,0,1];\ | |
| }else if(s2>s1){\ | |
| return [0,1,2];\ | |
| }else{\ | |
| return [0,2,1];\ | |
| }}})") | |
| } | |
| } else { | |
| code.push("ORDER})") | |
| } | |
| } | |
| //view.set(i0, ..., v): | |
| code.push( | |
| "proto.set=function "+className+"_set("+args.join(",")+",v){") | |
| if(useGetters) { | |
| code.push("return this.data.set("+index_str+",v)}") | |
| } else { | |
| code.push("return this.data["+index_str+"]=v}") | |
| } | |
| //view.get(i0, ...): | |
| code.push("proto.get=function "+className+"_get("+args.join(",")+"){") | |
| if(useGetters) { | |
| code.push("return this.data.get("+index_str+")}") | |
| } else { | |
| code.push("return this.data["+index_str+"]}") | |
| } | |
| //view.index: | |
| code.push( | |
| "proto.index=function "+className+"_index(", args.join(), "){return "+index_str+"}") | |
| //view.hi(): | |
| code.push("proto.hi=function "+className+"_hi("+args.join(",")+"){return new "+className+"(this.data,"+ | |
| indices.map(function(i) { | |
| return ["(typeof i",i,"!=='number'||i",i,"<0)?this.shape[", i, "]:i", i,"|0"].join("") | |
| }).join(",")+","+ | |
| indices.map(function(i) { | |
| return "this.stride["+i + "]" | |
| }).join(",")+",this.offset)}") | |
| //view.lo(): | |
| var a_vars = indices.map(function(i) { return "a"+i+"=this.shape["+i+"]" }) | |
| var c_vars = indices.map(function(i) { return "c"+i+"=this.stride["+i+"]" }) | |
| code.push("proto.lo=function "+className+"_lo("+args.join(",")+"){var b=this.offset,d=0,"+a_vars.join(",")+","+c_vars.join(",")) | |
| for(var i=0; i<dimension; ++i) { | |
| code.push( | |
| "if(typeof i"+i+"==='number'&&i"+i+">=0){\ | |
| d=i"+i+"|0;\ | |
| b+=c"+i+"*d;\ | |
| a"+i+"-=d}") | |
| } | |
| code.push("return new "+className+"(this.data,"+ | |
| indices.map(function(i) { | |
| return "a"+i | |
| }).join(",")+","+ | |
| indices.map(function(i) { | |
| return "c"+i | |
| }).join(",")+",b)}") | |
| //view.step(): | |
| code.push("proto.step=function "+className+"_step("+args.join(",")+"){var "+ | |
| indices.map(function(i) { | |
| return "a"+i+"=this.shape["+i+"]" | |
| }).join(",")+","+ | |
| indices.map(function(i) { | |
| return "b"+i+"=this.stride["+i+"]" | |
| }).join(",")+",c=this.offset,d=0,ceil=Math.ceil") | |
| for(var i=0; i<dimension; ++i) { | |
| code.push( | |
| "if(typeof i"+i+"==='number'){\ | |
| d=i"+i+"|0;\ | |
| if(d<0){\ | |
| c+=b"+i+"*(a"+i+"-1);\ | |
| a"+i+"=ceil(-a"+i+"/d)\ | |
| }else{\ | |
| a"+i+"=ceil(a"+i+"/d)\ | |
| }\ | |
| b"+i+"*=d\ | |
| }") | |
| } | |
| code.push("return new "+className+"(this.data,"+ | |
| indices.map(function(i) { | |
| return "a" + i | |
| }).join(",")+","+ | |
| indices.map(function(i) { | |
| return "b" + i | |
| }).join(",")+",c)}") | |
| //view.transpose(): | |
| var tShape = new Array(dimension) | |
| var tStride = new Array(dimension) | |
| for(var i=0; i<dimension; ++i) { | |
| tShape[i] = "a[i"+i+"]" | |
| tStride[i] = "b[i"+i+"]" | |
| } | |
| code.push("proto.transpose=function "+className+"_transpose("+args+"){"+ | |
| args.map(function(n,idx) { return n + "=(" + n + "===undefined?" + idx + ":" + n + "|0)"}).join(";"), | |
| "var a=this.shape,b=this.stride;return new "+className+"(this.data,"+tShape.join(",")+","+tStride.join(",")+",this.offset)}") | |
| //view.pick(): | |
| code.push("proto.pick=function "+className+"_pick("+args+"){var a=[],b=[],c=this.offset") | |
| for(var i=0; i<dimension; ++i) { | |
| code.push("if(typeof i"+i+"==='number'&&i"+i+">=0){c=(c+this.stride["+i+"]*i"+i+")|0}else{a.push(this.shape["+i+"]);b.push(this.stride["+i+"])}") | |
| } | |
| code.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}") | |
| //Add return statement | |
| code.push("return function construct_"+className+"(data,shape,stride,offset){return new "+className+"(data,"+ | |
| indices.map(function(i) { | |
| return "shape["+i+"]" | |
| }).join(",")+","+ | |
| indices.map(function(i) { | |
| return "stride["+i+"]" | |
| }).join(",")+",offset)}") | |
| //Compile procedure | |
| var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n")) | |
| return procedure(CACHED_CONSTRUCTORS[dtype], order) | |
| } | |
| function arrayDType(data) { | |
| if(isBuffer(data)) { | |
| return "buffer" | |
| } | |
| if(hasTypedArrays) { | |
| switch(Object.prototype.toString.call(data)) { | |
| case "[object Float64Array]": | |
| return "float64" | |
| case "[object Float32Array]": | |
| return "float32" | |
| case "[object Int8Array]": | |
| return "int8" | |
| case "[object Int16Array]": | |
| return "int16" | |
| case "[object Int32Array]": | |
| return "int32" | |
| case "[object Uint8Array]": | |
| return "uint8" | |
| case "[object Uint16Array]": | |
| return "uint16" | |
| case "[object Uint32Array]": | |
| return "uint32" | |
| case "[object Uint8ClampedArray]": | |
| return "uint8_clamped" | |
| case "[object BigInt64Array]": | |
| return "bigint64" | |
| case "[object BigUint64Array]": | |
| return "biguint64" | |
| } | |
| } | |
| if(Array.isArray(data)) { | |
| return "array" | |
| } | |
| return "generic" | |
| } | |
| var CACHED_CONSTRUCTORS = { | |
| "float32":[], | |
| "float64":[], | |
| "int8":[], | |
| "int16":[], | |
| "int32":[], | |
| "uint8":[], | |
| "uint16":[], | |
| "uint32":[], | |
| "array":[], | |
| "uint8_clamped":[], | |
| "bigint64": [], | |
| "biguint64": [], | |
| "buffer":[], | |
| "generic":[] | |
| } | |
| ;(function() { | |
| for(var id in CACHED_CONSTRUCTORS) { | |
| CACHED_CONSTRUCTORS[id].push(compileConstructor(id, -1)) | |
| } | |
| }); | |
| function wrappedNDArrayCtor(data, shape, stride, offset) { | |
| if(data === undefined) { | |
| var ctor = CACHED_CONSTRUCTORS.array[0] | |
| return ctor([]) | |
| } else if(typeof data === "number") { | |
| data = [data] | |
| } | |
| if(shape === undefined) { | |
| shape = [ data.length ] | |
| } | |
| var d = shape.length | |
| if(stride === undefined) { | |
| stride = new Array(d) | |
| for(var i=d-1, sz=1; i>=0; --i) { | |
| stride[i] = sz | |
| sz *= shape[i] | |
| } | |
| } | |
| if(offset === undefined) { | |
| offset = 0 | |
| for(var i=0; i<d; ++i) { | |
| if(stride[i] < 0) { | |
| offset -= (shape[i]-1)*stride[i] | |
| } | |
| } | |
| } | |
| var dtype = arrayDType(data) | |
| var ctor_list = CACHED_CONSTRUCTORS[dtype] | |
| while(ctor_list.length <= d+1) { | |
| ctor_list.push(compileConstructor(dtype, ctor_list.length-1)) | |
| } | |
| var ctor = ctor_list[d+1] | |
| return ctor(data, shape, stride, offset) | |
| } | |
| module.exports = wrappedNDArrayCtor |