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.
 
 
 
 
StackGenVis/frontend/node_modules/box-intersect/lib/intersect.js

494 lines
12 KiB

'use strict'
module.exports = boxIntersectIter
var pool = require('typedarray-pool')
var bits = require('bit-twiddle')
var bruteForce = require('./brute')
var bruteForcePartial = bruteForce.partial
var bruteForceFull = bruteForce.full
var sweep = require('./sweep')
var findMedian = require('./median')
var genPartition = require('./partition')
//Twiddle parameters
var BRUTE_FORCE_CUTOFF = 128 //Cut off for brute force search
var SCAN_CUTOFF = (1<<22) //Cut off for two way scan
var SCAN_COMPLETE_CUTOFF = (1<<22)
//Partition functions
var partitionInteriorContainsInterval = genPartition(
'!(lo>=p0)&&!(p1>=hi)',
['p0', 'p1'])
var partitionStartEqual = genPartition(
'lo===p0',
['p0'])
var partitionStartLessThan = genPartition(
'lo<p0',
['p0'])
var partitionEndLessThanEqual = genPartition(
'hi<=p0',
['p0'])
var partitionContainsPoint = genPartition(
'lo<=p0&&p0<=hi',
['p0'])
var partitionContainsPointProper = genPartition(
'lo<p0&&p0<=hi',
['p0'])
//Frame size for iterative loop
var IFRAME_SIZE = 6
var DFRAME_SIZE = 2
//Data for box statck
var INIT_CAPACITY = 1024
var BOX_ISTACK = pool.mallocInt32(INIT_CAPACITY)
var BOX_DSTACK = pool.mallocDouble(INIT_CAPACITY)
//Initialize iterative loop queue
function iterInit(d, count) {
var levels = (8 * bits.log2(count+1) * (d+1))|0
var maxInts = bits.nextPow2(IFRAME_SIZE*levels)
if(BOX_ISTACK.length < maxInts) {
pool.free(BOX_ISTACK)
BOX_ISTACK = pool.mallocInt32(maxInts)
}
var maxDoubles = bits.nextPow2(DFRAME_SIZE*levels)
if(BOX_DSTACK.length < maxDoubles) {
pool.free(BOX_DSTACK)
BOX_DSTACK = pool.mallocDouble(maxDoubles)
}
}
//Append item to queue
function iterPush(ptr,
axis,
redStart, redEnd,
blueStart, blueEnd,
state,
lo, hi) {
var iptr = IFRAME_SIZE * ptr
BOX_ISTACK[iptr] = axis
BOX_ISTACK[iptr+1] = redStart
BOX_ISTACK[iptr+2] = redEnd
BOX_ISTACK[iptr+3] = blueStart
BOX_ISTACK[iptr+4] = blueEnd
BOX_ISTACK[iptr+5] = state
var dptr = DFRAME_SIZE * ptr
BOX_DSTACK[dptr] = lo
BOX_DSTACK[dptr+1] = hi
}
//Special case: Intersect single point with list of intervals
function onePointPartial(
d, axis, visit, flip,
redStart, redEnd, red, redIndex,
blueOffset, blue, blueId) {
var elemSize = 2 * d
var bluePtr = blueOffset * elemSize
var blueX = blue[bluePtr + axis]
red_loop:
for(var i=redStart, redPtr=redStart*elemSize; i<redEnd; ++i, redPtr+=elemSize) {
var r0 = red[redPtr+axis]
var r1 = red[redPtr+axis+d]
if(blueX < r0 || r1 < blueX) {
continue
}
if(flip && blueX === r0) {
continue
}
var redId = redIndex[i]
for(var j=axis+1; j<d; ++j) {
var r0 = red[redPtr+j]
var r1 = red[redPtr+j+d]
var b0 = blue[bluePtr+j]
var b1 = blue[bluePtr+j+d]
if(r1 < b0 || b1 < r0) {
continue red_loop
}
}
var retval
if(flip) {
retval = visit(blueId, redId)
} else {
retval = visit(redId, blueId)
}
if(retval !== void 0) {
return retval
}
}
}
//Special case: Intersect one point with list of intervals
function onePointFull(
d, axis, visit,
redStart, redEnd, red, redIndex,
blueOffset, blue, blueId) {
var elemSize = 2 * d
var bluePtr = blueOffset * elemSize
var blueX = blue[bluePtr + axis]
red_loop:
for(var i=redStart, redPtr=redStart*elemSize; i<redEnd; ++i, redPtr+=elemSize) {
var redId = redIndex[i]
if(redId === blueId) {
continue
}
var r0 = red[redPtr+axis]
var r1 = red[redPtr+axis+d]
if(blueX < r0 || r1 < blueX) {
continue
}
for(var j=axis+1; j<d; ++j) {
var r0 = red[redPtr+j]
var r1 = red[redPtr+j+d]
var b0 = blue[bluePtr+j]
var b1 = blue[bluePtr+j+d]
if(r1 < b0 || b1 < r0) {
continue red_loop
}
}
var retval = visit(redId, blueId)
if(retval !== void 0) {
return retval
}
}
}
//The main box intersection routine
function boxIntersectIter(
d, visit, initFull,
xSize, xBoxes, xIndex,
ySize, yBoxes, yIndex) {
//Reserve memory for stack
iterInit(d, xSize + ySize)
var top = 0
var elemSize = 2 * d
var retval
iterPush(top++,
0,
0, xSize,
0, ySize,
initFull ? 16 : 0,
-Infinity, Infinity)
if(!initFull) {
iterPush(top++,
0,
0, ySize,
0, xSize,
1,
-Infinity, Infinity)
}
while(top > 0) {
top -= 1
var iptr = top * IFRAME_SIZE
var axis = BOX_ISTACK[iptr]
var redStart = BOX_ISTACK[iptr+1]
var redEnd = BOX_ISTACK[iptr+2]
var blueStart = BOX_ISTACK[iptr+3]
var blueEnd = BOX_ISTACK[iptr+4]
var state = BOX_ISTACK[iptr+5]
var dptr = top * DFRAME_SIZE
var lo = BOX_DSTACK[dptr]
var hi = BOX_DSTACK[dptr+1]
//Unpack state info
var flip = (state & 1)
var full = !!(state & 16)
//Unpack indices
var red = xBoxes
var redIndex = xIndex
var blue = yBoxes
var blueIndex = yIndex
if(flip) {
red = yBoxes
redIndex = yIndex
blue = xBoxes
blueIndex = xIndex
}
if(state & 2) {
redEnd = partitionStartLessThan(
d, axis,
redStart, redEnd, red, redIndex,
hi)
if(redStart >= redEnd) {
continue
}
}
if(state & 4) {
redStart = partitionEndLessThanEqual(
d, axis,
redStart, redEnd, red, redIndex,
lo)
if(redStart >= redEnd) {
continue
}
}
var redCount = redEnd - redStart
var blueCount = blueEnd - blueStart
if(full) {
if(d * redCount * (redCount + blueCount) < SCAN_COMPLETE_CUTOFF) {
retval = sweep.scanComplete(
d, axis, visit,
redStart, redEnd, red, redIndex,
blueStart, blueEnd, blue, blueIndex)
if(retval !== void 0) {
return retval
}
continue
}
} else {
if(d * Math.min(redCount, blueCount) < BRUTE_FORCE_CUTOFF) {
//If input small, then use brute force
retval = bruteForcePartial(
d, axis, visit, flip,
redStart, redEnd, red, redIndex,
blueStart, blueEnd, blue, blueIndex)
if(retval !== void 0) {
return retval
}
continue
} else if(d * redCount * blueCount < SCAN_CUTOFF) {
//If input medium sized, then use sweep and prune
retval = sweep.scanBipartite(
d, axis, visit, flip,
redStart, redEnd, red, redIndex,
blueStart, blueEnd, blue, blueIndex)
if(retval !== void 0) {
return retval
}
continue
}
}
//First, find all red intervals whose interior contains (lo,hi)
var red0 = partitionInteriorContainsInterval(
d, axis,
redStart, redEnd, red, redIndex,
lo, hi)
//Lower dimensional case
if(redStart < red0) {
if(d * (red0 - redStart) < BRUTE_FORCE_CUTOFF) {
//Special case for small inputs: use brute force
retval = bruteForceFull(
d, axis+1, visit,
redStart, red0, red, redIndex,
blueStart, blueEnd, blue, blueIndex)
if(retval !== void 0) {
return retval
}
} else if(axis === d-2) {
if(flip) {
retval = sweep.sweepBipartite(
d, visit,
blueStart, blueEnd, blue, blueIndex,
redStart, red0, red, redIndex)
} else {
retval = sweep.sweepBipartite(
d, visit,
redStart, red0, red, redIndex,
blueStart, blueEnd, blue, blueIndex)
}
if(retval !== void 0) {
return retval
}
} else {
iterPush(top++,
axis+1,
redStart, red0,
blueStart, blueEnd,
flip,
-Infinity, Infinity)
iterPush(top++,
axis+1,
blueStart, blueEnd,
redStart, red0,
flip^1,
-Infinity, Infinity)
}
}
//Divide and conquer phase
if(red0 < redEnd) {
//Cut blue into 3 parts:
//
// Points < mid point
// Points = mid point
// Points > mid point
//
var blue0 = findMedian(
d, axis,
blueStart, blueEnd, blue, blueIndex)
var mid = blue[elemSize * blue0 + axis]
var blue1 = partitionStartEqual(
d, axis,
blue0, blueEnd, blue, blueIndex,
mid)
//Right case
if(blue1 < blueEnd) {
iterPush(top++,
axis,
red0, redEnd,
blue1, blueEnd,
(flip|4) + (full ? 16 : 0),
mid, hi)
}
//Left case
if(blueStart < blue0) {
iterPush(top++,
axis,
red0, redEnd,
blueStart, blue0,
(flip|2) + (full ? 16 : 0),
lo, mid)
}
//Center case (the hard part)
if(blue0 + 1 === blue1) {
//Optimization: Range with exactly 1 point, use a brute force scan
if(full) {
retval = onePointFull(
d, axis, visit,
red0, redEnd, red, redIndex,
blue0, blue, blueIndex[blue0])
} else {
retval = onePointPartial(
d, axis, visit, flip,
red0, redEnd, red, redIndex,
blue0, blue, blueIndex[blue0])
}
if(retval !== void 0) {
return retval
}
} else if(blue0 < blue1) {
var red1
if(full) {
//If full intersection, need to handle special case
red1 = partitionContainsPoint(
d, axis,
red0, redEnd, red, redIndex,
mid)
if(red0 < red1) {
var redX = partitionStartEqual(
d, axis,
red0, red1, red, redIndex,
mid)
if(axis === d-2) {
//Degenerate sweep intersection:
// [red0, redX] with [blue0, blue1]
if(red0 < redX) {
retval = sweep.sweepComplete(
d, visit,
red0, redX, red, redIndex,
blue0, blue1, blue, blueIndex)
if(retval !== void 0) {
return retval
}
}
//Normal sweep intersection:
// [redX, red1] with [blue0, blue1]
if(redX < red1) {
retval = sweep.sweepBipartite(
d, visit,
redX, red1, red, redIndex,
blue0, blue1, blue, blueIndex)
if(retval !== void 0) {
return retval
}
}
} else {
if(red0 < redX) {
iterPush(top++,
axis+1,
red0, redX,
blue0, blue1,
16,
-Infinity, Infinity)
}
if(redX < red1) {
iterPush(top++,
axis+1,
redX, red1,
blue0, blue1,
0,
-Infinity, Infinity)
iterPush(top++,
axis+1,
blue0, blue1,
redX, red1,
1,
-Infinity, Infinity)
}
}
}
} else {
if(flip) {
red1 = partitionContainsPointProper(
d, axis,
red0, redEnd, red, redIndex,
mid)
} else {
red1 = partitionContainsPoint(
d, axis,
red0, redEnd, red, redIndex,
mid)
}
if(red0 < red1) {
if(axis === d-2) {
if(flip) {
retval = sweep.sweepBipartite(
d, visit,
blue0, blue1, blue, blueIndex,
red0, red1, red, redIndex)
} else {
retval = sweep.sweepBipartite(
d, visit,
red0, red1, red, redIndex,
blue0, blue1, blue, blueIndex)
}
} else {
iterPush(top++,
axis+1,
red0, red1,
blue0, blue1,
flip,
-Infinity, Infinity)
iterPush(top++,
axis+1,
blue0, blue1,
red0, red1,
flip^1,
-Infinity, Infinity)
}
}
}
}
}
}
}