 85bf1341f3
			
		
	
	85bf1341f3
	
	
	
		
			
			Frontend Enhancements: - Complete React TypeScript frontend with modern UI components - Distributed workflows management interface with real-time updates - Socket.IO integration for live agent status monitoring - Agent management dashboard with cluster visualization - Project management interface with metrics and task tracking - Responsive design with proper error handling and loading states Backend Infrastructure: - Distributed coordinator for multi-agent workflow orchestration - Cluster management API with comprehensive agent operations - Enhanced database models for agents and projects - Project service for filesystem-based project discovery - Performance monitoring and metrics collection - Comprehensive API documentation and error handling Documentation: - Complete distributed development guide (README_DISTRIBUTED.md) - Comprehensive development report with architecture insights - System configuration templates and deployment guides The platform now provides a complete web interface for managing the distributed AI cluster with real-time monitoring, workflow orchestration, and agent coordination capabilities. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			1456 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			1456 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // https://d3js.org/d3-array/ v3.2.4 Copyright 2010-2023 Mike Bostock
 | ||
| (function (global, factory) {
 | ||
| typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
 | ||
| typeof define === 'function' && define.amd ? define(['exports'], factory) :
 | ||
| (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.d3 = global.d3 || {}));
 | ||
| })(this, (function (exports) { 'use strict';
 | ||
| 
 | ||
| function ascending(a, b) {
 | ||
|   return a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
 | ||
| }
 | ||
| 
 | ||
| function descending(a, b) {
 | ||
|   return a == null || b == null ? NaN
 | ||
|     : b < a ? -1
 | ||
|     : b > a ? 1
 | ||
|     : b >= a ? 0
 | ||
|     : NaN;
 | ||
| }
 | ||
| 
 | ||
| function bisector(f) {
 | ||
|   let compare1, compare2, delta;
 | ||
| 
 | ||
|   // If an accessor is specified, promote it to a comparator. In this case we
 | ||
|   // can test whether the search value is (self-) comparable. We can’t do this
 | ||
|   // for a comparator (except for specific, known comparators) because we can’t
 | ||
|   // tell if the comparator is symmetric, and an asymmetric comparator can’t be
 | ||
|   // used to test whether a single value is comparable.
 | ||
|   if (f.length !== 2) {
 | ||
|     compare1 = ascending;
 | ||
|     compare2 = (d, x) => ascending(f(d), x);
 | ||
|     delta = (d, x) => f(d) - x;
 | ||
|   } else {
 | ||
|     compare1 = f === ascending || f === descending ? f : zero;
 | ||
|     compare2 = f;
 | ||
|     delta = f;
 | ||
|   }
 | ||
| 
 | ||
|   function left(a, x, lo = 0, hi = a.length) {
 | ||
|     if (lo < hi) {
 | ||
|       if (compare1(x, x) !== 0) return hi;
 | ||
|       do {
 | ||
|         const mid = (lo + hi) >>> 1;
 | ||
|         if (compare2(a[mid], x) < 0) lo = mid + 1;
 | ||
|         else hi = mid;
 | ||
|       } while (lo < hi);
 | ||
|     }
 | ||
|     return lo;
 | ||
|   }
 | ||
| 
 | ||
|   function right(a, x, lo = 0, hi = a.length) {
 | ||
|     if (lo < hi) {
 | ||
|       if (compare1(x, x) !== 0) return hi;
 | ||
|       do {
 | ||
|         const mid = (lo + hi) >>> 1;
 | ||
|         if (compare2(a[mid], x) <= 0) lo = mid + 1;
 | ||
|         else hi = mid;
 | ||
|       } while (lo < hi);
 | ||
|     }
 | ||
|     return lo;
 | ||
|   }
 | ||
| 
 | ||
|   function center(a, x, lo = 0, hi = a.length) {
 | ||
|     const i = left(a, x, lo, hi - 1);
 | ||
|     return i > lo && delta(a[i - 1], x) > -delta(a[i], x) ? i - 1 : i;
 | ||
|   }
 | ||
| 
 | ||
|   return {left, center, right};
 | ||
| }
 | ||
| 
 | ||
| function zero() {
 | ||
|   return 0;
 | ||
| }
 | ||
| 
 | ||
| function number(x) {
 | ||
|   return x === null ? NaN : +x;
 | ||
| }
 | ||
| 
 | ||
| function* numbers(values, valueof) {
 | ||
|   if (valueof === undefined) {
 | ||
|     for (let value of values) {
 | ||
|       if (value != null && (value = +value) >= value) {
 | ||
|         yield value;
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     let index = -1;
 | ||
|     for (let value of values) {
 | ||
|       if ((value = valueof(value, ++index, values)) != null && (value = +value) >= value) {
 | ||
|         yield value;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| const ascendingBisect = bisector(ascending);
 | ||
| const bisectRight = ascendingBisect.right;
 | ||
| const bisectLeft = ascendingBisect.left;
 | ||
| const bisectCenter = bisector(number).center;
 | ||
| var bisect = bisectRight;
 | ||
| 
 | ||
| function blur(values, r) {
 | ||
|   if (!((r = +r) >= 0)) throw new RangeError("invalid r");
 | ||
|   let length = values.length;
 | ||
|   if (!((length = Math.floor(length)) >= 0)) throw new RangeError("invalid length");
 | ||
|   if (!length || !r) return values;
 | ||
|   const blur = blurf(r);
 | ||
|   const temp = values.slice();
 | ||
|   blur(values, temp, 0, length, 1);
 | ||
|   blur(temp, values, 0, length, 1);
 | ||
|   blur(values, temp, 0, length, 1);
 | ||
|   return values;
 | ||
| }
 | ||
| 
 | ||
| const blur2 = Blur2(blurf);
 | ||
| 
 | ||
| const blurImage = Blur2(blurfImage);
 | ||
| 
 | ||
| function Blur2(blur) {
 | ||
|   return function(data, rx, ry = rx) {
 | ||
|     if (!((rx = +rx) >= 0)) throw new RangeError("invalid rx");
 | ||
|     if (!((ry = +ry) >= 0)) throw new RangeError("invalid ry");
 | ||
|     let {data: values, width, height} = data;
 | ||
|     if (!((width = Math.floor(width)) >= 0)) throw new RangeError("invalid width");
 | ||
|     if (!((height = Math.floor(height !== undefined ? height : values.length / width)) >= 0)) throw new RangeError("invalid height");
 | ||
|     if (!width || !height || (!rx && !ry)) return data;
 | ||
|     const blurx = rx && blur(rx);
 | ||
|     const blury = ry && blur(ry);
 | ||
|     const temp = values.slice();
 | ||
|     if (blurx && blury) {
 | ||
|       blurh(blurx, temp, values, width, height);
 | ||
|       blurh(blurx, values, temp, width, height);
 | ||
|       blurh(blurx, temp, values, width, height);
 | ||
|       blurv(blury, values, temp, width, height);
 | ||
|       blurv(blury, temp, values, width, height);
 | ||
|       blurv(blury, values, temp, width, height);
 | ||
|     } else if (blurx) {
 | ||
|       blurh(blurx, values, temp, width, height);
 | ||
|       blurh(blurx, temp, values, width, height);
 | ||
|       blurh(blurx, values, temp, width, height);
 | ||
|     } else if (blury) {
 | ||
|       blurv(blury, values, temp, width, height);
 | ||
|       blurv(blury, temp, values, width, height);
 | ||
|       blurv(blury, values, temp, width, height);
 | ||
|     }
 | ||
|     return data;
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function blurh(blur, T, S, w, h) {
 | ||
|   for (let y = 0, n = w * h; y < n;) {
 | ||
|     blur(T, S, y, y += w, 1);
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function blurv(blur, T, S, w, h) {
 | ||
|   for (let x = 0, n = w * h; x < w; ++x) {
 | ||
|     blur(T, S, x, x + n, w);
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function blurfImage(radius) {
 | ||
|   const blur = blurf(radius);
 | ||
|   return (T, S, start, stop, step) => {
 | ||
|     start <<= 2, stop <<= 2, step <<= 2;
 | ||
|     blur(T, S, start + 0, stop + 0, step);
 | ||
|     blur(T, S, start + 1, stop + 1, step);
 | ||
|     blur(T, S, start + 2, stop + 2, step);
 | ||
|     blur(T, S, start + 3, stop + 3, step);
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| // Given a target array T, a source array S, sets each value T[i] to the average
 | ||
| // of {S[i - r], …, S[i], …, S[i + r]}, where r = ⌊radius⌋, start <= i < stop,
 | ||
| // for each i, i + step, i + 2 * step, etc., and where S[j] is clamped between
 | ||
| // S[start] (inclusive) and S[stop] (exclusive). If the given radius is not an
 | ||
| // integer, S[i - r - 1] and S[i + r + 1] are added to the sum, each weighted
 | ||
| // according to r - ⌊radius⌋.
 | ||
| function blurf(radius) {
 | ||
|   const radius0 = Math.floor(radius);
 | ||
|   if (radius0 === radius) return bluri(radius);
 | ||
|   const t = radius - radius0;
 | ||
|   const w = 2 * radius + 1;
 | ||
|   return (T, S, start, stop, step) => { // stop must be aligned!
 | ||
|     if (!((stop -= step) >= start)) return; // inclusive stop
 | ||
|     let sum = radius0 * S[start];
 | ||
|     const s0 = step * radius0;
 | ||
|     const s1 = s0 + step;
 | ||
|     for (let i = start, j = start + s0; i < j; i += step) {
 | ||
|       sum += S[Math.min(stop, i)];
 | ||
|     }
 | ||
|     for (let i = start, j = stop; i <= j; i += step) {
 | ||
|       sum += S[Math.min(stop, i + s0)];
 | ||
|       T[i] = (sum + t * (S[Math.max(start, i - s1)] + S[Math.min(stop, i + s1)])) / w;
 | ||
|       sum -= S[Math.max(start, i - s0)];
 | ||
|     }
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| // Like blurf, but optimized for integer radius.
 | ||
| function bluri(radius) {
 | ||
|   const w = 2 * radius + 1;
 | ||
|   return (T, S, start, stop, step) => { // stop must be aligned!
 | ||
|     if (!((stop -= step) >= start)) return; // inclusive stop
 | ||
|     let sum = radius * S[start];
 | ||
|     const s = step * radius;
 | ||
|     for (let i = start, j = start + s; i < j; i += step) {
 | ||
|       sum += S[Math.min(stop, i)];
 | ||
|     }
 | ||
|     for (let i = start, j = stop; i <= j; i += step) {
 | ||
|       sum += S[Math.min(stop, i + s)];
 | ||
|       T[i] = sum / w;
 | ||
|       sum -= S[Math.max(start, i - s)];
 | ||
|     }
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function count(values, valueof) {
 | ||
|   let count = 0;
 | ||
|   if (valueof === undefined) {
 | ||
|     for (let value of values) {
 | ||
|       if (value != null && (value = +value) >= value) {
 | ||
|         ++count;
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     let index = -1;
 | ||
|     for (let value of values) {
 | ||
|       if ((value = valueof(value, ++index, values)) != null && (value = +value) >= value) {
 | ||
|         ++count;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return count;
 | ||
| }
 | ||
| 
 | ||
| function length$1(array) {
 | ||
|   return array.length | 0;
 | ||
| }
 | ||
| 
 | ||
| function empty(length) {
 | ||
|   return !(length > 0);
 | ||
| }
 | ||
| 
 | ||
| function arrayify(values) {
 | ||
|   return typeof values !== "object" || "length" in values ? values : Array.from(values);
 | ||
| }
 | ||
| 
 | ||
| function reducer(reduce) {
 | ||
|   return values => reduce(...values);
 | ||
| }
 | ||
| 
 | ||
| function cross(...values) {
 | ||
|   const reduce = typeof values[values.length - 1] === "function" && reducer(values.pop());
 | ||
|   values = values.map(arrayify);
 | ||
|   const lengths = values.map(length$1);
 | ||
|   const j = values.length - 1;
 | ||
|   const index = new Array(j + 1).fill(0);
 | ||
|   const product = [];
 | ||
|   if (j < 0 || lengths.some(empty)) return product;
 | ||
|   while (true) {
 | ||
|     product.push(index.map((j, i) => values[i][j]));
 | ||
|     let i = j;
 | ||
|     while (++index[i] === lengths[i]) {
 | ||
|       if (i === 0) return reduce ? product.map(reduce) : product;
 | ||
|       index[i--] = 0;
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function cumsum(values, valueof) {
 | ||
|   var sum = 0, index = 0;
 | ||
|   return Float64Array.from(values, valueof === undefined
 | ||
|     ? v => (sum += +v || 0)
 | ||
|     : v => (sum += +valueof(v, index++, values) || 0));
 | ||
| }
 | ||
| 
 | ||
| function variance(values, valueof) {
 | ||
|   let count = 0;
 | ||
|   let delta;
 | ||
|   let mean = 0;
 | ||
|   let sum = 0;
 | ||
|   if (valueof === undefined) {
 | ||
|     for (let value of values) {
 | ||
|       if (value != null && (value = +value) >= value) {
 | ||
|         delta = value - mean;
 | ||
|         mean += delta / ++count;
 | ||
|         sum += delta * (value - mean);
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     let index = -1;
 | ||
|     for (let value of values) {
 | ||
|       if ((value = valueof(value, ++index, values)) != null && (value = +value) >= value) {
 | ||
|         delta = value - mean;
 | ||
|         mean += delta / ++count;
 | ||
|         sum += delta * (value - mean);
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   if (count > 1) return sum / (count - 1);
 | ||
| }
 | ||
| 
 | ||
| function deviation(values, valueof) {
 | ||
|   const v = variance(values, valueof);
 | ||
|   return v ? Math.sqrt(v) : v;
 | ||
| }
 | ||
| 
 | ||
| function extent(values, valueof) {
 | ||
|   let min;
 | ||
|   let max;
 | ||
|   if (valueof === undefined) {
 | ||
|     for (const value of values) {
 | ||
|       if (value != null) {
 | ||
|         if (min === undefined) {
 | ||
|           if (value >= value) min = max = value;
 | ||
|         } else {
 | ||
|           if (min > value) min = value;
 | ||
|           if (max < value) max = value;
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     let index = -1;
 | ||
|     for (let value of values) {
 | ||
|       if ((value = valueof(value, ++index, values)) != null) {
 | ||
|         if (min === undefined) {
 | ||
|           if (value >= value) min = max = value;
 | ||
|         } else {
 | ||
|           if (min > value) min = value;
 | ||
|           if (max < value) max = value;
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return [min, max];
 | ||
| }
 | ||
| 
 | ||
| // https://github.com/python/cpython/blob/a74eea238f5baba15797e2e8b570d153bc8690a7/Modules/mathmodule.c#L1423
 | ||
| class Adder {
 | ||
|   constructor() {
 | ||
|     this._partials = new Float64Array(32);
 | ||
|     this._n = 0;
 | ||
|   }
 | ||
|   add(x) {
 | ||
|     const p = this._partials;
 | ||
|     let i = 0;
 | ||
|     for (let j = 0; j < this._n && j < 32; j++) {
 | ||
|       const y = p[j],
 | ||
|         hi = x + y,
 | ||
|         lo = Math.abs(x) < Math.abs(y) ? x - (hi - y) : y - (hi - x);
 | ||
|       if (lo) p[i++] = lo;
 | ||
|       x = hi;
 | ||
|     }
 | ||
|     p[i] = x;
 | ||
|     this._n = i + 1;
 | ||
|     return this;
 | ||
|   }
 | ||
|   valueOf() {
 | ||
|     const p = this._partials;
 | ||
|     let n = this._n, x, y, lo, hi = 0;
 | ||
|     if (n > 0) {
 | ||
|       hi = p[--n];
 | ||
|       while (n > 0) {
 | ||
|         x = hi;
 | ||
|         y = p[--n];
 | ||
|         hi = x + y;
 | ||
|         lo = y - (hi - x);
 | ||
|         if (lo) break;
 | ||
|       }
 | ||
|       if (n > 0 && ((lo < 0 && p[n - 1] < 0) || (lo > 0 && p[n - 1] > 0))) {
 | ||
|         y = lo * 2;
 | ||
|         x = hi + y;
 | ||
|         if (y == x - hi) hi = x;
 | ||
|       }
 | ||
|     }
 | ||
|     return hi;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function fsum(values, valueof) {
 | ||
|   const adder = new Adder();
 | ||
|   if (valueof === undefined) {
 | ||
|     for (let value of values) {
 | ||
|       if (value = +value) {
 | ||
|         adder.add(value);
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     let index = -1;
 | ||
|     for (let value of values) {
 | ||
|       if (value = +valueof(value, ++index, values)) {
 | ||
|         adder.add(value);
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return +adder;
 | ||
| }
 | ||
| 
 | ||
| function fcumsum(values, valueof) {
 | ||
|   const adder = new Adder();
 | ||
|   let index = -1;
 | ||
|   return Float64Array.from(values, valueof === undefined
 | ||
|       ? v => adder.add(+v || 0)
 | ||
|       : v => adder.add(+valueof(v, ++index, values) || 0)
 | ||
|   );
 | ||
| }
 | ||
| 
 | ||
| class InternMap extends Map {
 | ||
|   constructor(entries, key = keyof) {
 | ||
|     super();
 | ||
|     Object.defineProperties(this, {_intern: {value: new Map()}, _key: {value: key}});
 | ||
|     if (entries != null) for (const [key, value] of entries) this.set(key, value);
 | ||
|   }
 | ||
|   get(key) {
 | ||
|     return super.get(intern_get(this, key));
 | ||
|   }
 | ||
|   has(key) {
 | ||
|     return super.has(intern_get(this, key));
 | ||
|   }
 | ||
|   set(key, value) {
 | ||
|     return super.set(intern_set(this, key), value);
 | ||
|   }
 | ||
|   delete(key) {
 | ||
|     return super.delete(intern_delete(this, key));
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| class InternSet extends Set {
 | ||
|   constructor(values, key = keyof) {
 | ||
|     super();
 | ||
|     Object.defineProperties(this, {_intern: {value: new Map()}, _key: {value: key}});
 | ||
|     if (values != null) for (const value of values) this.add(value);
 | ||
|   }
 | ||
|   has(value) {
 | ||
|     return super.has(intern_get(this, value));
 | ||
|   }
 | ||
|   add(value) {
 | ||
|     return super.add(intern_set(this, value));
 | ||
|   }
 | ||
|   delete(value) {
 | ||
|     return super.delete(intern_delete(this, value));
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function intern_get({_intern, _key}, value) {
 | ||
|   const key = _key(value);
 | ||
|   return _intern.has(key) ? _intern.get(key) : value;
 | ||
| }
 | ||
| 
 | ||
| function intern_set({_intern, _key}, value) {
 | ||
|   const key = _key(value);
 | ||
|   if (_intern.has(key)) return _intern.get(key);
 | ||
|   _intern.set(key, value);
 | ||
|   return value;
 | ||
| }
 | ||
| 
 | ||
| function intern_delete({_intern, _key}, value) {
 | ||
|   const key = _key(value);
 | ||
|   if (_intern.has(key)) {
 | ||
|     value = _intern.get(key);
 | ||
|     _intern.delete(key);
 | ||
|   }
 | ||
|   return value;
 | ||
| }
 | ||
| 
 | ||
| function keyof(value) {
 | ||
|   return value !== null && typeof value === "object" ? value.valueOf() : value;
 | ||
| }
 | ||
| 
 | ||
| function identity(x) {
 | ||
|   return x;
 | ||
| }
 | ||
| 
 | ||
| function group(values, ...keys) {
 | ||
|   return nest(values, identity, identity, keys);
 | ||
| }
 | ||
| 
 | ||
| function groups(values, ...keys) {
 | ||
|   return nest(values, Array.from, identity, keys);
 | ||
| }
 | ||
| 
 | ||
| function flatten$1(groups, keys) {
 | ||
|   for (let i = 1, n = keys.length; i < n; ++i) {
 | ||
|     groups = groups.flatMap(g => g.pop().map(([key, value]) => [...g, key, value]));
 | ||
|   }
 | ||
|   return groups;
 | ||
| }
 | ||
| 
 | ||
| function flatGroup(values, ...keys) {
 | ||
|   return flatten$1(groups(values, ...keys), keys);
 | ||
| }
 | ||
| 
 | ||
| function flatRollup(values, reduce, ...keys) {
 | ||
|   return flatten$1(rollups(values, reduce, ...keys), keys);
 | ||
| }
 | ||
| 
 | ||
| function rollup(values, reduce, ...keys) {
 | ||
|   return nest(values, identity, reduce, keys);
 | ||
| }
 | ||
| 
 | ||
| function rollups(values, reduce, ...keys) {
 | ||
|   return nest(values, Array.from, reduce, keys);
 | ||
| }
 | ||
| 
 | ||
| function index(values, ...keys) {
 | ||
|   return nest(values, identity, unique, keys);
 | ||
| }
 | ||
| 
 | ||
| function indexes(values, ...keys) {
 | ||
|   return nest(values, Array.from, unique, keys);
 | ||
| }
 | ||
| 
 | ||
| function unique(values) {
 | ||
|   if (values.length !== 1) throw new Error("duplicate key");
 | ||
|   return values[0];
 | ||
| }
 | ||
| 
 | ||
| function nest(values, map, reduce, keys) {
 | ||
|   return (function regroup(values, i) {
 | ||
|     if (i >= keys.length) return reduce(values);
 | ||
|     const groups = new InternMap();
 | ||
|     const keyof = keys[i++];
 | ||
|     let index = -1;
 | ||
|     for (const value of values) {
 | ||
|       const key = keyof(value, ++index, values);
 | ||
|       const group = groups.get(key);
 | ||
|       if (group) group.push(value);
 | ||
|       else groups.set(key, [value]);
 | ||
|     }
 | ||
|     for (const [key, values] of groups) {
 | ||
|       groups.set(key, regroup(values, i));
 | ||
|     }
 | ||
|     return map(groups);
 | ||
|   })(values, 0);
 | ||
| }
 | ||
| 
 | ||
| function permute(source, keys) {
 | ||
|   return Array.from(keys, key => source[key]);
 | ||
| }
 | ||
| 
 | ||
| function sort(values, ...F) {
 | ||
|   if (typeof values[Symbol.iterator] !== "function") throw new TypeError("values is not iterable");
 | ||
|   values = Array.from(values);
 | ||
|   let [f] = F;
 | ||
|   if ((f && f.length !== 2) || F.length > 1) {
 | ||
|     const index = Uint32Array.from(values, (d, i) => i);
 | ||
|     if (F.length > 1) {
 | ||
|       F = F.map(f => values.map(f));
 | ||
|       index.sort((i, j) => {
 | ||
|         for (const f of F) {
 | ||
|           const c = ascendingDefined(f[i], f[j]);
 | ||
|           if (c) return c;
 | ||
|         }
 | ||
|       });
 | ||
|     } else {
 | ||
|       f = values.map(f);
 | ||
|       index.sort((i, j) => ascendingDefined(f[i], f[j]));
 | ||
|     }
 | ||
|     return permute(values, index);
 | ||
|   }
 | ||
|   return values.sort(compareDefined(f));
 | ||
| }
 | ||
| 
 | ||
| function compareDefined(compare = ascending) {
 | ||
|   if (compare === ascending) return ascendingDefined;
 | ||
|   if (typeof compare !== "function") throw new TypeError("compare is not a function");
 | ||
|   return (a, b) => {
 | ||
|     const x = compare(a, b);
 | ||
|     if (x || x === 0) return x;
 | ||
|     return (compare(b, b) === 0) - (compare(a, a) === 0);
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function ascendingDefined(a, b) {
 | ||
|   return (a == null || !(a >= a)) - (b == null || !(b >= b)) || (a < b ? -1 : a > b ? 1 : 0);
 | ||
| }
 | ||
| 
 | ||
| function groupSort(values, reduce, key) {
 | ||
|   return (reduce.length !== 2
 | ||
|     ? sort(rollup(values, reduce, key), (([ak, av], [bk, bv]) => ascending(av, bv) || ascending(ak, bk)))
 | ||
|     : sort(group(values, key), (([ak, av], [bk, bv]) => reduce(av, bv) || ascending(ak, bk))))
 | ||
|     .map(([key]) => key);
 | ||
| }
 | ||
| 
 | ||
| var array = Array.prototype;
 | ||
| 
 | ||
| var slice = array.slice;
 | ||
| 
 | ||
| function constant(x) {
 | ||
|   return () => x;
 | ||
| }
 | ||
| 
 | ||
| const e10 = Math.sqrt(50),
 | ||
|     e5 = Math.sqrt(10),
 | ||
|     e2 = Math.sqrt(2);
 | ||
| 
 | ||
| function tickSpec(start, stop, count) {
 | ||
|   const step = (stop - start) / Math.max(0, count),
 | ||
|       power = Math.floor(Math.log10(step)),
 | ||
|       error = step / Math.pow(10, power),
 | ||
|       factor = error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1;
 | ||
|   let i1, i2, inc;
 | ||
|   if (power < 0) {
 | ||
|     inc = Math.pow(10, -power) / factor;
 | ||
|     i1 = Math.round(start * inc);
 | ||
|     i2 = Math.round(stop * inc);
 | ||
|     if (i1 / inc < start) ++i1;
 | ||
|     if (i2 / inc > stop) --i2;
 | ||
|     inc = -inc;
 | ||
|   } else {
 | ||
|     inc = Math.pow(10, power) * factor;
 | ||
|     i1 = Math.round(start / inc);
 | ||
|     i2 = Math.round(stop / inc);
 | ||
|     if (i1 * inc < start) ++i1;
 | ||
|     if (i2 * inc > stop) --i2;
 | ||
|   }
 | ||
|   if (i2 < i1 && 0.5 <= count && count < 2) return tickSpec(start, stop, count * 2);
 | ||
|   return [i1, i2, inc];
 | ||
| }
 | ||
| 
 | ||
| function ticks(start, stop, count) {
 | ||
|   stop = +stop, start = +start, count = +count;
 | ||
|   if (!(count > 0)) return [];
 | ||
|   if (start === stop) return [start];
 | ||
|   const reverse = stop < start, [i1, i2, inc] = reverse ? tickSpec(stop, start, count) : tickSpec(start, stop, count);
 | ||
|   if (!(i2 >= i1)) return [];
 | ||
|   const n = i2 - i1 + 1, ticks = new Array(n);
 | ||
|   if (reverse) {
 | ||
|     if (inc < 0) for (let i = 0; i < n; ++i) ticks[i] = (i2 - i) / -inc;
 | ||
|     else for (let i = 0; i < n; ++i) ticks[i] = (i2 - i) * inc;
 | ||
|   } else {
 | ||
|     if (inc < 0) for (let i = 0; i < n; ++i) ticks[i] = (i1 + i) / -inc;
 | ||
|     else for (let i = 0; i < n; ++i) ticks[i] = (i1 + i) * inc;
 | ||
|   }
 | ||
|   return ticks;
 | ||
| }
 | ||
| 
 | ||
| function tickIncrement(start, stop, count) {
 | ||
|   stop = +stop, start = +start, count = +count;
 | ||
|   return tickSpec(start, stop, count)[2];
 | ||
| }
 | ||
| 
 | ||
| function tickStep(start, stop, count) {
 | ||
|   stop = +stop, start = +start, count = +count;
 | ||
|   const reverse = stop < start, inc = reverse ? tickIncrement(stop, start, count) : tickIncrement(start, stop, count);
 | ||
|   return (reverse ? -1 : 1) * (inc < 0 ? 1 / -inc : inc);
 | ||
| }
 | ||
| 
 | ||
| function nice(start, stop, count) {
 | ||
|   let prestep;
 | ||
|   while (true) {
 | ||
|     const step = tickIncrement(start, stop, count);
 | ||
|     if (step === prestep || step === 0 || !isFinite(step)) {
 | ||
|       return [start, stop];
 | ||
|     } else if (step > 0) {
 | ||
|       start = Math.floor(start / step) * step;
 | ||
|       stop = Math.ceil(stop / step) * step;
 | ||
|     } else if (step < 0) {
 | ||
|       start = Math.ceil(start * step) / step;
 | ||
|       stop = Math.floor(stop * step) / step;
 | ||
|     }
 | ||
|     prestep = step;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function thresholdSturges(values) {
 | ||
|   return Math.max(1, Math.ceil(Math.log(count(values)) / Math.LN2) + 1);
 | ||
| }
 | ||
| 
 | ||
| function bin() {
 | ||
|   var value = identity,
 | ||
|       domain = extent,
 | ||
|       threshold = thresholdSturges;
 | ||
| 
 | ||
|   function histogram(data) {
 | ||
|     if (!Array.isArray(data)) data = Array.from(data);
 | ||
| 
 | ||
|     var i,
 | ||
|         n = data.length,
 | ||
|         x,
 | ||
|         step,
 | ||
|         values = new Array(n);
 | ||
| 
 | ||
|     for (i = 0; i < n; ++i) {
 | ||
|       values[i] = value(data[i], i, data);
 | ||
|     }
 | ||
| 
 | ||
|     var xz = domain(values),
 | ||
|         x0 = xz[0],
 | ||
|         x1 = xz[1],
 | ||
|         tz = threshold(values, x0, x1);
 | ||
| 
 | ||
|     // Convert number of thresholds into uniform thresholds, and nice the
 | ||
|     // default domain accordingly.
 | ||
|     if (!Array.isArray(tz)) {
 | ||
|       const max = x1, tn = +tz;
 | ||
|       if (domain === extent) [x0, x1] = nice(x0, x1, tn);
 | ||
|       tz = ticks(x0, x1, tn);
 | ||
| 
 | ||
|       // If the domain is aligned with the first tick (which it will by
 | ||
|       // default), then we can use quantization rather than bisection to bin
 | ||
|       // values, which is substantially faster.
 | ||
|       if (tz[0] <= x0) step = tickIncrement(x0, x1, tn);
 | ||
| 
 | ||
|       // If the last threshold is coincident with the domain’s upper bound, the
 | ||
|       // last bin will be zero-width. If the default domain is used, and this
 | ||
|       // last threshold is coincident with the maximum input value, we can
 | ||
|       // extend the niced upper bound by one tick to ensure uniform bin widths;
 | ||
|       // otherwise, we simply remove the last threshold. Note that we don’t
 | ||
|       // coerce values or the domain to numbers, and thus must be careful to
 | ||
|       // compare order (>=) rather than strict equality (===)!
 | ||
|       if (tz[tz.length - 1] >= x1) {
 | ||
|         if (max >= x1 && domain === extent) {
 | ||
|           const step = tickIncrement(x0, x1, tn);
 | ||
|           if (isFinite(step)) {
 | ||
|             if (step > 0) {
 | ||
|               x1 = (Math.floor(x1 / step) + 1) * step;
 | ||
|             } else if (step < 0) {
 | ||
|               x1 = (Math.ceil(x1 * -step) + 1) / -step;
 | ||
|             }
 | ||
|           }
 | ||
|         } else {
 | ||
|           tz.pop();
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     // Remove any thresholds outside the domain.
 | ||
|     // Be careful not to mutate an array owned by the user!
 | ||
|     var m = tz.length, a = 0, b = m;
 | ||
|     while (tz[a] <= x0) ++a;
 | ||
|     while (tz[b - 1] > x1) --b;
 | ||
|     if (a || b < m) tz = tz.slice(a, b), m = b - a;
 | ||
| 
 | ||
|     var bins = new Array(m + 1),
 | ||
|         bin;
 | ||
| 
 | ||
|     // Initialize bins.
 | ||
|     for (i = 0; i <= m; ++i) {
 | ||
|       bin = bins[i] = [];
 | ||
|       bin.x0 = i > 0 ? tz[i - 1] : x0;
 | ||
|       bin.x1 = i < m ? tz[i] : x1;
 | ||
|     }
 | ||
| 
 | ||
|     // Assign data to bins by value, ignoring any outside the domain.
 | ||
|     if (isFinite(step)) {
 | ||
|       if (step > 0) {
 | ||
|         for (i = 0; i < n; ++i) {
 | ||
|           if ((x = values[i]) != null && x0 <= x && x <= x1) {
 | ||
|             bins[Math.min(m, Math.floor((x - x0) / step))].push(data[i]);
 | ||
|           }
 | ||
|         }
 | ||
|       } else if (step < 0) {
 | ||
|         for (i = 0; i < n; ++i) {
 | ||
|           if ((x = values[i]) != null && x0 <= x && x <= x1) {
 | ||
|             const j = Math.floor((x0 - x) * step);
 | ||
|             bins[Math.min(m, j + (tz[j] <= x))].push(data[i]); // handle off-by-one due to rounding
 | ||
|           }
 | ||
|         }
 | ||
|       }
 | ||
|     } else {
 | ||
|       for (i = 0; i < n; ++i) {
 | ||
|         if ((x = values[i]) != null && x0 <= x && x <= x1) {
 | ||
|           bins[bisect(tz, x, 0, m)].push(data[i]);
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     return bins;
 | ||
|   }
 | ||
| 
 | ||
|   histogram.value = function(_) {
 | ||
|     return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value;
 | ||
|   };
 | ||
| 
 | ||
|   histogram.domain = function(_) {
 | ||
|     return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain;
 | ||
|   };
 | ||
| 
 | ||
|   histogram.thresholds = function(_) {
 | ||
|     return arguments.length ? (threshold = typeof _ === "function" ? _ : constant(Array.isArray(_) ? slice.call(_) : _), histogram) : threshold;
 | ||
|   };
 | ||
| 
 | ||
|   return histogram;
 | ||
| }
 | ||
| 
 | ||
| function max(values, valueof) {
 | ||
|   let max;
 | ||
|   if (valueof === undefined) {
 | ||
|     for (const value of values) {
 | ||
|       if (value != null
 | ||
|           && (max < value || (max === undefined && value >= value))) {
 | ||
|         max = value;
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     let index = -1;
 | ||
|     for (let value of values) {
 | ||
|       if ((value = valueof(value, ++index, values)) != null
 | ||
|           && (max < value || (max === undefined && value >= value))) {
 | ||
|         max = value;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return max;
 | ||
| }
 | ||
| 
 | ||
| function maxIndex(values, valueof) {
 | ||
|   let max;
 | ||
|   let maxIndex = -1;
 | ||
|   let index = -1;
 | ||
|   if (valueof === undefined) {
 | ||
|     for (const value of values) {
 | ||
|       ++index;
 | ||
|       if (value != null
 | ||
|           && (max < value || (max === undefined && value >= value))) {
 | ||
|         max = value, maxIndex = index;
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     for (let value of values) {
 | ||
|       if ((value = valueof(value, ++index, values)) != null
 | ||
|           && (max < value || (max === undefined && value >= value))) {
 | ||
|         max = value, maxIndex = index;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return maxIndex;
 | ||
| }
 | ||
| 
 | ||
| function min(values, valueof) {
 | ||
|   let min;
 | ||
|   if (valueof === undefined) {
 | ||
|     for (const value of values) {
 | ||
|       if (value != null
 | ||
|           && (min > value || (min === undefined && value >= value))) {
 | ||
|         min = value;
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     let index = -1;
 | ||
|     for (let value of values) {
 | ||
|       if ((value = valueof(value, ++index, values)) != null
 | ||
|           && (min > value || (min === undefined && value >= value))) {
 | ||
|         min = value;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return min;
 | ||
| }
 | ||
| 
 | ||
| function minIndex(values, valueof) {
 | ||
|   let min;
 | ||
|   let minIndex = -1;
 | ||
|   let index = -1;
 | ||
|   if (valueof === undefined) {
 | ||
|     for (const value of values) {
 | ||
|       ++index;
 | ||
|       if (value != null
 | ||
|           && (min > value || (min === undefined && value >= value))) {
 | ||
|         min = value, minIndex = index;
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     for (let value of values) {
 | ||
|       if ((value = valueof(value, ++index, values)) != null
 | ||
|           && (min > value || (min === undefined && value >= value))) {
 | ||
|         min = value, minIndex = index;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return minIndex;
 | ||
| }
 | ||
| 
 | ||
| // Based on https://github.com/mourner/quickselect
 | ||
| // ISC license, Copyright 2018 Vladimir Agafonkin.
 | ||
| function quickselect(array, k, left = 0, right = Infinity, compare) {
 | ||
|   k = Math.floor(k);
 | ||
|   left = Math.floor(Math.max(0, left));
 | ||
|   right = Math.floor(Math.min(array.length - 1, right));
 | ||
| 
 | ||
|   if (!(left <= k && k <= right)) return array;
 | ||
| 
 | ||
|   compare = compare === undefined ? ascendingDefined : compareDefined(compare);
 | ||
| 
 | ||
|   while (right > left) {
 | ||
|     if (right - left > 600) {
 | ||
|       const n = right - left + 1;
 | ||
|       const m = k - left + 1;
 | ||
|       const z = Math.log(n);
 | ||
|       const s = 0.5 * Math.exp(2 * z / 3);
 | ||
|       const sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
 | ||
|       const newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
 | ||
|       const newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
 | ||
|       quickselect(array, k, newLeft, newRight, compare);
 | ||
|     }
 | ||
| 
 | ||
|     const t = array[k];
 | ||
|     let i = left;
 | ||
|     let j = right;
 | ||
| 
 | ||
|     swap(array, left, k);
 | ||
|     if (compare(array[right], t) > 0) swap(array, left, right);
 | ||
| 
 | ||
|     while (i < j) {
 | ||
|       swap(array, i, j), ++i, --j;
 | ||
|       while (compare(array[i], t) < 0) ++i;
 | ||
|       while (compare(array[j], t) > 0) --j;
 | ||
|     }
 | ||
| 
 | ||
|     if (compare(array[left], t) === 0) swap(array, left, j);
 | ||
|     else ++j, swap(array, j, right);
 | ||
| 
 | ||
|     if (j <= k) left = j + 1;
 | ||
|     if (k <= j) right = j - 1;
 | ||
|   }
 | ||
| 
 | ||
|   return array;
 | ||
| }
 | ||
| 
 | ||
| function swap(array, i, j) {
 | ||
|   const t = array[i];
 | ||
|   array[i] = array[j];
 | ||
|   array[j] = t;
 | ||
| }
 | ||
| 
 | ||
| function greatest(values, compare = ascending) {
 | ||
|   let max;
 | ||
|   let defined = false;
 | ||
|   if (compare.length === 1) {
 | ||
|     let maxValue;
 | ||
|     for (const element of values) {
 | ||
|       const value = compare(element);
 | ||
|       if (defined
 | ||
|           ? ascending(value, maxValue) > 0
 | ||
|           : ascending(value, value) === 0) {
 | ||
|         max = element;
 | ||
|         maxValue = value;
 | ||
|         defined = true;
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     for (const value of values) {
 | ||
|       if (defined
 | ||
|           ? compare(value, max) > 0
 | ||
|           : compare(value, value) === 0) {
 | ||
|         max = value;
 | ||
|         defined = true;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return max;
 | ||
| }
 | ||
| 
 | ||
| function quantile(values, p, valueof) {
 | ||
|   values = Float64Array.from(numbers(values, valueof));
 | ||
|   if (!(n = values.length) || isNaN(p = +p)) return;
 | ||
|   if (p <= 0 || n < 2) return min(values);
 | ||
|   if (p >= 1) return max(values);
 | ||
|   var n,
 | ||
|       i = (n - 1) * p,
 | ||
|       i0 = Math.floor(i),
 | ||
|       value0 = max(quickselect(values, i0).subarray(0, i0 + 1)),
 | ||
|       value1 = min(values.subarray(i0 + 1));
 | ||
|   return value0 + (value1 - value0) * (i - i0);
 | ||
| }
 | ||
| 
 | ||
| function quantileSorted(values, p, valueof = number) {
 | ||
|   if (!(n = values.length) || isNaN(p = +p)) return;
 | ||
|   if (p <= 0 || n < 2) return +valueof(values[0], 0, values);
 | ||
|   if (p >= 1) return +valueof(values[n - 1], n - 1, values);
 | ||
|   var n,
 | ||
|       i = (n - 1) * p,
 | ||
|       i0 = Math.floor(i),
 | ||
|       value0 = +valueof(values[i0], i0, values),
 | ||
|       value1 = +valueof(values[i0 + 1], i0 + 1, values);
 | ||
|   return value0 + (value1 - value0) * (i - i0);
 | ||
| }
 | ||
| 
 | ||
| function quantileIndex(values, p, valueof = number) {
 | ||
|   if (isNaN(p = +p)) return;
 | ||
|   numbers = Float64Array.from(values, (_, i) => number(valueof(values[i], i, values)));
 | ||
|   if (p <= 0) return minIndex(numbers);
 | ||
|   if (p >= 1) return maxIndex(numbers);
 | ||
|   var numbers,
 | ||
|       index = Uint32Array.from(values, (_, i) => i),
 | ||
|       j = numbers.length - 1,
 | ||
|       i = Math.floor(j * p);
 | ||
|   quickselect(index, i, 0, j, (i, j) => ascendingDefined(numbers[i], numbers[j]));
 | ||
|   i = greatest(index.subarray(0, i + 1), (i) => numbers[i]);
 | ||
|   return i >= 0 ? i : -1;
 | ||
| }
 | ||
| 
 | ||
| function thresholdFreedmanDiaconis(values, min, max) {
 | ||
|   const c = count(values), d = quantile(values, 0.75) - quantile(values, 0.25);
 | ||
|   return c && d ? Math.ceil((max - min) / (2 * d * Math.pow(c, -1 / 3))) : 1;
 | ||
| }
 | ||
| 
 | ||
| function thresholdScott(values, min, max) {
 | ||
|   const c = count(values), d = deviation(values);
 | ||
|   return c && d ? Math.ceil((max - min) * Math.cbrt(c) / (3.49 * d)) : 1;
 | ||
| }
 | ||
| 
 | ||
| function mean(values, valueof) {
 | ||
|   let count = 0;
 | ||
|   let sum = 0;
 | ||
|   if (valueof === undefined) {
 | ||
|     for (let value of values) {
 | ||
|       if (value != null && (value = +value) >= value) {
 | ||
|         ++count, sum += value;
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     let index = -1;
 | ||
|     for (let value of values) {
 | ||
|       if ((value = valueof(value, ++index, values)) != null && (value = +value) >= value) {
 | ||
|         ++count, sum += value;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   if (count) return sum / count;
 | ||
| }
 | ||
| 
 | ||
| function median(values, valueof) {
 | ||
|   return quantile(values, 0.5, valueof);
 | ||
| }
 | ||
| 
 | ||
| function medianIndex(values, valueof) {
 | ||
|   return quantileIndex(values, 0.5, valueof);
 | ||
| }
 | ||
| 
 | ||
| function* flatten(arrays) {
 | ||
|   for (const array of arrays) {
 | ||
|     yield* array;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| function merge(arrays) {
 | ||
|   return Array.from(flatten(arrays));
 | ||
| }
 | ||
| 
 | ||
| function mode(values, valueof) {
 | ||
|   const counts = new InternMap();
 | ||
|   if (valueof === undefined) {
 | ||
|     for (let value of values) {
 | ||
|       if (value != null && value >= value) {
 | ||
|         counts.set(value, (counts.get(value) || 0) + 1);
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     let index = -1;
 | ||
|     for (let value of values) {
 | ||
|       if ((value = valueof(value, ++index, values)) != null && value >= value) {
 | ||
|         counts.set(value, (counts.get(value) || 0) + 1);
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   let modeValue;
 | ||
|   let modeCount = 0;
 | ||
|   for (const [value, count] of counts) {
 | ||
|     if (count > modeCount) {
 | ||
|       modeCount = count;
 | ||
|       modeValue = value;
 | ||
|     }
 | ||
|   }
 | ||
|   return modeValue;
 | ||
| }
 | ||
| 
 | ||
| function pairs(values, pairof = pair) {
 | ||
|   const pairs = [];
 | ||
|   let previous;
 | ||
|   let first = false;
 | ||
|   for (const value of values) {
 | ||
|     if (first) pairs.push(pairof(previous, value));
 | ||
|     previous = value;
 | ||
|     first = true;
 | ||
|   }
 | ||
|   return pairs;
 | ||
| }
 | ||
| 
 | ||
| function pair(a, b) {
 | ||
|   return [a, b];
 | ||
| }
 | ||
| 
 | ||
| function range(start, stop, step) {
 | ||
|   start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
 | ||
| 
 | ||
|   var i = -1,
 | ||
|       n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
 | ||
|       range = new Array(n);
 | ||
| 
 | ||
|   while (++i < n) {
 | ||
|     range[i] = start + i * step;
 | ||
|   }
 | ||
| 
 | ||
|   return range;
 | ||
| }
 | ||
| 
 | ||
| function rank(values, valueof = ascending) {
 | ||
|   if (typeof values[Symbol.iterator] !== "function") throw new TypeError("values is not iterable");
 | ||
|   let V = Array.from(values);
 | ||
|   const R = new Float64Array(V.length);
 | ||
|   if (valueof.length !== 2) V = V.map(valueof), valueof = ascending;
 | ||
|   const compareIndex = (i, j) => valueof(V[i], V[j]);
 | ||
|   let k, r;
 | ||
|   values = Uint32Array.from(V, (_, i) => i);
 | ||
|   // Risky chaining due to Safari 14 https://github.com/d3/d3-array/issues/123
 | ||
|   values.sort(valueof === ascending ? (i, j) => ascendingDefined(V[i], V[j]) : compareDefined(compareIndex));
 | ||
|   values.forEach((j, i) => {
 | ||
|       const c = compareIndex(j, k === undefined ? j : k);
 | ||
|       if (c >= 0) {
 | ||
|         if (k === undefined || c > 0) k = j, r = i;
 | ||
|         R[j] = r;
 | ||
|       } else {
 | ||
|         R[j] = NaN;
 | ||
|       }
 | ||
|     });
 | ||
|   return R;
 | ||
| }
 | ||
| 
 | ||
| function least(values, compare = ascending) {
 | ||
|   let min;
 | ||
|   let defined = false;
 | ||
|   if (compare.length === 1) {
 | ||
|     let minValue;
 | ||
|     for (const element of values) {
 | ||
|       const value = compare(element);
 | ||
|       if (defined
 | ||
|           ? ascending(value, minValue) < 0
 | ||
|           : ascending(value, value) === 0) {
 | ||
|         min = element;
 | ||
|         minValue = value;
 | ||
|         defined = true;
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     for (const value of values) {
 | ||
|       if (defined
 | ||
|           ? compare(value, min) < 0
 | ||
|           : compare(value, value) === 0) {
 | ||
|         min = value;
 | ||
|         defined = true;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return min;
 | ||
| }
 | ||
| 
 | ||
| function leastIndex(values, compare = ascending) {
 | ||
|   if (compare.length === 1) return minIndex(values, compare);
 | ||
|   let minValue;
 | ||
|   let min = -1;
 | ||
|   let index = -1;
 | ||
|   for (const value of values) {
 | ||
|     ++index;
 | ||
|     if (min < 0
 | ||
|         ? compare(value, value) === 0
 | ||
|         : compare(value, minValue) < 0) {
 | ||
|       minValue = value;
 | ||
|       min = index;
 | ||
|     }
 | ||
|   }
 | ||
|   return min;
 | ||
| }
 | ||
| 
 | ||
| function greatestIndex(values, compare = ascending) {
 | ||
|   if (compare.length === 1) return maxIndex(values, compare);
 | ||
|   let maxValue;
 | ||
|   let max = -1;
 | ||
|   let index = -1;
 | ||
|   for (const value of values) {
 | ||
|     ++index;
 | ||
|     if (max < 0
 | ||
|         ? compare(value, value) === 0
 | ||
|         : compare(value, maxValue) > 0) {
 | ||
|       maxValue = value;
 | ||
|       max = index;
 | ||
|     }
 | ||
|   }
 | ||
|   return max;
 | ||
| }
 | ||
| 
 | ||
| function scan(values, compare) {
 | ||
|   const index = leastIndex(values, compare);
 | ||
|   return index < 0 ? undefined : index;
 | ||
| }
 | ||
| 
 | ||
| var shuffle = shuffler(Math.random);
 | ||
| 
 | ||
| function shuffler(random) {
 | ||
|   return function shuffle(array, i0 = 0, i1 = array.length) {
 | ||
|     let m = i1 - (i0 = +i0);
 | ||
|     while (m) {
 | ||
|       const i = random() * m-- | 0, t = array[m + i0];
 | ||
|       array[m + i0] = array[i + i0];
 | ||
|       array[i + i0] = t;
 | ||
|     }
 | ||
|     return array;
 | ||
|   };
 | ||
| }
 | ||
| 
 | ||
| function sum(values, valueof) {
 | ||
|   let sum = 0;
 | ||
|   if (valueof === undefined) {
 | ||
|     for (let value of values) {
 | ||
|       if (value = +value) {
 | ||
|         sum += value;
 | ||
|       }
 | ||
|     }
 | ||
|   } else {
 | ||
|     let index = -1;
 | ||
|     for (let value of values) {
 | ||
|       if (value = +valueof(value, ++index, values)) {
 | ||
|         sum += value;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return sum;
 | ||
| }
 | ||
| 
 | ||
| function transpose(matrix) {
 | ||
|   if (!(n = matrix.length)) return [];
 | ||
|   for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) {
 | ||
|     for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) {
 | ||
|       row[j] = matrix[j][i];
 | ||
|     }
 | ||
|   }
 | ||
|   return transpose;
 | ||
| }
 | ||
| 
 | ||
| function length(d) {
 | ||
|   return d.length;
 | ||
| }
 | ||
| 
 | ||
| function zip() {
 | ||
|   return transpose(arguments);
 | ||
| }
 | ||
| 
 | ||
| function every(values, test) {
 | ||
|   if (typeof test !== "function") throw new TypeError("test is not a function");
 | ||
|   let index = -1;
 | ||
|   for (const value of values) {
 | ||
|     if (!test(value, ++index, values)) {
 | ||
|       return false;
 | ||
|     }
 | ||
|   }
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| function some(values, test) {
 | ||
|   if (typeof test !== "function") throw new TypeError("test is not a function");
 | ||
|   let index = -1;
 | ||
|   for (const value of values) {
 | ||
|     if (test(value, ++index, values)) {
 | ||
|       return true;
 | ||
|     }
 | ||
|   }
 | ||
|   return false;
 | ||
| }
 | ||
| 
 | ||
| function filter(values, test) {
 | ||
|   if (typeof test !== "function") throw new TypeError("test is not a function");
 | ||
|   const array = [];
 | ||
|   let index = -1;
 | ||
|   for (const value of values) {
 | ||
|     if (test(value, ++index, values)) {
 | ||
|       array.push(value);
 | ||
|     }
 | ||
|   }
 | ||
|   return array;
 | ||
| }
 | ||
| 
 | ||
| function map(values, mapper) {
 | ||
|   if (typeof values[Symbol.iterator] !== "function") throw new TypeError("values is not iterable");
 | ||
|   if (typeof mapper !== "function") throw new TypeError("mapper is not a function");
 | ||
|   return Array.from(values, (value, index) => mapper(value, index, values));
 | ||
| }
 | ||
| 
 | ||
| function reduce(values, reducer, value) {
 | ||
|   if (typeof reducer !== "function") throw new TypeError("reducer is not a function");
 | ||
|   const iterator = values[Symbol.iterator]();
 | ||
|   let done, next, index = -1;
 | ||
|   if (arguments.length < 3) {
 | ||
|     ({done, value} = iterator.next());
 | ||
|     if (done) return;
 | ||
|     ++index;
 | ||
|   }
 | ||
|   while (({done, value: next} = iterator.next()), !done) {
 | ||
|     value = reducer(value, next, ++index, values);
 | ||
|   }
 | ||
|   return value;
 | ||
| }
 | ||
| 
 | ||
| function reverse(values) {
 | ||
|   if (typeof values[Symbol.iterator] !== "function") throw new TypeError("values is not iterable");
 | ||
|   return Array.from(values).reverse();
 | ||
| }
 | ||
| 
 | ||
| function difference(values, ...others) {
 | ||
|   values = new InternSet(values);
 | ||
|   for (const other of others) {
 | ||
|     for (const value of other) {
 | ||
|       values.delete(value);
 | ||
|     }
 | ||
|   }
 | ||
|   return values;
 | ||
| }
 | ||
| 
 | ||
| function disjoint(values, other) {
 | ||
|   const iterator = other[Symbol.iterator](), set = new InternSet();
 | ||
|   for (const v of values) {
 | ||
|     if (set.has(v)) return false;
 | ||
|     let value, done;
 | ||
|     while (({value, done} = iterator.next())) {
 | ||
|       if (done) break;
 | ||
|       if (Object.is(v, value)) return false;
 | ||
|       set.add(value);
 | ||
|     }
 | ||
|   }
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| function intersection(values, ...others) {
 | ||
|   values = new InternSet(values);
 | ||
|   others = others.map(set);
 | ||
|   out: for (const value of values) {
 | ||
|     for (const other of others) {
 | ||
|       if (!other.has(value)) {
 | ||
|         values.delete(value);
 | ||
|         continue out;
 | ||
|       }
 | ||
|     }
 | ||
|   }
 | ||
|   return values;
 | ||
| }
 | ||
| 
 | ||
| function set(values) {
 | ||
|   return values instanceof InternSet ? values : new InternSet(values);
 | ||
| }
 | ||
| 
 | ||
| function superset(values, other) {
 | ||
|   const iterator = values[Symbol.iterator](), set = new Set();
 | ||
|   for (const o of other) {
 | ||
|     const io = intern(o);
 | ||
|     if (set.has(io)) continue;
 | ||
|     let value, done;
 | ||
|     while (({value, done} = iterator.next())) {
 | ||
|       if (done) return false;
 | ||
|       const ivalue = intern(value);
 | ||
|       set.add(ivalue);
 | ||
|       if (Object.is(io, ivalue)) break;
 | ||
|     }
 | ||
|   }
 | ||
|   return true;
 | ||
| }
 | ||
| 
 | ||
| function intern(value) {
 | ||
|   return value !== null && typeof value === "object" ? value.valueOf() : value;
 | ||
| }
 | ||
| 
 | ||
| function subset(values, other) {
 | ||
|   return superset(other, values);
 | ||
| }
 | ||
| 
 | ||
| function union(...others) {
 | ||
|   const set = new InternSet();
 | ||
|   for (const other of others) {
 | ||
|     for (const o of other) {
 | ||
|       set.add(o);
 | ||
|     }
 | ||
|   }
 | ||
|   return set;
 | ||
| }
 | ||
| 
 | ||
| exports.Adder = Adder;
 | ||
| exports.InternMap = InternMap;
 | ||
| exports.InternSet = InternSet;
 | ||
| exports.ascending = ascending;
 | ||
| exports.bin = bin;
 | ||
| exports.bisect = bisect;
 | ||
| exports.bisectCenter = bisectCenter;
 | ||
| exports.bisectLeft = bisectLeft;
 | ||
| exports.bisectRight = bisectRight;
 | ||
| exports.bisector = bisector;
 | ||
| exports.blur = blur;
 | ||
| exports.blur2 = blur2;
 | ||
| exports.blurImage = blurImage;
 | ||
| exports.count = count;
 | ||
| exports.cross = cross;
 | ||
| exports.cumsum = cumsum;
 | ||
| exports.descending = descending;
 | ||
| exports.deviation = deviation;
 | ||
| exports.difference = difference;
 | ||
| exports.disjoint = disjoint;
 | ||
| exports.every = every;
 | ||
| exports.extent = extent;
 | ||
| exports.fcumsum = fcumsum;
 | ||
| exports.filter = filter;
 | ||
| exports.flatGroup = flatGroup;
 | ||
| exports.flatRollup = flatRollup;
 | ||
| exports.fsum = fsum;
 | ||
| exports.greatest = greatest;
 | ||
| exports.greatestIndex = greatestIndex;
 | ||
| exports.group = group;
 | ||
| exports.groupSort = groupSort;
 | ||
| exports.groups = groups;
 | ||
| exports.histogram = bin;
 | ||
| exports.index = index;
 | ||
| exports.indexes = indexes;
 | ||
| exports.intersection = intersection;
 | ||
| exports.least = least;
 | ||
| exports.leastIndex = leastIndex;
 | ||
| exports.map = map;
 | ||
| exports.max = max;
 | ||
| exports.maxIndex = maxIndex;
 | ||
| exports.mean = mean;
 | ||
| exports.median = median;
 | ||
| exports.medianIndex = medianIndex;
 | ||
| exports.merge = merge;
 | ||
| exports.min = min;
 | ||
| exports.minIndex = minIndex;
 | ||
| exports.mode = mode;
 | ||
| exports.nice = nice;
 | ||
| exports.pairs = pairs;
 | ||
| exports.permute = permute;
 | ||
| exports.quantile = quantile;
 | ||
| exports.quantileIndex = quantileIndex;
 | ||
| exports.quantileSorted = quantileSorted;
 | ||
| exports.quickselect = quickselect;
 | ||
| exports.range = range;
 | ||
| exports.rank = rank;
 | ||
| exports.reduce = reduce;
 | ||
| exports.reverse = reverse;
 | ||
| exports.rollup = rollup;
 | ||
| exports.rollups = rollups;
 | ||
| exports.scan = scan;
 | ||
| exports.shuffle = shuffle;
 | ||
| exports.shuffler = shuffler;
 | ||
| exports.some = some;
 | ||
| exports.sort = sort;
 | ||
| exports.subset = subset;
 | ||
| exports.sum = sum;
 | ||
| exports.superset = superset;
 | ||
| exports.thresholdFreedmanDiaconis = thresholdFreedmanDiaconis;
 | ||
| exports.thresholdScott = thresholdScott;
 | ||
| exports.thresholdSturges = thresholdSturges;
 | ||
| exports.tickIncrement = tickIncrement;
 | ||
| exports.tickStep = tickStep;
 | ||
| exports.ticks = ticks;
 | ||
| exports.transpose = transpose;
 | ||
| exports.union = union;
 | ||
| exports.variance = variance;
 | ||
| exports.zip = zip;
 | ||
| 
 | ||
| }));
 |