vega-crossfilter
Advanced tools
Comparing version 4.0.2 to 4.0.3
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array'), require('vega-dataflow'), require('vega-util')) : | ||
typeof define === 'function' && define.amd ? define(['exports', 'd3-array', 'vega-dataflow', 'vega-util'], factory) : | ||
(global = global || self, factory((global.vega = global.vega || {}, global.vega.transforms = {}), global.d3, global.vega, global.vega)); | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.vega = global.vega || {}, global.vega.transforms = {}), global.d3, global.vega, global.vega)); | ||
}(this, (function (exports, d3Array, vegaDataflow, vegaUtil) { 'use strict'; | ||
function array8(n) { return new Uint8Array(n); } | ||
const array8 = n => new Uint8Array(n); | ||
function array16(n) { return new Uint16Array(n); } | ||
const array16 = n => new Uint16Array(n); | ||
function array32(n) { return new Uint32Array(n); } | ||
const array32 = n => new Uint32Array(n); | ||
@@ -18,3 +18,3 @@ /** | ||
var width = 8, | ||
let width = 8, | ||
data = [], | ||
@@ -26,11 +26,8 @@ seen = array32(0), | ||
return { | ||
data: () => data, | ||
data: function() { return data; }, | ||
seen: () => (seen = lengthen(seen, data.length)), | ||
seen: function() { | ||
return (seen = lengthen(seen, data.length)); | ||
}, | ||
add: function(array) { | ||
for (var i=0, j=data.length, n=array.length, t; i<n; ++i) { | ||
add(array) { | ||
for (let i=0, j=data.length, n=array.length, t; i<n; ++i) { | ||
t = array[i]; | ||
@@ -42,4 +39,4 @@ t._index = j++; | ||
remove: function(num, map) { // map: index -> boolean (true => remove) | ||
var n = data.length, | ||
remove(num, map) { // map: index -> boolean (true => remove) | ||
let n = data.length, | ||
copy = Array(n - num), | ||
@@ -74,20 +71,19 @@ reindex = data, // reuse old data array for index map | ||
size: function() { return data.length; }, | ||
size: () => data.length, | ||
curr: function() { return curr; }, | ||
curr: () => curr, | ||
prev: function() { return prev; }, | ||
prev: () => prev, | ||
reset: function(k) { prev[k] = curr[k]; }, | ||
reset: k => prev[k] = curr[k], | ||
all: function() { | ||
return width < 0x101 ? 0xff : width < 0x10001 ? 0xffff : 0xffffffff; | ||
}, | ||
all: () => | ||
width < 0x101 ? 0xff : width < 0x10001 ? 0xffff : 0xffffffff, | ||
set: function(k, one) { curr[k] |= one; }, | ||
set(k, one) { curr[k] |= one; }, | ||
clear: function(k, one) { curr[k] &= ~one; }, | ||
clear(k, one) { curr[k] &= ~one; }, | ||
resize: function(n, m) { | ||
var k = curr.length; | ||
resize(n, m) { | ||
const k = curr.length; | ||
if (n > k || m > width) { | ||
@@ -110,3 +106,5 @@ width = Math.max(m, width); | ||
function array(n, m, array) { | ||
var copy = (m < 0x101 ? array8 : m < 0x10001 ? array16 : array32)(n); | ||
const copy = (m < 0x101 ? array8 | ||
: m < 0x10001 ? array16 | ||
: array32)(n); | ||
if (array) copy.set(array); | ||
@@ -117,3 +115,3 @@ return copy; | ||
function Dimension(index, i, query) { | ||
var bit = (1 << i); | ||
const bit = (1 << i); | ||
@@ -128,4 +126,4 @@ return { | ||
onAdd: function(added, curr) { | ||
var dim = this, | ||
onAdd(added, curr) { | ||
let dim = this, | ||
range = dim.bisect(dim.range, added.value), | ||
@@ -148,3 +146,3 @@ idx = added.index, | ||
function SortedIndex() { | ||
var index = array32(0), | ||
let index = array32(0), | ||
value = [], | ||
@@ -156,3 +154,3 @@ size = 0; | ||
var n0 = size, | ||
let n0 = size, | ||
n1 = data.length, | ||
@@ -189,3 +187,3 @@ addv = Array(n1), | ||
// map: index -> remove | ||
var n = size, | ||
let n = size, | ||
idx, i, j; | ||
@@ -209,3 +207,3 @@ | ||
function reindex(map) { | ||
for (var i=0, n=size; i<n; ++i) { | ||
for (let i=0, n=size; i<n; ++i) { | ||
index[i] = map[index[i]]; | ||
@@ -216,3 +214,3 @@ } | ||
function bisect(range, array) { | ||
var n; | ||
let n; | ||
if (array) { | ||
@@ -235,4 +233,4 @@ n = array.length; | ||
reindex: reindex, | ||
index: function() { return index; }, | ||
size: function() { return size; } | ||
index: () => index, | ||
size: () => size | ||
}; | ||
@@ -242,5 +240,5 @@ } | ||
function sort(values, index) { | ||
values.sort.call(index, function(a, b) { | ||
var x = values[a], | ||
y = values[b]; | ||
values.sort.call(index, (a, b) => { | ||
const x = values[a], | ||
y = values[b]; | ||
return x < y ? -1 : x > y ? 1 : 0; | ||
@@ -252,3 +250,3 @@ }); | ||
function merge(base, value0, index0, n0, value1, index1, n1, value, index) { | ||
var i0 = 0, i1 = 0, i; | ||
let i0 = 0, i1 = 0, i; | ||
@@ -299,358 +297,358 @@ for (i=0; i0 < n0 && i1 < n1; ++i) { | ||
var prototype = vegaUtil.inherits(CrossFilter, vegaDataflow.Transform); | ||
vegaUtil.inherits(CrossFilter, vegaDataflow.Transform, { | ||
transform(_, pulse) { | ||
if (!this._dims) { | ||
return this.init(_, pulse); | ||
} else { | ||
var init = _.modified('fields') | ||
|| _.fields.some(f => pulse.modified(f.fields)); | ||
prototype.transform = function(_, pulse) { | ||
if (!this._dims) { | ||
return this.init(_, pulse); | ||
} else { | ||
var init = _.modified('fields') | ||
|| _.fields.some(function(f) { return pulse.modified(f.fields); }); | ||
return init | ||
? this.reinit(_, pulse) | ||
: this.eval(_, pulse); | ||
} | ||
}, | ||
return init | ||
? this.reinit(_, pulse) | ||
: this.eval(_, pulse); | ||
} | ||
}; | ||
init(_, pulse) { | ||
let fields = _.fields, | ||
query = _.query, | ||
indices = this._indices = {}, | ||
dims = this._dims = [], | ||
m = query.length, | ||
i = 0, key, index; | ||
prototype.init = function(_, pulse) { | ||
var fields = _.fields, | ||
query = _.query, | ||
indices = this._indices = {}, | ||
dims = this._dims = [], | ||
m = query.length, | ||
i = 0, key, index; | ||
// instantiate indices and dimensions | ||
for (; i<m; ++i) { | ||
key = fields[i].fname; | ||
index = indices[key] || (indices[key] = SortedIndex()); | ||
dims.push(Dimension(index, i, query[i])); | ||
} | ||
// instantiate indices and dimensions | ||
for (; i<m; ++i) { | ||
key = fields[i].fname; | ||
index = indices[key] || (indices[key] = SortedIndex()); | ||
dims.push(Dimension(index, i, query[i])); | ||
} | ||
return this.eval(_, pulse); | ||
}, | ||
return this.eval(_, pulse); | ||
}; | ||
reinit(_, pulse) { | ||
let output = pulse.materialize().fork(), | ||
fields = _.fields, | ||
query = _.query, | ||
indices = this._indices, | ||
dims = this._dims, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(), | ||
out = (output.rem = output.add), | ||
mod = output.mod, | ||
m = query.length, | ||
adds = {}, add, index, key, | ||
mods, remMap, modMap, i, n, f; | ||
prototype.reinit = function(_, pulse) { | ||
var output = pulse.materialize().fork(), | ||
fields = _.fields, | ||
query = _.query, | ||
indices = this._indices, | ||
dims = this._dims, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(), | ||
out = (output.rem = output.add), | ||
mod = output.mod, | ||
m = query.length, | ||
adds = {}, add, index, key, | ||
mods, remMap, modMap, i, n, f; | ||
// set prev to current state | ||
prev.set(curr); | ||
// set prev to current state | ||
prev.set(curr); | ||
// if pulse has remove tuples, process them first | ||
if (pulse.rem.length) { | ||
remMap = this.remove(_, pulse, output); | ||
} | ||
// if pulse has remove tuples, process them first | ||
if (pulse.rem.length) { | ||
remMap = this.remove(_, pulse, output); | ||
} | ||
// if pulse has added tuples, add them to state | ||
if (pulse.add.length) { | ||
bits.add(pulse.add); | ||
} | ||
// if pulse has added tuples, add them to state | ||
if (pulse.add.length) { | ||
bits.add(pulse.add); | ||
} | ||
// if pulse has modified tuples, create an index map | ||
if (pulse.mod.length) { | ||
modMap = {}; | ||
for (mods=pulse.mod, i=0, n=mods.length; i<n; ++i) { | ||
modMap[mods[i]._index] = 1; | ||
// if pulse has modified tuples, create an index map | ||
if (pulse.mod.length) { | ||
modMap = {}; | ||
for (mods=pulse.mod, i=0, n=mods.length; i<n; ++i) { | ||
modMap[mods[i]._index] = 1; | ||
} | ||
} | ||
} | ||
// re-initialize indices as needed, update curr bitmap | ||
for (i=0; i<m; ++i) { | ||
f = fields[i]; | ||
if (!dims[i] || _.modified('fields', i) || pulse.modified(f.fields)) { | ||
key = f.fname; | ||
if (!(add = adds[key])) { | ||
indices[key] = index = SortedIndex(); | ||
adds[key] = add = index.insert(f, pulse.source, 0); | ||
// re-initialize indices as needed, update curr bitmap | ||
for (i=0; i<m; ++i) { | ||
f = fields[i]; | ||
if (!dims[i] || _.modified('fields', i) || pulse.modified(f.fields)) { | ||
key = f.fname; | ||
if (!(add = adds[key])) { | ||
indices[key] = index = SortedIndex(); | ||
adds[key] = add = index.insert(f, pulse.source, 0); | ||
} | ||
dims[i] = Dimension(index, i, query[i]).onAdd(add, curr); | ||
} | ||
dims[i] = Dimension(index, i, query[i]).onAdd(add, curr); | ||
} | ||
} | ||
// visit each tuple | ||
// if filter state changed, push index to add/rem | ||
// else if in mod and passes a filter, push index to mod | ||
for (i=0, n=bits.data().length; i<n; ++i) { | ||
if (remMap[i]) { // skip if removed tuple | ||
continue; | ||
} else if (prev[i] !== curr[i]) { // add if state changed | ||
out.push(i); | ||
} else if (modMap[i] && curr[i] !== all) { // otherwise, pass mods through | ||
mod.push(i); | ||
// visit each tuple | ||
// if filter state changed, push index to add/rem | ||
// else if in mod and passes a filter, push index to mod | ||
for (i=0, n=bits.data().length; i<n; ++i) { | ||
if (remMap[i]) { // skip if removed tuple | ||
continue; | ||
} else if (prev[i] !== curr[i]) { // add if state changed | ||
out.push(i); | ||
} else if (modMap[i] && curr[i] !== all) { // otherwise, pass mods through | ||
mod.push(i); | ||
} | ||
} | ||
} | ||
bits.mask = (1 << m) - 1; | ||
return output; | ||
}; | ||
bits.mask = (1 << m) - 1; | ||
return output; | ||
}, | ||
prototype.eval = function(_, pulse) { | ||
var output = pulse.materialize().fork(), | ||
m = this._dims.length, | ||
mask = 0; | ||
eval(_, pulse) { | ||
let output = pulse.materialize().fork(), | ||
m = this._dims.length, | ||
mask = 0; | ||
if (pulse.rem.length) { | ||
this.remove(_, pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
if (pulse.rem.length) { | ||
this.remove(_, pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
if (_.modified('query') && !_.modified('fields')) { | ||
mask |= this.update(_, pulse, output); | ||
} | ||
if (_.modified('query') && !_.modified('fields')) { | ||
mask |= this.update(_, pulse, output); | ||
} | ||
if (pulse.add.length) { | ||
this.insert(_, pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
if (pulse.add.length) { | ||
this.insert(_, pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
if (pulse.mod.length) { | ||
this.modify(pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
if (pulse.mod.length) { | ||
this.modify(pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
this.value.mask = mask; | ||
return output; | ||
}; | ||
this.value.mask = mask; | ||
return output; | ||
}, | ||
prototype.insert = function(_, pulse, output) { | ||
var tuples = pulse.add, | ||
bits = this.value, | ||
dims = this._dims, | ||
indices = this._indices, | ||
fields = _.fields, | ||
adds = {}, | ||
out = output.add, | ||
k = bits.size(), | ||
n = k + tuples.length, | ||
m = dims.length, j, key, add; | ||
insert(_, pulse, output) { | ||
let tuples = pulse.add, | ||
bits = this.value, | ||
dims = this._dims, | ||
indices = this._indices, | ||
fields = _.fields, | ||
adds = {}, | ||
out = output.add, | ||
k = bits.size(), | ||
n = k + tuples.length, | ||
m = dims.length, j, key, add; | ||
// resize bitmaps and add tuples as needed | ||
bits.resize(n, m); | ||
bits.add(tuples); | ||
// resize bitmaps and add tuples as needed | ||
bits.resize(n, m); | ||
bits.add(tuples); | ||
var curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(); | ||
const curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(); | ||
// add to dimensional indices | ||
for (j=0; j<m; ++j) { | ||
key = fields[j].fname; | ||
add = adds[key] || (adds[key] = indices[key].insert(fields[j], tuples, k)); | ||
dims[j].onAdd(add, curr); | ||
} | ||
// add to dimensional indices | ||
for (j=0; j<m; ++j) { | ||
key = fields[j].fname; | ||
add = adds[key] || (adds[key] = indices[key].insert(fields[j], tuples, k)); | ||
dims[j].onAdd(add, curr); | ||
} | ||
// set previous filters, output if passes at least one filter | ||
for (; k<n; ++k) { | ||
prev[k] = all; | ||
if (curr[k] !== all) out.push(k); | ||
} | ||
}; | ||
// set previous filters, output if passes at least one filter | ||
for (; k<n; ++k) { | ||
prev[k] = all; | ||
if (curr[k] !== all) out.push(k); | ||
} | ||
}, | ||
prototype.modify = function(pulse, output) { | ||
var out = output.mod, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
all = bits.all(), | ||
tuples = pulse.mod, | ||
i, n, k; | ||
modify(pulse, output) { | ||
let out = output.mod, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
all = bits.all(), | ||
tuples = pulse.mod, | ||
i, n, k; | ||
for (i=0, n=tuples.length; i<n; ++i) { | ||
k = tuples[i]._index; | ||
if (curr[k] !== all) out.push(k); | ||
} | ||
}; | ||
for (i=0, n=tuples.length; i<n; ++i) { | ||
k = tuples[i]._index; | ||
if (curr[k] !== all) out.push(k); | ||
} | ||
}, | ||
prototype.remove = function(_, pulse, output) { | ||
var indices = this._indices, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(), | ||
map = {}, | ||
out = output.rem, | ||
tuples = pulse.rem, | ||
i, n, k, f; | ||
remove(_, pulse, output) { | ||
let indices = this._indices, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(), | ||
map = {}, | ||
out = output.rem, | ||
tuples = pulse.rem, | ||
i, n, k, f; | ||
// process tuples, output if passes at least one filter | ||
for (i=0, n=tuples.length; i<n; ++i) { | ||
k = tuples[i]._index; | ||
map[k] = 1; // build index map | ||
prev[k] = (f = curr[k]); | ||
curr[k] = all; | ||
if (f !== all) out.push(k); | ||
} | ||
// process tuples, output if passes at least one filter | ||
for (i=0, n=tuples.length; i<n; ++i) { | ||
k = tuples[i]._index; | ||
map[k] = 1; // build index map | ||
prev[k] = (f = curr[k]); | ||
curr[k] = all; | ||
if (f !== all) out.push(k); | ||
} | ||
// remove from dimensional indices | ||
for (k in indices) { | ||
indices[k].remove(n, map); | ||
} | ||
// remove from dimensional indices | ||
for (k in indices) { | ||
indices[k].remove(n, map); | ||
} | ||
this.reindex(pulse, n, map); | ||
return map; | ||
}; | ||
this.reindex(pulse, n, map); | ||
return map; | ||
}, | ||
// reindex filters and indices after propagation completes | ||
prototype.reindex = function(pulse, num, map) { | ||
var indices = this._indices, | ||
bits = this.value; | ||
// reindex filters and indices after propagation completes | ||
reindex(pulse, num, map) { | ||
const indices = this._indices, | ||
bits = this.value; | ||
pulse.runAfter(function() { | ||
var indexMap = bits.remove(num, map); | ||
for (var key in indices) indices[key].reindex(indexMap); | ||
}); | ||
}; | ||
pulse.runAfter(() => { | ||
const indexMap = bits.remove(num, map); | ||
for (const key in indices) indices[key].reindex(indexMap); | ||
}); | ||
}, | ||
prototype.update = function(_, pulse, output) { | ||
var dims = this._dims, | ||
query = _.query, | ||
stamp = pulse.stamp, | ||
m = dims.length, | ||
mask = 0, i, q; | ||
update(_, pulse, output) { | ||
let dims = this._dims, | ||
query = _.query, | ||
stamp = pulse.stamp, | ||
m = dims.length, | ||
mask = 0, i, q; | ||
// survey how many queries have changed | ||
output.filters = 0; | ||
for (q=0; q<m; ++q) { | ||
if (_.modified('query', q)) { i = q; ++mask; } | ||
} | ||
// survey how many queries have changed | ||
output.filters = 0; | ||
for (q=0; q<m; ++q) { | ||
if (_.modified('query', q)) { i = q; ++mask; } | ||
} | ||
if (mask === 1) { | ||
// only one query changed, use more efficient update | ||
mask = dims[i].one; | ||
this.incrementOne(dims[i], query[i], output.add, output.rem); | ||
} else { | ||
// multiple queries changed, perform full record keeping | ||
for (q=0, mask=0; q<m; ++q) { | ||
if (!_.modified('query', q)) continue; | ||
mask |= dims[q].one; | ||
this.incrementAll(dims[q], query[q], stamp, output.add); | ||
output.rem = output.add; // duplicate add/rem for downstream resolve | ||
if (mask === 1) { | ||
// only one query changed, use more efficient update | ||
mask = dims[i].one; | ||
this.incrementOne(dims[i], query[i], output.add, output.rem); | ||
} else { | ||
// multiple queries changed, perform full record keeping | ||
for (q=0, mask=0; q<m; ++q) { | ||
if (!_.modified('query', q)) continue; | ||
mask |= dims[q].one; | ||
this.incrementAll(dims[q], query[q], stamp, output.add); | ||
output.rem = output.add; // duplicate add/rem for downstream resolve | ||
} | ||
} | ||
} | ||
return mask; | ||
}; | ||
return mask; | ||
}, | ||
prototype.incrementAll = function(dim, query, stamp, out) { | ||
var bits = this.value, | ||
seen = bits.seen(), | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
index = dim.index(), | ||
old = dim.bisect(dim.range), | ||
range = dim.bisect(query), | ||
lo1 = range[0], | ||
hi1 = range[1], | ||
lo0 = old[0], | ||
hi0 = old[1], | ||
one = dim.one, | ||
i, j, k; | ||
incrementAll(dim, query, stamp, out) { | ||
let bits = this.value, | ||
seen = bits.seen(), | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
index = dim.index(), | ||
old = dim.bisect(dim.range), | ||
range = dim.bisect(query), | ||
lo1 = range[0], | ||
hi1 = range[1], | ||
lo0 = old[0], | ||
hi0 = old[1], | ||
one = dim.one, | ||
i, j, k; | ||
// Fast incremental update based on previous lo index. | ||
if (lo1 < lo0) { | ||
for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
// Fast incremental update based on previous lo index. | ||
if (lo1 < lo0) { | ||
for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} | ||
curr[k] ^= one; | ||
} | ||
curr[k] ^= one; | ||
} | ||
} else if (lo1 > lo0) { | ||
for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} else if (lo1 > lo0) { | ||
for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} | ||
curr[k] ^= one; | ||
} | ||
curr[k] ^= one; | ||
} | ||
} | ||
// Fast incremental update based on previous hi index. | ||
if (hi1 > hi0) { | ||
for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
// Fast incremental update based on previous hi index. | ||
if (hi1 > hi0) { | ||
for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} | ||
curr[k] ^= one; | ||
} | ||
curr[k] ^= one; | ||
} | ||
} else if (hi1 < hi0) { | ||
for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} else if (hi1 < hi0) { | ||
for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} | ||
curr[k] ^= one; | ||
} | ||
curr[k] ^= one; | ||
} | ||
} | ||
dim.range = query.slice(); | ||
}; | ||
dim.range = query.slice(); | ||
}, | ||
prototype.incrementOne = function(dim, query, add, rem) { | ||
var bits = this.value, | ||
curr = bits.curr(), | ||
index = dim.index(), | ||
old = dim.bisect(dim.range), | ||
range = dim.bisect(query), | ||
lo1 = range[0], | ||
hi1 = range[1], | ||
lo0 = old[0], | ||
hi0 = old[1], | ||
one = dim.one, | ||
i, j, k; | ||
incrementOne(dim, query, add, rem) { | ||
let bits = this.value, | ||
curr = bits.curr(), | ||
index = dim.index(), | ||
old = dim.bisect(dim.range), | ||
range = dim.bisect(query), | ||
lo1 = range[0], | ||
hi1 = range[1], | ||
lo0 = old[0], | ||
hi0 = old[1], | ||
one = dim.one, | ||
i, j, k; | ||
// Fast incremental update based on previous lo index. | ||
if (lo1 < lo0) { | ||
for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
add.push(k); | ||
// Fast incremental update based on previous lo index. | ||
if (lo1 < lo0) { | ||
for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
add.push(k); | ||
} | ||
} else if (lo1 > lo0) { | ||
for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
rem.push(k); | ||
} | ||
} | ||
} else if (lo1 > lo0) { | ||
for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
rem.push(k); | ||
// Fast incremental update based on previous hi index. | ||
if (hi1 > hi0) { | ||
for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
add.push(k); | ||
} | ||
} else if (hi1 < hi0) { | ||
for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
rem.push(k); | ||
} | ||
} | ||
} | ||
// Fast incremental update based on previous hi index. | ||
if (hi1 > hi0) { | ||
for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
add.push(k); | ||
} | ||
} else if (hi1 < hi0) { | ||
for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
rem.push(k); | ||
} | ||
dim.range = query.slice(); | ||
} | ||
}); | ||
dim.range = query.slice(); | ||
}; | ||
/** | ||
@@ -680,50 +678,47 @@ * Selectively filters tuples by resolving against a filter bitmap. | ||
var prototype$1 = vegaUtil.inherits(ResolveFilter, vegaDataflow.Transform); | ||
vegaUtil.inherits(ResolveFilter, vegaDataflow.Transform, { | ||
transform(_, pulse) { | ||
const ignore = ~(_.ignore || 0), // bit mask where zeros -> dims to ignore | ||
bitmap = _.filter, | ||
mask = bitmap.mask; | ||
prototype$1.transform = function(_, pulse) { | ||
var ignore = ~(_.ignore || 0), // bit mask where zeros -> dims to ignore | ||
bitmap = _.filter, | ||
mask = bitmap.mask; | ||
// exit early if no relevant filter changes | ||
if ((mask & ignore) === 0) return pulse.StopPropagation; | ||
// exit early if no relevant filter changes | ||
if ((mask & ignore) === 0) return pulse.StopPropagation; | ||
const output = pulse.fork(pulse.ALL), | ||
data = bitmap.data(), | ||
curr = bitmap.curr(), | ||
prev = bitmap.prev(), | ||
pass = k => !(curr[k] & ignore) ? data[k] : null; | ||
var output = pulse.fork(pulse.ALL), | ||
data = bitmap.data(), | ||
curr = bitmap.curr(), | ||
prev = bitmap.prev(), | ||
pass = function(k) { | ||
return !(curr[k] & ignore) ? data[k] : null; | ||
}; | ||
// propagate all mod tuples that pass the filter | ||
output.filter(output.MOD, pass); | ||
// propagate all mod tuples that pass the filter | ||
output.filter(output.MOD, pass); | ||
// determine add & rem tuples via filter functions | ||
// for efficiency, we do *not* populate new arrays, | ||
// instead we add filter functions applied downstream | ||
// determine add & rem tuples via filter functions | ||
// for efficiency, we do *not* populate new arrays, | ||
// instead we add filter functions applied downstream | ||
if (!(mask & (mask-1))) { // only one filter changed | ||
output.filter(output.ADD, pass); | ||
output.filter(output.REM, k => | ||
(curr[k] & ignore) === mask ? data[k] : null); | ||
if (!(mask & (mask-1))) { // only one filter changed | ||
output.filter(output.ADD, pass); | ||
output.filter(output.REM, function(k) { | ||
return (curr[k] & ignore) === mask ? data[k] : null; | ||
}); | ||
} else { // multiple filters changed | ||
output.filter(output.ADD, k => { | ||
const c = curr[k] & ignore, | ||
f = !c && (c ^ (prev[k] & ignore)); | ||
return f ? data[k] : null; | ||
}); | ||
output.filter(output.REM, k => { | ||
const c = curr[k] & ignore, | ||
f = c && !(c ^ (c ^ (prev[k] & ignore))); | ||
return f ? data[k] : null; | ||
}); | ||
} | ||
} else { // multiple filters changed | ||
output.filter(output.ADD, function(k) { | ||
var c = curr[k] & ignore, | ||
f = !c && (c ^ (prev[k] & ignore)); | ||
return f ? data[k] : null; | ||
}); | ||
output.filter(output.REM, function(k) { | ||
var c = curr[k] & ignore, | ||
f = c && !(c ^ (c ^ (prev[k] & ignore))); | ||
return f ? data[k] : null; | ||
}); | ||
// add filter to source data in case of reflow... | ||
return output.filter(output.SOURCE, t => pass(t._index)); | ||
} | ||
}); | ||
// add filter to source data in case of reflow... | ||
return output.filter(output.SOURCE, function(t) { return pass(t._index); }); | ||
}; | ||
exports.crossfilter = CrossFilter; | ||
@@ -730,0 +725,0 @@ exports.resolvefilter = ResolveFilter; |
@@ -1,1 +0,1 @@ | ||
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("d3-array"),require("vega-dataflow"),require("vega-util")):"function"==typeof define&&define.amd?define(["exports","d3-array","vega-dataflow","vega-util"],r):r(((e=e||self).vega=e.vega||{},e.vega.transforms={}),e.d3,e.vega,e.vega)}(this,(function(e,r,n,i){"use strict";function t(e){return new Uint8Array(e)}function a(e){return new Uint16Array(e)}function o(e){return new Uint32Array(e)}function f(e,r,n){var i=(r<257?t:r<65537?a:o)(e);return n&&i.set(n),i}function u(e,r,n){var i=1<<r;return{one:i,zero:~i,range:n.slice(),bisect:e.bisect,index:e.index,size:e.size,onAdd:function(e,r){var n,t=this.bisect(this.range,e.value),a=e.index,o=t[0],f=t[1],u=a.length;for(n=0;n<o;++n)r[a[n]]|=i;for(n=f;n<u;++n)r[a[n]]|=i;return this}}}function s(){var e=o(0),n=[],i=0;return{insert:function(t,a,f){if(!a.length)return[];var u,s,l,d=i,c=a.length,h=Array(c),m=o(c);for(l=0;l<c;++l)h[l]=t(a[l]),m[l]=l;if(h=function(e,n){return e.sort.call(n,(function(r,n){var i=e[r],t=e[n];return i<t?-1:i>t?1:0})),r.permute(e,n)}(h,m),d)u=n,s=e,n=Array(d+c),e=o(d+c),function(e,r,n,i,t,a,o,f,u){var s,l=0,d=0;for(s=0;l<i&&d<o;++s)r[l]<t[d]?(f[s]=r[l],u[s]=n[l++]):(f[s]=t[d],u[s]=a[d++]+e);for(;l<i;++l,++s)f[s]=r[l],u[s]=n[l];for(;d<o;++d,++s)f[s]=t[d],u[s]=a[d]+e}(f,u,s,d,h,m,c,n,e);else{if(f>0)for(l=0;l<c;++l)m[l]+=f;n=h,e=m}return i=d+c,{index:m,value:h}},remove:function(r,t){var a,o,f,u=i;for(o=0;!t[e[o]]&&o<u;++o);for(f=o;o<u;++o)t[a=e[o]]||(e[f]=a,n[f]=n[o],++f);i=u-r},bisect:function(e,t){var a;return t?a=t.length:(t=n,a=i),[r.bisectLeft(t,e[0],0,a),r.bisectRight(t,e[1],0,a)]},reindex:function(r){for(var n=0,t=i;n<t;++n)e[n]=r[e[n]]},index:function(){return e},size:function(){return i}}}function l(e){var r,i,t,a,u;n.Transform.call(this,(r=8,i=[],t=o(0),a=f(0,r),u=f(0,r),{data:function(){return i},seen:function(){return t=function(e,r,n){return e.length>=r?e:((n=n||new e.constructor(r)).set(e),n)}(t,i.length)},add:function(e){for(var r,n=0,t=i.length,a=e.length;n<a;++n)(r=e[n])._index=t++,i.push(r)},remove:function(e,r){var n,t,o,f=i.length,s=Array(f-e),l=i;for(t=0;!r[t]&&t<f;++t)s[t]=i[t],l[t]=t;for(o=t;t<f;++t)n=i[t],r[t]?l[t]=-1:(l[t]=o,a[o]=a[t],u[o]=u[t],s[o]=n,n._index=o++),a[t]=0;return i=s,l},size:function(){return i.length},curr:function(){return a},prev:function(){return u},reset:function(e){u[e]=a[e]},all:function(){return r<257?255:r<65537?65535:4294967295},set:function(e,r){a[e]|=r},clear:function(e,r){a[e]&=~r},resize:function(e,n){(e>a.length||n>r)&&(r=Math.max(n,r),a=f(e,r,a),u=f(e,r))}}),e),this._indices=null,this._dims=null}l.Definition={type:"CrossFilter",metadata:{},params:[{name:"fields",type:"field",array:!0,required:!0},{name:"query",type:"array",array:!0,required:!0,content:{type:"number",array:!0,length:2}}]};var d=i.inherits(l,n.Transform);function c(e){n.Transform.call(this,null,e)}d.transform=function(e,r){return this._dims?e.modified("fields")||e.fields.some((function(e){return r.modified(e.fields)}))?this.reinit(e,r):this.eval(e,r):this.init(e,r)},d.init=function(e,r){for(var n,i,t=e.fields,a=e.query,o=this._indices={},f=this._dims=[],l=a.length,d=0;d<l;++d)i=o[n=t[d].fname]||(o[n]=s()),f.push(u(i,d,a[d]));return this.eval(e,r)},d.reinit=function(e,r){var n,i,t,a,o,f,l,d,c,h=r.materialize().fork(),m=e.fields,v=e.query,g=this._indices,p=this._dims,y=this.value,x=y.curr(),_=y.prev(),b=y.all(),A=h.rem=h.add,q=h.mod,M=v.length,z={};if(_.set(x),r.rem.length&&(o=this.remove(e,r,h)),r.add.length&&y.add(r.add),r.mod.length)for(f={},l=0,d=(a=r.mod).length;l<d;++l)f[a[l]._index]=1;for(l=0;l<M;++l)c=m[l],(!p[l]||e.modified("fields",l)||r.modified(c.fields))&&((n=z[t=c.fname])||(g[t]=i=s(),z[t]=n=i.insert(c,r.source,0)),p[l]=u(i,l,v[l]).onAdd(n,x));for(l=0,d=y.data().length;l<d;++l)o[l]||(_[l]!==x[l]?A.push(l):f[l]&&x[l]!==b&&q.push(l));return y.mask=(1<<M)-1,h},d.eval=function(e,r){var n=r.materialize().fork(),i=this._dims.length,t=0;return r.rem.length&&(this.remove(e,r,n),t|=(1<<i)-1),e.modified("query")&&!e.modified("fields")&&(t|=this.update(e,r,n)),r.add.length&&(this.insert(e,r,n),t|=(1<<i)-1),r.mod.length&&(this.modify(r,n),t|=(1<<i)-1),this.value.mask=t,n},d.insert=function(e,r,n){var i,t,a,o=r.add,f=this.value,u=this._dims,s=this._indices,l=e.fields,d={},c=n.add,h=f.size(),m=h+o.length,v=u.length;f.resize(m,v),f.add(o);var g=f.curr(),p=f.prev(),y=f.all();for(i=0;i<v;++i)a=d[t=l[i].fname]||(d[t]=s[t].insert(l[i],o,h)),u[i].onAdd(a,g);for(;h<m;++h)p[h]=y,g[h]!==y&&c.push(h)},d.modify=function(e,r){var n,i,t,a=r.mod,o=this.value,f=o.curr(),u=o.all(),s=e.mod;for(n=0,i=s.length;n<i;++n)f[t=s[n]._index]!==u&&a.push(t)},d.remove=function(e,r,n){var i,t,a,o,f=this._indices,u=this.value,s=u.curr(),l=u.prev(),d=u.all(),c={},h=n.rem,m=r.rem;for(i=0,t=m.length;i<t;++i)c[a=m[i]._index]=1,l[a]=o=s[a],s[a]=d,o!==d&&h.push(a);for(a in f)f[a].remove(t,c);return this.reindex(r,t,c),c},d.reindex=function(e,r,n){var i=this._indices,t=this.value;e.runAfter((function(){var e=t.remove(r,n);for(var a in i)i[a].reindex(e)}))},d.update=function(e,r,n){var i,t,a=this._dims,o=e.query,f=r.stamp,u=a.length,s=0;for(n.filters=0,t=0;t<u;++t)e.modified("query",t)&&(i=t,++s);if(1===s)s=a[i].one,this.incrementOne(a[i],o[i],n.add,n.rem);else for(t=0,s=0;t<u;++t)e.modified("query",t)&&(s|=a[t].one,this.incrementAll(a[t],o[t],f,n.add),n.rem=n.add);return s},d.incrementAll=function(e,r,n,i){var t,a,o,f=this.value,u=f.seen(),s=f.curr(),l=f.prev(),d=e.index(),c=e.bisect(e.range),h=e.bisect(r),m=h[0],v=h[1],g=c[0],p=c[1],y=e.one;if(m<g)for(t=m,a=Math.min(g,v);t<a;++t)u[o=d[t]]!==n&&(l[o]=s[o],u[o]=n,i.push(o)),s[o]^=y;else if(m>g)for(t=g,a=Math.min(m,p);t<a;++t)u[o=d[t]]!==n&&(l[o]=s[o],u[o]=n,i.push(o)),s[o]^=y;if(v>p)for(t=Math.max(m,p),a=v;t<a;++t)u[o=d[t]]!==n&&(l[o]=s[o],u[o]=n,i.push(o)),s[o]^=y;else if(v<p)for(t=Math.max(g,v),a=p;t<a;++t)u[o=d[t]]!==n&&(l[o]=s[o],u[o]=n,i.push(o)),s[o]^=y;e.range=r.slice()},d.incrementOne=function(e,r,n,i){var t,a,o,f=this.value.curr(),u=e.index(),s=e.bisect(e.range),l=e.bisect(r),d=l[0],c=l[1],h=s[0],m=s[1],v=e.one;if(d<h)for(t=d,a=Math.min(h,c);t<a;++t)f[o=u[t]]^=v,n.push(o);else if(d>h)for(t=h,a=Math.min(d,m);t<a;++t)f[o=u[t]]^=v,i.push(o);if(c>m)for(t=Math.max(d,m),a=c;t<a;++t)f[o=u[t]]^=v,n.push(o);else if(c<m)for(t=Math.max(h,c),a=m;t<a;++t)f[o=u[t]]^=v,i.push(o);e.range=r.slice()},c.Definition={type:"ResolveFilter",metadata:{},params:[{name:"ignore",type:"number",required:!0,description:"A bit mask indicating which filters to ignore."},{name:"filter",type:"object",required:!0,description:"Per-tuple filter bitmaps from a CrossFilter transform."}]},i.inherits(c,n.Transform).transform=function(e,r){var n=~(e.ignore||0),i=e.filter,t=i.mask;if(0==(t&n))return r.StopPropagation;var a=r.fork(r.ALL),o=i.data(),f=i.curr(),u=i.prev(),s=function(e){return f[e]&n?null:o[e]};return a.filter(a.MOD,s),t&t-1?(a.filter(a.ADD,(function(e){var r=f[e]&n;return!r&&r^u[e]&n?o[e]:null})),a.filter(a.REM,(function(e){var r=f[e]&n;return r&&!(r^r^u[e]&n)?o[e]:null}))):(a.filter(a.ADD,s),a.filter(a.REM,(function(e){return(f[e]&n)===t?o[e]:null}))),a.filter(a.SOURCE,(function(e){return s(e._index)}))},e.crossfilter=l,e.resolvefilter=c,Object.defineProperty(e,"__esModule",{value:!0})})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("d3-array"),require("vega-dataflow"),require("vega-util")):"function"==typeof define&&define.amd?define(["exports","d3-array","vega-dataflow","vega-util"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).vega=e.vega||{},e.vega.transforms={}),e.d3,e.vega,e.vega)}(this,(function(e,t,r,i){"use strict";const n=e=>new Uint8Array(e),s=e=>new Uint16Array(e),l=e=>new Uint32Array(e);function o(e,t,r){const i=(t<257?n:t<65537?s:l)(e);return r&&i.set(r),i}function a(e,t,r){const i=1<<t;return{one:i,zero:~i,range:r.slice(),bisect:e.bisect,index:e.index,size:e.size,onAdd(e,t){let r,n=this.bisect(this.range,e.value),s=e.index,l=n[0],o=n[1],a=s.length;for(r=0;r<l;++r)t[s[r]]|=i;for(r=o;r<a;++r)t[s[r]]|=i;return this}}}function f(){let e=l(0),r=[],i=0;return{insert:function(n,s,o){if(!s.length)return[];let a,f,d,u=i,h=s.length,m=Array(h),c=l(h);for(d=0;d<h;++d)m[d]=n(s[d]),c[d]=d;if(m=function(e,r){return e.sort.call(r,(t,r)=>{const i=e[t],n=e[r];return i<n?-1:i>n?1:0}),t.permute(e,r)}(m,c),u)a=r,f=e,r=Array(u+h),e=l(u+h),function(e,t,r,i,n,s,l,o,a){let f,d=0,u=0;for(f=0;d<i&&u<l;++f)t[d]<n[u]?(o[f]=t[d],a[f]=r[d++]):(o[f]=n[u],a[f]=s[u++]+e);for(;d<i;++d,++f)o[f]=t[d],a[f]=r[d];for(;u<l;++u,++f)o[f]=n[u],a[f]=s[u]+e}(o,a,f,u,m,c,h,r,e);else{if(o>0)for(d=0;d<h;++d)c[d]+=o;r=m,e=c}return i=u+h,{index:c,value:m}},remove:function(t,n){let s,l,o,a=i;for(l=0;!n[e[l]]&&l<a;++l);for(o=l;l<a;++l)n[s=e[l]]||(e[o]=s,r[o]=r[l],++o);i=a-t},bisect:function(e,n){let s;return n?s=n.length:(n=r,s=i),[t.bisectLeft(n,e[0],0,s),t.bisectRight(n,e[1],0,s)]},reindex:function(t){for(let r=0,n=i;r<n;++r)e[r]=t[e[r]]},index:()=>e,size:()=>i}}function d(e){r.Transform.call(this,function(){let e=8,t=[],r=l(0),i=o(0,e),n=o(0,e);return{data:()=>t,seen:()=>r=function(e,t,r){return e.length>=t?e:((r=r||new e.constructor(t)).set(e),r)}(r,t.length),add(e){for(let r,i=0,n=t.length,s=e.length;i<s;++i)r=e[i],r._index=n++,t.push(r)},remove(e,r){let s,l,o,a=t.length,f=Array(a-e),d=t;for(l=0;!r[l]&&l<a;++l)f[l]=t[l],d[l]=l;for(o=l;l<a;++l)s=t[l],r[l]?d[l]=-1:(d[l]=o,i[o]=i[l],n[o]=n[l],f[o]=s,s._index=o++),i[l]=0;return t=f,d},size:()=>t.length,curr:()=>i,prev:()=>n,reset:e=>n[e]=i[e],all:()=>e<257?255:e<65537?65535:4294967295,set(e,t){i[e]|=t},clear(e,t){i[e]&=~t},resize(t,r){(t>i.length||r>e)&&(e=Math.max(r,e),i=o(t,e,i),n=o(t,e))}}}(),e),this._indices=null,this._dims=null}function u(e){r.Transform.call(this,null,e)}d.Definition={type:"CrossFilter",metadata:{},params:[{name:"fields",type:"field",array:!0,required:!0},{name:"query",type:"array",array:!0,required:!0,content:{type:"number",array:!0,length:2}}]},i.inherits(d,r.Transform,{transform(e,t){return this._dims?e.modified("fields")||e.fields.some(e=>t.modified(e.fields))?this.reinit(e,t):this.eval(e,t):this.init(e,t)},init(e,t){let r,i,n=e.fields,s=e.query,l=this._indices={},o=this._dims=[],d=s.length,u=0;for(;u<d;++u)r=n[u].fname,i=l[r]||(l[r]=f()),o.push(a(i,u,s[u]));return this.eval(e,t)},reinit(e,t){let r,i,n,s,l,o,d,u,h,m=t.materialize().fork(),c=e.fields,g=e.query,p=this._indices,v=this._dims,y=this.value,x=y.curr(),_=y.prev(),b=y.all(),A=m.rem=m.add,q=m.mod,M=g.length,z={};if(_.set(x),t.rem.length&&(l=this.remove(e,t,m)),t.add.length&&y.add(t.add),t.mod.length)for(o={},s=t.mod,d=0,u=s.length;d<u;++d)o[s[d]._index]=1;for(d=0;d<M;++d)h=c[d],(!v[d]||e.modified("fields",d)||t.modified(h.fields))&&(n=h.fname,(r=z[n])||(p[n]=i=f(),z[n]=r=i.insert(h,t.source,0)),v[d]=a(i,d,g[d]).onAdd(r,x));for(d=0,u=y.data().length;d<u;++d)l[d]||(_[d]!==x[d]?A.push(d):o[d]&&x[d]!==b&&q.push(d));return y.mask=(1<<M)-1,m},eval(e,t){let r=t.materialize().fork(),i=this._dims.length,n=0;return t.rem.length&&(this.remove(e,t,r),n|=(1<<i)-1),e.modified("query")&&!e.modified("fields")&&(n|=this.update(e,t,r)),t.add.length&&(this.insert(e,t,r),n|=(1<<i)-1),t.mod.length&&(this.modify(t,r),n|=(1<<i)-1),this.value.mask=n,r},insert(e,t,r){let i,n,s,l=t.add,o=this.value,a=this._dims,f=this._indices,d=e.fields,u={},h=r.add,m=o.size(),c=m+l.length,g=a.length;o.resize(c,g),o.add(l);const p=o.curr(),v=o.prev(),y=o.all();for(i=0;i<g;++i)n=d[i].fname,s=u[n]||(u[n]=f[n].insert(d[i],l,m)),a[i].onAdd(s,p);for(;m<c;++m)v[m]=y,p[m]!==y&&h.push(m)},modify(e,t){let r,i,n,s=t.mod,l=this.value,o=l.curr(),a=l.all(),f=e.mod;for(r=0,i=f.length;r<i;++r)n=f[r]._index,o[n]!==a&&s.push(n)},remove(e,t,r){let i,n,s,l,o=this._indices,a=this.value,f=a.curr(),d=a.prev(),u=a.all(),h={},m=r.rem,c=t.rem;for(i=0,n=c.length;i<n;++i)s=c[i]._index,h[s]=1,d[s]=l=f[s],f[s]=u,l!==u&&m.push(s);for(s in o)o[s].remove(n,h);return this.reindex(t,n,h),h},reindex(e,t,r){const i=this._indices,n=this.value;e.runAfter(()=>{const e=n.remove(t,r);for(const t in i)i[t].reindex(e)})},update(e,t,r){let i,n,s=this._dims,l=e.query,o=t.stamp,a=s.length,f=0;for(r.filters=0,n=0;n<a;++n)e.modified("query",n)&&(i=n,++f);if(1===f)f=s[i].one,this.incrementOne(s[i],l[i],r.add,r.rem);else for(n=0,f=0;n<a;++n)e.modified("query",n)&&(f|=s[n].one,this.incrementAll(s[n],l[n],o,r.add),r.rem=r.add);return f},incrementAll(e,t,r,i){let n,s,l,o=this.value,a=o.seen(),f=o.curr(),d=o.prev(),u=e.index(),h=e.bisect(e.range),m=e.bisect(t),c=m[0],g=m[1],p=h[0],v=h[1],y=e.one;if(c<p)for(n=c,s=Math.min(p,g);n<s;++n)l=u[n],a[l]!==r&&(d[l]=f[l],a[l]=r,i.push(l)),f[l]^=y;else if(c>p)for(n=p,s=Math.min(c,v);n<s;++n)l=u[n],a[l]!==r&&(d[l]=f[l],a[l]=r,i.push(l)),f[l]^=y;if(g>v)for(n=Math.max(c,v),s=g;n<s;++n)l=u[n],a[l]!==r&&(d[l]=f[l],a[l]=r,i.push(l)),f[l]^=y;else if(g<v)for(n=Math.max(p,g),s=v;n<s;++n)l=u[n],a[l]!==r&&(d[l]=f[l],a[l]=r,i.push(l)),f[l]^=y;e.range=t.slice()},incrementOne(e,t,r,i){let n,s,l,o=this.value.curr(),a=e.index(),f=e.bisect(e.range),d=e.bisect(t),u=d[0],h=d[1],m=f[0],c=f[1],g=e.one;if(u<m)for(n=u,s=Math.min(m,h);n<s;++n)l=a[n],o[l]^=g,r.push(l);else if(u>m)for(n=m,s=Math.min(u,c);n<s;++n)l=a[n],o[l]^=g,i.push(l);if(h>c)for(n=Math.max(u,c),s=h;n<s;++n)l=a[n],o[l]^=g,r.push(l);else if(h<c)for(n=Math.max(m,h),s=c;n<s;++n)l=a[n],o[l]^=g,i.push(l);e.range=t.slice()}}),u.Definition={type:"ResolveFilter",metadata:{},params:[{name:"ignore",type:"number",required:!0,description:"A bit mask indicating which filters to ignore."},{name:"filter",type:"object",required:!0,description:"Per-tuple filter bitmaps from a CrossFilter transform."}]},i.inherits(u,r.Transform,{transform(e,t){const r=~(e.ignore||0),i=e.filter,n=i.mask;if(0==(n&r))return t.StopPropagation;const s=t.fork(t.ALL),l=i.data(),o=i.curr(),a=i.prev(),f=e=>o[e]&r?null:l[e];return s.filter(s.MOD,f),n&n-1?(s.filter(s.ADD,e=>{const t=o[e]&r;return!t&&t^a[e]&r?l[e]:null}),s.filter(s.REM,e=>{const t=o[e]&r;return t&&!(t^t^a[e]&r)?l[e]:null})):(s.filter(s.ADD,f),s.filter(s.REM,e=>(o[e]&r)===n?l[e]:null)),s.filter(s.SOURCE,e=>f(e._index))}}),e.crossfilter=d,e.resolvefilter=u,Object.defineProperty(e,"__esModule",{value:!0})})); |
{ | ||
"name": "vega-crossfilter", | ||
"version": "4.0.2", | ||
"version": "4.0.3", | ||
"description": "Indexed cross-filtering for Vega dataflows.", | ||
@@ -25,5 +25,5 @@ "keywords": [ | ||
"dependencies": { | ||
"d3-array": "^2.4.0", | ||
"vega-dataflow": "^5.5.1", | ||
"vega-util": "^1.13.2" | ||
"d3-array": "^2.5.1", | ||
"vega-dataflow": "^5.7.1", | ||
"vega-util": "^1.15.0" | ||
}, | ||
@@ -33,3 +33,3 @@ "devDependencies": { | ||
}, | ||
"gitHead": "35e31c5c6b54db9dc3a577b5adad8d15ec274d32" | ||
"gitHead": "28db83352e43e321dfe55fc5cb6489b211e45662" | ||
} |
@@ -1,5 +0,5 @@ | ||
export function array8(n) { return new Uint8Array(n); } | ||
export const array8 = n => new Uint8Array(n); | ||
export function array16(n) { return new Uint16Array(n); } | ||
export const array16 = n => new Uint16Array(n); | ||
export function array32(n) { return new Uint32Array(n); } | ||
export const array32 = n => new Uint32Array(n); |
@@ -8,3 +8,3 @@ import {array16, array32, array8} from './arrays'; | ||
var width = 8, | ||
let width = 8, | ||
data = [], | ||
@@ -16,11 +16,8 @@ seen = array32(0), | ||
return { | ||
data: () => data, | ||
data: function() { return data; }, | ||
seen: () => (seen = lengthen(seen, data.length)), | ||
seen: function() { | ||
return (seen = lengthen(seen, data.length)); | ||
}, | ||
add: function(array) { | ||
for (var i=0, j=data.length, n=array.length, t; i<n; ++i) { | ||
add(array) { | ||
for (let i=0, j=data.length, n=array.length, t; i<n; ++i) { | ||
t = array[i]; | ||
@@ -32,4 +29,4 @@ t._index = j++; | ||
remove: function(num, map) { // map: index -> boolean (true => remove) | ||
var n = data.length, | ||
remove(num, map) { // map: index -> boolean (true => remove) | ||
let n = data.length, | ||
copy = Array(n - num), | ||
@@ -64,20 +61,19 @@ reindex = data, // reuse old data array for index map | ||
size: function() { return data.length; }, | ||
size: () => data.length, | ||
curr: function() { return curr; }, | ||
curr: () => curr, | ||
prev: function() { return prev; }, | ||
prev: () => prev, | ||
reset: function(k) { prev[k] = curr[k]; }, | ||
reset: k => prev[k] = curr[k], | ||
all: function() { | ||
return width < 0x101 ? 0xff : width < 0x10001 ? 0xffff : 0xffffffff; | ||
}, | ||
all: () => | ||
width < 0x101 ? 0xff : width < 0x10001 ? 0xffff : 0xffffffff, | ||
set: function(k, one) { curr[k] |= one; }, | ||
set(k, one) { curr[k] |= one; }, | ||
clear: function(k, one) { curr[k] &= ~one; }, | ||
clear(k, one) { curr[k] &= ~one; }, | ||
resize: function(n, m) { | ||
var k = curr.length; | ||
resize(n, m) { | ||
const k = curr.length; | ||
if (n > k || m > width) { | ||
@@ -100,5 +96,7 @@ width = Math.max(m, width); | ||
function array(n, m, array) { | ||
var copy = (m < 0x101 ? array8 : m < 0x10001 ? array16 : array32)(n); | ||
const copy = (m < 0x101 ? array8 | ||
: m < 0x10001 ? array16 | ||
: array32)(n); | ||
if (array) copy.set(array); | ||
return copy; | ||
} |
@@ -30,356 +30,356 @@ import Bitmaps from './Bitmaps'; | ||
var prototype = inherits(CrossFilter, Transform); | ||
inherits(CrossFilter, Transform, { | ||
transform(_, pulse) { | ||
if (!this._dims) { | ||
return this.init(_, pulse); | ||
} else { | ||
var init = _.modified('fields') | ||
|| _.fields.some(f => pulse.modified(f.fields)); | ||
prototype.transform = function(_, pulse) { | ||
if (!this._dims) { | ||
return this.init(_, pulse); | ||
} else { | ||
var init = _.modified('fields') | ||
|| _.fields.some(function(f) { return pulse.modified(f.fields); }); | ||
return init | ||
? this.reinit(_, pulse) | ||
: this.eval(_, pulse); | ||
} | ||
}, | ||
return init | ||
? this.reinit(_, pulse) | ||
: this.eval(_, pulse); | ||
} | ||
}; | ||
init(_, pulse) { | ||
let fields = _.fields, | ||
query = _.query, | ||
indices = this._indices = {}, | ||
dims = this._dims = [], | ||
m = query.length, | ||
i = 0, key, index; | ||
prototype.init = function(_, pulse) { | ||
var fields = _.fields, | ||
query = _.query, | ||
indices = this._indices = {}, | ||
dims = this._dims = [], | ||
m = query.length, | ||
i = 0, key, index; | ||
// instantiate indices and dimensions | ||
for (; i<m; ++i) { | ||
key = fields[i].fname; | ||
index = indices[key] || (indices[key] = SortedIndex()); | ||
dims.push(Dimension(index, i, query[i])); | ||
} | ||
// instantiate indices and dimensions | ||
for (; i<m; ++i) { | ||
key = fields[i].fname; | ||
index = indices[key] || (indices[key] = SortedIndex()); | ||
dims.push(Dimension(index, i, query[i])); | ||
} | ||
return this.eval(_, pulse); | ||
}, | ||
return this.eval(_, pulse); | ||
}; | ||
reinit(_, pulse) { | ||
let output = pulse.materialize().fork(), | ||
fields = _.fields, | ||
query = _.query, | ||
indices = this._indices, | ||
dims = this._dims, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(), | ||
out = (output.rem = output.add), | ||
mod = output.mod, | ||
m = query.length, | ||
adds = {}, add, index, key, | ||
mods, remMap, modMap, i, n, f; | ||
prototype.reinit = function(_, pulse) { | ||
var output = pulse.materialize().fork(), | ||
fields = _.fields, | ||
query = _.query, | ||
indices = this._indices, | ||
dims = this._dims, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(), | ||
out = (output.rem = output.add), | ||
mod = output.mod, | ||
m = query.length, | ||
adds = {}, add, index, key, | ||
mods, remMap, modMap, i, n, f; | ||
// set prev to current state | ||
prev.set(curr); | ||
// set prev to current state | ||
prev.set(curr); | ||
// if pulse has remove tuples, process them first | ||
if (pulse.rem.length) { | ||
remMap = this.remove(_, pulse, output); | ||
} | ||
// if pulse has remove tuples, process them first | ||
if (pulse.rem.length) { | ||
remMap = this.remove(_, pulse, output); | ||
} | ||
// if pulse has added tuples, add them to state | ||
if (pulse.add.length) { | ||
bits.add(pulse.add); | ||
} | ||
// if pulse has added tuples, add them to state | ||
if (pulse.add.length) { | ||
bits.add(pulse.add); | ||
} | ||
// if pulse has modified tuples, create an index map | ||
if (pulse.mod.length) { | ||
modMap = {}; | ||
for (mods=pulse.mod, i=0, n=mods.length; i<n; ++i) { | ||
modMap[mods[i]._index] = 1; | ||
// if pulse has modified tuples, create an index map | ||
if (pulse.mod.length) { | ||
modMap = {}; | ||
for (mods=pulse.mod, i=0, n=mods.length; i<n; ++i) { | ||
modMap[mods[i]._index] = 1; | ||
} | ||
} | ||
} | ||
// re-initialize indices as needed, update curr bitmap | ||
for (i=0; i<m; ++i) { | ||
f = fields[i]; | ||
if (!dims[i] || _.modified('fields', i) || pulse.modified(f.fields)) { | ||
key = f.fname; | ||
if (!(add = adds[key])) { | ||
indices[key] = index = SortedIndex(); | ||
adds[key] = add = index.insert(f, pulse.source, 0); | ||
// re-initialize indices as needed, update curr bitmap | ||
for (i=0; i<m; ++i) { | ||
f = fields[i]; | ||
if (!dims[i] || _.modified('fields', i) || pulse.modified(f.fields)) { | ||
key = f.fname; | ||
if (!(add = adds[key])) { | ||
indices[key] = index = SortedIndex(); | ||
adds[key] = add = index.insert(f, pulse.source, 0); | ||
} | ||
dims[i] = Dimension(index, i, query[i]).onAdd(add, curr); | ||
} | ||
dims[i] = Dimension(index, i, query[i]).onAdd(add, curr); | ||
} | ||
} | ||
// visit each tuple | ||
// if filter state changed, push index to add/rem | ||
// else if in mod and passes a filter, push index to mod | ||
for (i=0, n=bits.data().length; i<n; ++i) { | ||
if (remMap[i]) { // skip if removed tuple | ||
continue; | ||
} else if (prev[i] !== curr[i]) { // add if state changed | ||
out.push(i); | ||
} else if (modMap[i] && curr[i] !== all) { // otherwise, pass mods through | ||
mod.push(i); | ||
// visit each tuple | ||
// if filter state changed, push index to add/rem | ||
// else if in mod and passes a filter, push index to mod | ||
for (i=0, n=bits.data().length; i<n; ++i) { | ||
if (remMap[i]) { // skip if removed tuple | ||
continue; | ||
} else if (prev[i] !== curr[i]) { // add if state changed | ||
out.push(i); | ||
} else if (modMap[i] && curr[i] !== all) { // otherwise, pass mods through | ||
mod.push(i); | ||
} | ||
} | ||
} | ||
bits.mask = (1 << m) - 1; | ||
return output; | ||
}; | ||
bits.mask = (1 << m) - 1; | ||
return output; | ||
}, | ||
prototype.eval = function(_, pulse) { | ||
var output = pulse.materialize().fork(), | ||
m = this._dims.length, | ||
mask = 0; | ||
eval(_, pulse) { | ||
let output = pulse.materialize().fork(), | ||
m = this._dims.length, | ||
mask = 0; | ||
if (pulse.rem.length) { | ||
this.remove(_, pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
if (pulse.rem.length) { | ||
this.remove(_, pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
if (_.modified('query') && !_.modified('fields')) { | ||
mask |= this.update(_, pulse, output); | ||
} | ||
if (_.modified('query') && !_.modified('fields')) { | ||
mask |= this.update(_, pulse, output); | ||
} | ||
if (pulse.add.length) { | ||
this.insert(_, pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
if (pulse.add.length) { | ||
this.insert(_, pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
if (pulse.mod.length) { | ||
this.modify(pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
if (pulse.mod.length) { | ||
this.modify(pulse, output); | ||
mask |= (1 << m) - 1; | ||
} | ||
this.value.mask = mask; | ||
return output; | ||
}; | ||
this.value.mask = mask; | ||
return output; | ||
}, | ||
prototype.insert = function(_, pulse, output) { | ||
var tuples = pulse.add, | ||
bits = this.value, | ||
dims = this._dims, | ||
indices = this._indices, | ||
fields = _.fields, | ||
adds = {}, | ||
out = output.add, | ||
k = bits.size(), | ||
n = k + tuples.length, | ||
m = dims.length, j, key, add; | ||
insert(_, pulse, output) { | ||
let tuples = pulse.add, | ||
bits = this.value, | ||
dims = this._dims, | ||
indices = this._indices, | ||
fields = _.fields, | ||
adds = {}, | ||
out = output.add, | ||
k = bits.size(), | ||
n = k + tuples.length, | ||
m = dims.length, j, key, add; | ||
// resize bitmaps and add tuples as needed | ||
bits.resize(n, m); | ||
bits.add(tuples); | ||
// resize bitmaps and add tuples as needed | ||
bits.resize(n, m); | ||
bits.add(tuples); | ||
var curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(); | ||
const curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(); | ||
// add to dimensional indices | ||
for (j=0; j<m; ++j) { | ||
key = fields[j].fname; | ||
add = adds[key] || (adds[key] = indices[key].insert(fields[j], tuples, k)); | ||
dims[j].onAdd(add, curr); | ||
} | ||
// add to dimensional indices | ||
for (j=0; j<m; ++j) { | ||
key = fields[j].fname; | ||
add = adds[key] || (adds[key] = indices[key].insert(fields[j], tuples, k)); | ||
dims[j].onAdd(add, curr); | ||
} | ||
// set previous filters, output if passes at least one filter | ||
for (; k<n; ++k) { | ||
prev[k] = all; | ||
if (curr[k] !== all) out.push(k); | ||
} | ||
}; | ||
// set previous filters, output if passes at least one filter | ||
for (; k<n; ++k) { | ||
prev[k] = all; | ||
if (curr[k] !== all) out.push(k); | ||
} | ||
}, | ||
prototype.modify = function(pulse, output) { | ||
var out = output.mod, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
all = bits.all(), | ||
tuples = pulse.mod, | ||
i, n, k; | ||
modify(pulse, output) { | ||
let out = output.mod, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
all = bits.all(), | ||
tuples = pulse.mod, | ||
i, n, k; | ||
for (i=0, n=tuples.length; i<n; ++i) { | ||
k = tuples[i]._index; | ||
if (curr[k] !== all) out.push(k); | ||
} | ||
}; | ||
for (i=0, n=tuples.length; i<n; ++i) { | ||
k = tuples[i]._index; | ||
if (curr[k] !== all) out.push(k); | ||
} | ||
}, | ||
prototype.remove = function(_, pulse, output) { | ||
var indices = this._indices, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(), | ||
map = {}, | ||
out = output.rem, | ||
tuples = pulse.rem, | ||
i, n, k, f; | ||
remove(_, pulse, output) { | ||
let indices = this._indices, | ||
bits = this.value, | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
all = bits.all(), | ||
map = {}, | ||
out = output.rem, | ||
tuples = pulse.rem, | ||
i, n, k, f; | ||
// process tuples, output if passes at least one filter | ||
for (i=0, n=tuples.length; i<n; ++i) { | ||
k = tuples[i]._index; | ||
map[k] = 1; // build index map | ||
prev[k] = (f = curr[k]); | ||
curr[k] = all; | ||
if (f !== all) out.push(k); | ||
} | ||
// process tuples, output if passes at least one filter | ||
for (i=0, n=tuples.length; i<n; ++i) { | ||
k = tuples[i]._index; | ||
map[k] = 1; // build index map | ||
prev[k] = (f = curr[k]); | ||
curr[k] = all; | ||
if (f !== all) out.push(k); | ||
} | ||
// remove from dimensional indices | ||
for (k in indices) { | ||
indices[k].remove(n, map); | ||
} | ||
// remove from dimensional indices | ||
for (k in indices) { | ||
indices[k].remove(n, map); | ||
} | ||
this.reindex(pulse, n, map); | ||
return map; | ||
}; | ||
this.reindex(pulse, n, map); | ||
return map; | ||
}, | ||
// reindex filters and indices after propagation completes | ||
prototype.reindex = function(pulse, num, map) { | ||
var indices = this._indices, | ||
bits = this.value; | ||
// reindex filters and indices after propagation completes | ||
reindex(pulse, num, map) { | ||
const indices = this._indices, | ||
bits = this.value; | ||
pulse.runAfter(function() { | ||
var indexMap = bits.remove(num, map); | ||
for (var key in indices) indices[key].reindex(indexMap); | ||
}); | ||
}; | ||
pulse.runAfter(() => { | ||
const indexMap = bits.remove(num, map); | ||
for (const key in indices) indices[key].reindex(indexMap); | ||
}); | ||
}, | ||
prototype.update = function(_, pulse, output) { | ||
var dims = this._dims, | ||
query = _.query, | ||
stamp = pulse.stamp, | ||
m = dims.length, | ||
mask = 0, i, q; | ||
update(_, pulse, output) { | ||
let dims = this._dims, | ||
query = _.query, | ||
stamp = pulse.stamp, | ||
m = dims.length, | ||
mask = 0, i, q; | ||
// survey how many queries have changed | ||
output.filters = 0; | ||
for (q=0; q<m; ++q) { | ||
if (_.modified('query', q)) { i = q; ++mask; } | ||
} | ||
// survey how many queries have changed | ||
output.filters = 0; | ||
for (q=0; q<m; ++q) { | ||
if (_.modified('query', q)) { i = q; ++mask; } | ||
} | ||
if (mask === 1) { | ||
// only one query changed, use more efficient update | ||
mask = dims[i].one; | ||
this.incrementOne(dims[i], query[i], output.add, output.rem); | ||
} else { | ||
// multiple queries changed, perform full record keeping | ||
for (q=0, mask=0; q<m; ++q) { | ||
if (!_.modified('query', q)) continue; | ||
mask |= dims[q].one; | ||
this.incrementAll(dims[q], query[q], stamp, output.add); | ||
output.rem = output.add; // duplicate add/rem for downstream resolve | ||
if (mask === 1) { | ||
// only one query changed, use more efficient update | ||
mask = dims[i].one; | ||
this.incrementOne(dims[i], query[i], output.add, output.rem); | ||
} else { | ||
// multiple queries changed, perform full record keeping | ||
for (q=0, mask=0; q<m; ++q) { | ||
if (!_.modified('query', q)) continue; | ||
mask |= dims[q].one; | ||
this.incrementAll(dims[q], query[q], stamp, output.add); | ||
output.rem = output.add; // duplicate add/rem for downstream resolve | ||
} | ||
} | ||
} | ||
return mask; | ||
}; | ||
return mask; | ||
}, | ||
prototype.incrementAll = function(dim, query, stamp, out) { | ||
var bits = this.value, | ||
seen = bits.seen(), | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
index = dim.index(), | ||
old = dim.bisect(dim.range), | ||
range = dim.bisect(query), | ||
lo1 = range[0], | ||
hi1 = range[1], | ||
lo0 = old[0], | ||
hi0 = old[1], | ||
one = dim.one, | ||
i, j, k; | ||
incrementAll(dim, query, stamp, out) { | ||
let bits = this.value, | ||
seen = bits.seen(), | ||
curr = bits.curr(), | ||
prev = bits.prev(), | ||
index = dim.index(), | ||
old = dim.bisect(dim.range), | ||
range = dim.bisect(query), | ||
lo1 = range[0], | ||
hi1 = range[1], | ||
lo0 = old[0], | ||
hi0 = old[1], | ||
one = dim.one, | ||
i, j, k; | ||
// Fast incremental update based on previous lo index. | ||
if (lo1 < lo0) { | ||
for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
// Fast incremental update based on previous lo index. | ||
if (lo1 < lo0) { | ||
for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} | ||
curr[k] ^= one; | ||
} | ||
curr[k] ^= one; | ||
} | ||
} else if (lo1 > lo0) { | ||
for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} else if (lo1 > lo0) { | ||
for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} | ||
curr[k] ^= one; | ||
} | ||
curr[k] ^= one; | ||
} | ||
} | ||
// Fast incremental update based on previous hi index. | ||
if (hi1 > hi0) { | ||
for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
// Fast incremental update based on previous hi index. | ||
if (hi1 > hi0) { | ||
for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} | ||
curr[k] ^= one; | ||
} | ||
curr[k] ^= one; | ||
} | ||
} else if (hi1 < hi0) { | ||
for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} else if (hi1 < hi0) { | ||
for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) { | ||
k = index[i]; | ||
if (seen[k] !== stamp) { | ||
prev[k] = curr[k]; | ||
seen[k] = stamp; | ||
out.push(k); | ||
} | ||
curr[k] ^= one; | ||
} | ||
curr[k] ^= one; | ||
} | ||
} | ||
dim.range = query.slice(); | ||
}; | ||
dim.range = query.slice(); | ||
}, | ||
prototype.incrementOne = function(dim, query, add, rem) { | ||
var bits = this.value, | ||
curr = bits.curr(), | ||
index = dim.index(), | ||
old = dim.bisect(dim.range), | ||
range = dim.bisect(query), | ||
lo1 = range[0], | ||
hi1 = range[1], | ||
lo0 = old[0], | ||
hi0 = old[1], | ||
one = dim.one, | ||
i, j, k; | ||
incrementOne(dim, query, add, rem) { | ||
let bits = this.value, | ||
curr = bits.curr(), | ||
index = dim.index(), | ||
old = dim.bisect(dim.range), | ||
range = dim.bisect(query), | ||
lo1 = range[0], | ||
hi1 = range[1], | ||
lo0 = old[0], | ||
hi0 = old[1], | ||
one = dim.one, | ||
i, j, k; | ||
// Fast incremental update based on previous lo index. | ||
if (lo1 < lo0) { | ||
for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
add.push(k); | ||
// Fast incremental update based on previous lo index. | ||
if (lo1 < lo0) { | ||
for (i = lo1, j = Math.min(lo0, hi1); i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
add.push(k); | ||
} | ||
} else if (lo1 > lo0) { | ||
for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
rem.push(k); | ||
} | ||
} | ||
} else if (lo1 > lo0) { | ||
for (i = lo0, j = Math.min(lo1, hi0); i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
rem.push(k); | ||
// Fast incremental update based on previous hi index. | ||
if (hi1 > hi0) { | ||
for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
add.push(k); | ||
} | ||
} else if (hi1 < hi0) { | ||
for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
rem.push(k); | ||
} | ||
} | ||
} | ||
// Fast incremental update based on previous hi index. | ||
if (hi1 > hi0) { | ||
for (i = Math.max(lo1, hi0), j = hi1; i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
add.push(k); | ||
} | ||
} else if (hi1 < hi0) { | ||
for (i = Math.max(lo0, hi1), j = hi0; i < j; ++i) { | ||
k = index[i]; | ||
curr[k] ^= one; | ||
rem.push(k); | ||
} | ||
dim.range = query.slice(); | ||
} | ||
dim.range = query.slice(); | ||
}; | ||
}); |
export default function(index, i, query) { | ||
var bit = (1 << i); | ||
const bit = (1 << i); | ||
@@ -12,4 +12,4 @@ return { | ||
onAdd: function(added, curr) { | ||
var dim = this, | ||
onAdd(added, curr) { | ||
let dim = this, | ||
range = dim.bisect(dim.range, added.value), | ||
@@ -16,0 +16,0 @@ idx = added.index, |
@@ -28,48 +28,45 @@ import {Transform} from 'vega-dataflow'; | ||
var prototype = inherits(ResolveFilter, Transform); | ||
inherits(ResolveFilter, Transform, { | ||
transform(_, pulse) { | ||
const ignore = ~(_.ignore || 0), // bit mask where zeros -> dims to ignore | ||
bitmap = _.filter, | ||
mask = bitmap.mask; | ||
prototype.transform = function(_, pulse) { | ||
var ignore = ~(_.ignore || 0), // bit mask where zeros -> dims to ignore | ||
bitmap = _.filter, | ||
mask = bitmap.mask; | ||
// exit early if no relevant filter changes | ||
if ((mask & ignore) === 0) return pulse.StopPropagation; | ||
// exit early if no relevant filter changes | ||
if ((mask & ignore) === 0) return pulse.StopPropagation; | ||
const output = pulse.fork(pulse.ALL), | ||
data = bitmap.data(), | ||
curr = bitmap.curr(), | ||
prev = bitmap.prev(), | ||
pass = k => !(curr[k] & ignore) ? data[k] : null; | ||
var output = pulse.fork(pulse.ALL), | ||
data = bitmap.data(), | ||
curr = bitmap.curr(), | ||
prev = bitmap.prev(), | ||
pass = function(k) { | ||
return !(curr[k] & ignore) ? data[k] : null; | ||
}; | ||
// propagate all mod tuples that pass the filter | ||
output.filter(output.MOD, pass); | ||
// propagate all mod tuples that pass the filter | ||
output.filter(output.MOD, pass); | ||
// determine add & rem tuples via filter functions | ||
// for efficiency, we do *not* populate new arrays, | ||
// instead we add filter functions applied downstream | ||
// determine add & rem tuples via filter functions | ||
// for efficiency, we do *not* populate new arrays, | ||
// instead we add filter functions applied downstream | ||
if (!(mask & (mask-1))) { // only one filter changed | ||
output.filter(output.ADD, pass); | ||
output.filter(output.REM, k => | ||
(curr[k] & ignore) === mask ? data[k] : null); | ||
if (!(mask & (mask-1))) { // only one filter changed | ||
output.filter(output.ADD, pass); | ||
output.filter(output.REM, function(k) { | ||
return (curr[k] & ignore) === mask ? data[k] : null; | ||
}); | ||
} else { // multiple filters changed | ||
output.filter(output.ADD, k => { | ||
const c = curr[k] & ignore, | ||
f = !c && (c ^ (prev[k] & ignore)); | ||
return f ? data[k] : null; | ||
}); | ||
output.filter(output.REM, k => { | ||
const c = curr[k] & ignore, | ||
f = c && !(c ^ (c ^ (prev[k] & ignore))); | ||
return f ? data[k] : null; | ||
}); | ||
} | ||
} else { // multiple filters changed | ||
output.filter(output.ADD, function(k) { | ||
var c = curr[k] & ignore, | ||
f = !c && (c ^ (prev[k] & ignore)); | ||
return f ? data[k] : null; | ||
}); | ||
output.filter(output.REM, function(k) { | ||
var c = curr[k] & ignore, | ||
f = c && !(c ^ (c ^ (prev[k] & ignore))); | ||
return f ? data[k] : null; | ||
}); | ||
// add filter to source data in case of reflow... | ||
return output.filter(output.SOURCE, t => pass(t._index)); | ||
} | ||
// add filter to source data in case of reflow... | ||
return output.filter(output.SOURCE, function(t) { return pass(t._index); }); | ||
}; | ||
}); |
@@ -8,3 +8,3 @@ import {array32} from './arrays'; | ||
export default function SortedIndex() { | ||
var index = array32(0), | ||
let index = array32(0), | ||
value = [], | ||
@@ -16,3 +16,3 @@ size = 0; | ||
var n0 = size, | ||
let n0 = size, | ||
n1 = data.length, | ||
@@ -49,3 +49,3 @@ addv = Array(n1), | ||
// map: index -> remove | ||
var n = size, | ||
let n = size, | ||
idx, i, j; | ||
@@ -69,3 +69,3 @@ | ||
function reindex(map) { | ||
for (var i=0, n=size; i<n; ++i) { | ||
for (let i=0, n=size; i<n; ++i) { | ||
index[i] = map[index[i]]; | ||
@@ -76,3 +76,3 @@ } | ||
function bisect(range, array) { | ||
var n; | ||
let n; | ||
if (array) { | ||
@@ -95,4 +95,4 @@ n = array.length; | ||
reindex: reindex, | ||
index: function() { return index; }, | ||
size: function() { return size; } | ||
index: () => index, | ||
size: () => size | ||
}; | ||
@@ -102,5 +102,5 @@ } | ||
function sort(values, index) { | ||
values.sort.call(index, function(a, b) { | ||
var x = values[a], | ||
y = values[b]; | ||
values.sort.call(index, (a, b) => { | ||
const x = values[a], | ||
y = values[b]; | ||
return x < y ? -1 : x > y ? 1 : 0; | ||
@@ -112,3 +112,3 @@ }); | ||
function merge(base, value0, index0, n0, value1, index1, n1, value, index) { | ||
var i0 = 0, i1 = 0, i; | ||
let i0 = 0, i1 = 0, i; | ||
@@ -115,0 +115,0 @@ for (i=0; i0 < n0 && i1 < n1; ++i) { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
47056
1221
Updatedd3-array@^2.5.1
Updatedvega-dataflow@^5.7.1
Updatedvega-util@^1.15.0