StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
4.4 KiB
152 lines
4.4 KiB
"use strict"
|
|
|
|
var pool = require("typedarray-pool")
|
|
var ops = require("ndarray-ops")
|
|
var ndarray = require("ndarray")
|
|
|
|
var SUPPORTED_TYPES = [
|
|
"uint8",
|
|
"uint8_clamped",
|
|
"uint16",
|
|
"uint32",
|
|
"int8",
|
|
"int16",
|
|
"int32",
|
|
"float32" ]
|
|
|
|
function GLBuffer(gl, type, handle, length, usage) {
|
|
this.gl = gl
|
|
this.type = type
|
|
this.handle = handle
|
|
this.length = length
|
|
this.usage = usage
|
|
}
|
|
|
|
var proto = GLBuffer.prototype
|
|
|
|
proto.bind = function() {
|
|
this.gl.bindBuffer(this.type, this.handle)
|
|
}
|
|
|
|
proto.unbind = function() {
|
|
this.gl.bindBuffer(this.type, null)
|
|
}
|
|
|
|
proto.dispose = function() {
|
|
this.gl.deleteBuffer(this.handle)
|
|
}
|
|
|
|
function updateTypeArray(gl, type, len, usage, data, offset) {
|
|
var dataLen = data.length * data.BYTES_PER_ELEMENT
|
|
if(offset < 0) {
|
|
gl.bufferData(type, data, usage)
|
|
return dataLen
|
|
}
|
|
if(dataLen + offset > len) {
|
|
throw new Error("gl-buffer: If resizing buffer, must not specify offset")
|
|
}
|
|
gl.bufferSubData(type, offset, data)
|
|
return len
|
|
}
|
|
|
|
function makeScratchTypeArray(array, dtype) {
|
|
var res = pool.malloc(array.length, dtype)
|
|
var n = array.length
|
|
for(var i=0; i<n; ++i) {
|
|
res[i] = array[i]
|
|
}
|
|
return res
|
|
}
|
|
|
|
function isPacked(shape, stride) {
|
|
var n = 1
|
|
for(var i=stride.length-1; i>=0; --i) {
|
|
if(stride[i] !== n) {
|
|
return false
|
|
}
|
|
n *= shape[i]
|
|
}
|
|
return true
|
|
}
|
|
|
|
proto.update = function(array, offset) {
|
|
if(typeof offset !== "number") {
|
|
offset = -1
|
|
}
|
|
this.bind()
|
|
if(typeof array === "object" && typeof array.shape !== "undefined") { //ndarray
|
|
var dtype = array.dtype
|
|
if(SUPPORTED_TYPES.indexOf(dtype) < 0) {
|
|
dtype = "float32"
|
|
}
|
|
if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) {
|
|
var ext = gl.getExtension('OES_element_index_uint')
|
|
if(ext && dtype !== "uint16") {
|
|
dtype = "uint32"
|
|
} else {
|
|
dtype = "uint16"
|
|
}
|
|
}
|
|
if(dtype === array.dtype && isPacked(array.shape, array.stride)) {
|
|
if(array.offset === 0 && array.data.length === array.shape[0]) {
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data, offset)
|
|
} else {
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data.subarray(array.offset, array.shape[0]), offset)
|
|
}
|
|
} else {
|
|
var tmp = pool.malloc(array.size, dtype)
|
|
var ndt = ndarray(tmp, array.shape)
|
|
ops.assign(ndt, array)
|
|
if(offset < 0) {
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp, offset)
|
|
} else {
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp.subarray(0, array.size), offset)
|
|
}
|
|
pool.free(tmp)
|
|
}
|
|
} else if(Array.isArray(array)) { //Vanilla array
|
|
var t
|
|
if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) {
|
|
t = makeScratchTypeArray(array, "uint16")
|
|
} else {
|
|
t = makeScratchTypeArray(array, "float32")
|
|
}
|
|
if(offset < 0) {
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t, offset)
|
|
} else {
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t.subarray(0, array.length), offset)
|
|
}
|
|
pool.free(t)
|
|
} else if(typeof array === "object" && typeof array.length === "number") { //Typed array
|
|
this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array, offset)
|
|
} else if(typeof array === "number" || array === undefined) { //Number/default
|
|
if(offset >= 0) {
|
|
throw new Error("gl-buffer: Cannot specify offset when resizing buffer")
|
|
}
|
|
array = array | 0
|
|
if(array <= 0) {
|
|
array = 1
|
|
}
|
|
this.gl.bufferData(this.type, array|0, this.usage)
|
|
this.length = array
|
|
} else { //Error, case should not happen
|
|
throw new Error("gl-buffer: Invalid data type")
|
|
}
|
|
}
|
|
|
|
function createBuffer(gl, data, type, usage) {
|
|
type = type || gl.ARRAY_BUFFER
|
|
usage = usage || gl.DYNAMIC_DRAW
|
|
if(type !== gl.ARRAY_BUFFER && type !== gl.ELEMENT_ARRAY_BUFFER) {
|
|
throw new Error("gl-buffer: Invalid type for webgl buffer, must be either gl.ARRAY_BUFFER or gl.ELEMENT_ARRAY_BUFFER")
|
|
}
|
|
if(usage !== gl.DYNAMIC_DRAW && usage !== gl.STATIC_DRAW && usage !== gl.STREAM_DRAW) {
|
|
throw new Error("gl-buffer: Invalid usage for buffer, must be either gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW")
|
|
}
|
|
var handle = gl.createBuffer()
|
|
var result = new GLBuffer(gl, type, handle, 0, usage)
|
|
result.update(data)
|
|
return result
|
|
}
|
|
|
|
module.exports = createBuffer
|
|
|