| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- 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
|