arquero
Version:
Query processing and transformation of array-backed data tables.
1,652 lines (1,492 loc) • 759 kB
JavaScript
(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.aq = {}));
})(this, (function (exports) { 'use strict';
const ONE = 0x80000000;
const ALL = 0xFFFFFFFF;
/**
* Represent an indexable set of bits.
*/
class BitSet {
/**
* Instantiate a new BitSet instance.
* @param {number} size The number of bits.
*/
constructor(size) {
this._size = size;
this._bits = new Uint32Array(Math.ceil(size / 32));
}
/**
* The number of bits.
* @return {number}
*/
get length() {
return this._size;
}
/**
* The number of bits set to one.
* https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
* @return {number}
*/
count() {
const n = this._bits.length;
let count = 0;
for (let i = 0; i < n; ++i) {
for (let b = this._bits[i]; b; ++count) {
b &= b - 1;
}
}
return count;
}
/**
* Get the bit at a given index.
* @param {number} i The bit index.
*/
get(i) {
return this._bits[i >> 5] & (ONE >>> i);
}
/**
* Set the bit at a given index to one.
* @param {number} i The bit index.
*/
set(i) {
this._bits[i >> 5] |= (ONE >>> i);
}
/**
* Clear the bit at a given index to zero.
* @param {number} i The bit index.
*/
clear(i) {
this._bits[i >> 5] &= ~(ONE >>> i);
}
/**
* Scan the bits, invoking a callback function with the index of
* each non-zero bit.
* @param {(i: number) => void} fn A callback function.
*/
scan(fn) {
for (let i = this.next(0); i >= 0; i = this.next(i + 1)) {
fn(i);
}
}
/**
* Get the next non-zero bit starting from a given index.
* @param {number} i The bit index.
*/
next(i) {
const bits = this._bits;
const n = bits.length;
let index = i >> 5;
let curr = bits[index] & (ALL >>> i);
for (; index < n; curr = bits[++index]) {
if (curr !== 0) {
return (index << 5) + Math.clz32(curr);
}
}
return -1;
}
/**
* Return the index of the nth non-zero bit.
* @param {number} n The number of non-zero bits to advance.
* @return {number} The index of the nth non-zero bit.
*/
nth(n) {
let i = this.next(0);
while (n-- && i >= 0) i = this.next(i + 1);
return i;
}
/**
* Negate all bits in this bitset.
* Modifies this BitSet in place.
* @return {this}
*/
not() {
const bits = this._bits;
const n = bits.length;
// invert all bits
for (let i = 0; i < n; ++i) {
bits[i] = ~bits[i];
}
// unset extraneous trailing bits
const tail = this._size % 32;
if (tail) {
bits[n - 1] &= ONE >> (tail - 1);
}
return this;
}
/**
* Compute the logical AND of this BitSet and another.
* @param {BitSet} bitset The BitSet to combine with.
* @return {BitSet} This BitSet updated with the logical AND.
*/
and(bitset) {
if (bitset) {
const a = this._bits;
const b = bitset._bits;
const n = a.length;
for (let i = 0; i < n; ++i) {
a[i] &= b[i];
}
}
return this;
}
/**
* Compute the logical OR of this BitSet and another.
* @param {BitSet} bitset The BitSet to combine with.
* @return {BitSet} This BitSet updated with the logical OR.
*/
or(bitset) {
if (bitset) {
const a = this._bits;
const b = bitset._bits;
const n = a.length;
for (let i = 0; i < n; ++i) {
a[i] |= b[i];
}
}
return this;
}
}
/**
* Truncate a value to a bin boundary.
* Useful for creating equal-width histograms.
* Values outside the [min, max] range will be mapped to
* -Infinity (< min) or +Infinity (> max).
* @param {number} value The value to bin.
* @param {number} min The minimum bin boundary.
* @param {number} max The maximum bin boundary.
* @param {number} step The step size between bin boundaries.
* @param {number} [offset=0] Offset in steps by which to adjust
* the bin value. An offset of 1 will return the next boundary.
*/
function bin$1(value, min, max, step, offset) {
return value == null ? null
: value < min ? -Infinity
: value > max ? +Infinity
: (
value = Math.max(min, Math.min(value, max)),
min + step * Math.floor(1e-14 + (value - min) / step + (offset || 0))
);
}
/**
* @param {*} value
* @returns {value is Date}
*/
function isDate$1(value) {
return value instanceof Date;
}
/**
* @param {*} value
* @returns {value is RegExp}
*/
function isRegExp(value) {
return value instanceof RegExp;
}
function isObject(value) {
return value === Object(value);
}
/**
* Compare two values for equality, using join semantics in which null
* !== null. If the inputs are object-valued, a deep equality check
* of array entries or object key-value pairs is performed.
* @param {*} a The first input.
* @param {*} b The second input.
* @return {boolean} True if equal, false if not.
*/
function equal(a, b) {
return (a == null || b == null || a !== a || b !== b) ? false
: a === b ? true
: (isDate$1(a) || isDate$1(b)) ? +a === +b
: (isRegExp(a) && isRegExp(b)) ? a + '' === b + ''
: (isObject(a) && isObject(b)) ? deepEqual(a, b)
: false;
}
function deepEqual(a, b) {
if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) {
return false;
}
if (a.length || b.length) {
return arrayEqual(a, b);
}
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) {
return false;
}
keysA.sort();
keysB.sort();
if (!arrayEqual(keysA, keysB, (a, b) => a === b)) {
return false;
}
const n = keysA.length;
for (let i = 0; i < n; ++i) {
const k = keysA[i];
if (!equal(a[k], b[k])) {
return false;
}
}
return true;
}
function arrayEqual(a, b, test = equal) {
const n = a.length;
if (n !== b.length) return false;
for (let i = 0; i < n; ++i) {
if (!test(a[i], b[i])) {
return false;
}
}
return true;
}
/**
* Recodes an input value to an alternative value, based on a provided
* value map. If a fallback value is specified, it will be returned when
* a matching value is not found in the map; otherwise, the input value
* is returned unchanged.
* @template T
* @param {T} value The value to recode. The value must be safely
* coercible to a string for lookup against the value map.
* @param {Map|Record<string,any>} map An object or Map with input values
* for keys and output recoded values as values. If a non-Map object, only
* the object's own properties will be considered.
* @param {T} [fallback] A default fallback value to use if the input
* value is not found in the value map.
* @return {T} The recoded value.
*/
function recode(value, map, fallback) {
if (map instanceof Map) {
if (map.has(value)) return map.get(value);
} else {
const key = `${value}`;
if (Object.hasOwn(map, key)) return map[key];
}
return fallback !== undefined ? fallback : value;
}
/**
* Returns an array containing an arithmetic sequence from the start value
* to the stop value, in step increments. If step is positive, the last
* element is the largest start + i * step less than stop; if step is
* negative, the last element is the smallest start + i * step greater
* than stop. If the returned array would contain an infinite number of
* values, an empty range is returned.
* @param {number} [start=0] The starting value of the sequence.
* @param {number} [stop] The stopping value of the sequence.
* The stop value is exclusive; it is not included in the result.
* @param {number} [step=1] The step increment between sequence values.
* @return {number[]} The generated sequence.
*/
function sequence(start, stop, step) {
let n = arguments.length;
start = +start;
stop = +stop;
step = n < 2
? (stop = start, start = 0, 1)
: n < 3 ? 1 : +step;
n = Math.max(0, Math.ceil((stop - start) / step)) | 0;
const seq = new Array(n);
for (let i = 0; i < n; ++i) {
seq[i] = start + i * step;
}
return seq;
}
/**
* Default NULL (missing) value to use.
*/
const NULL = undefined;
/**
* @param {*} value
* @returns {value is Array}
*/
function isArray$2(value) {
return Array.isArray(value);
}
const TypedArray$1 = Object.getPrototypeOf(Int8Array);
/**
* @param {*} value
* @return {value is import("../table/types.js").TypedArray}
*/
function isTypedArray$1(value) {
return value instanceof TypedArray$1;
}
/**
* @param {*} value
* @return {value is (any[] | import('../table/types.js').TypedArray)}
*/
function isArrayType(value) {
return isArray$2(value) || isTypedArray$1(value);
}
/**
* @param {*} value
* @return {value is String}
*/
function isString(value) {
return typeof value === 'string';
}
function isValid(value) {
return value != null && value === value;
}
const isSeq = (seq) => isArrayType(seq) || isString(seq);
/**
* Returns a new compacted array with invalid values
* (`null`, `undefined`, `NaN`) removed.
* @template T
* @param {T[]} array The input array.
* @return {T[]} A compacted array.
*/
function compact(array) {
return isArrayType(array)
? array.filter(v => isValid(v))
: array;
}
/**
* Merges two or more arrays in sequence, returning a new array.
* @template T
* @param {...(T|T[])} values The arrays to merge.
* @return {T[]} The merged array.
*/
function concat$2(...values) {
return [].concat(...values);
}
/**
* Determines whether an *array* includes a certain *value* among its
* entries, returning `true` or `false` as appropriate.
* @template T
* @param {T[]} sequence The input array value.
* @param {T} value The value to search for.
* @param {number} [index=0] The integer index to start searching
* from (default `0`).
* @return {boolean} True if the value is included, false otherwise.
*/
function includes(sequence, value, index) {
return isSeq(sequence)
? sequence.includes(value, index)
: false;
}
/**
* Returns the first index at which a given *value* can be found in the
* *sequence* (array or string), or -1 if it is not present.
* @template T
* @param {T[]|string} sequence The input array or string value.
* @param {T} value The value to search for.
* @return {number} The index of the value, or -1 if not present.
*/
function indexof(sequence, value) {
return isSeq(sequence)
// @ts-ignore
? sequence.indexOf(value)
: -1;
}
/**
* Creates and returns a new string by concatenating all of the elements
* in an *array* (or an array-like object), separated by commas or a
* specified *delimiter* string. If the *array* has only one item, then
* that item will be returned without using the delimiter.
* @template T
* @param {T[]} array The input array value.
* @param {string} delim The delimiter string (default `','`).
* @return {string} The joined string.
*/
function join$1(array, delim) {
return isArrayType(array) ? array.join(delim) : NULL;
}
/**
* Returns the last index at which a given *value* can be found in the
* *sequence* (array or string), or -1 if it is not present.
* @template T
* @param {T[]|string} sequence The input array or string value.
* @param {T} value The value to search for.
* @return {number} The last index of the value, or -1 if not present.
*/
function lastindexof(sequence, value) {
return isSeq(sequence)
// @ts-ignore
? sequence.lastIndexOf(value)
: -1;
}
/**
* Returns the length of the input *sequence* (array or string).
* @param {Array|string} sequence The input array or string value.
* @return {number} The length of the sequence.
*/
function length(sequence) {
return isSeq(sequence) ? sequence.length : 0;
}
/**
* Returns a new array in which the given *property* has been extracted
* for each element in the input *array*.
* @param {Array} array The input array value.
* @param {string} property The property name string to extract. Nested
* properties are not supported: the input `"a.b"` will indicates a
* property with that exact name, *not* a nested property `"b"` of
* the object `"a"`.
* @return {Array} An array of plucked properties.
*/
function pluck(array, property) {
return isArrayType(array)
? array.map(v => isValid(v) ? v[property] : NULL)
: NULL;
}
/**
* Returns a new array or string with the element order reversed: the first
* *sequence* element becomes the last, and the last *sequence* element
* becomes the first. The input *sequence* is unchanged.
* @template T
* @param {T[]|string} sequence The input array or string value.
* @return {T[]|string} The reversed sequence.
*/
function reverse(sequence) {
return isArrayType(sequence) ? sequence.slice().reverse()
: isString(sequence) ? sequence.split('').reverse().join('')
: NULL;
}
/**
* Returns a copy of a portion of the input *sequence* (array or string)
* selected from *start* to *end* (*end* not included) where *start* and
* *end* represent the index of items in the sequence.
* @template T
* @param {T[]|string} sequence The input array or string value.
* @param {number} [start=0] The starting integer index to copy from
* (inclusive, default `0`).
* @param {number} [end] The ending integer index to copy from (exclusive,
* default `sequence.length`).
* @return {T[]|string} The sliced sequence.
*/
function slice$2(sequence, start, end) {
return isSeq(sequence)
? sequence.slice(start, end)
: NULL;
}
var array$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
compact: compact,
concat: concat$2,
includes: includes,
indexof: indexof,
join: join$1,
lastindexof: lastindexof,
length: length,
pluck: pluck,
reverse: reverse,
slice: slice$2
});
function pad(value, width, char = '0') {
const s = value + '';
const len = s.length;
return len < width ? Array(width - len + 1).join(char) + s : s;
}
const pad2 = v => (v < 10 ? '0' : '') + v;
const formatYear = year => year < 0 ? '-' + pad(-year, 6)
: year > 9999 ? '+' + pad(year, 6)
: pad(year, 4);
function formatISO(year, month, date, hours, min, sec, ms, utc, short) {
const suffix = utc ? 'Z' : '';
return formatYear(year) + '-' + pad2(month + 1) + '-' + pad2(date) + (
!short || ms ? 'T' + pad2(hours) + ':' + pad2(min) + ':' + pad2(sec) + '.' + pad(ms, 3) + suffix
: sec ? 'T' + pad2(hours) + ':' + pad2(min) + ':' + pad2(sec) + suffix
: min || hours || !utc ? 'T' + pad2(hours) + ':' + pad2(min) + suffix
: ''
);
}
function formatDate(d, short) {
return isNaN(d)
? 'Invalid Date'
: formatISO(
d.getFullYear(),
d.getMonth(),
d.getDate(),
d.getHours(),
d.getMinutes(),
d.getSeconds(),
d.getMilliseconds(),
false, short
);
}
function formatUTCDate(d, short) {
return isNaN(d)
? 'Invalid Date'
: formatISO(
d.getUTCFullYear(),
d.getUTCMonth(),
d.getUTCDate(),
d.getUTCHours(),
d.getUTCMinutes(),
d.getUTCSeconds(),
d.getUTCMilliseconds(),
true, short
);
}
const iso_re = /^([-+]\d{2})?\d{4}(-\d{2}(-\d{2})?)?(T\d{2}:\d{2}(:\d{2}(\.\d{3})?)?(Z|[-+]\d{2}:\d{2})?)?$/;
/**
* @param {string} value
* @returns {boolean}
*/
function isISODateString(value) {
return value.match(iso_re) && !isNaN(Date.parse(value));
}
function parseISODate(value, parse = Date.parse) {
return isISODateString(value) ? parse(value) : value;
}
const msMinute = 6e4;
const msDay = 864e5;
const msWeek = 6048e5;
const t0 = new Date();
const t1 = new Date();
const t = d => (
t0.setTime(typeof d === 'string' ? parseISODate(d) : d),
t0
);
/**
* Returns an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) formatted
* string for the given *date* in local timezone. The resulting string is
* compatible with *parse_date* and JavaScript's built-in *Date.parse*.
* @param {Date | number} date The input Date or timestamp value.
* @param {boolean} [shorten=false] A boolean flag (default `false`)
* indicating if the formatted string should be shortened if possible.
* For example, the local date `2001-01-01` will shorten from
* `"2001-01-01T00:00:00.000"` to `"2001-01-01T00:00"`.
* @return {string} The formatted date string in local time.
*/
function format_date(date, shorten) {
return formatDate(t(date), !shorten);
}
/**
* Returns an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) formatted
* string for the given *date* in Coordinated Universal Time (UTC). The
* resulting string is compatible with *parse_date* and JavaScript's
* built-in *Date.parse*.
* @param {Date | number} date The input Date or timestamp value.
* @param {boolean} [shorten=false] A boolean flag (default `false`)
* indicating if the formatted string should be shortened if possible.
* For example, the the UTC date `2001-01-01` will shorten from
* `"2001-01-01T00:00:00.000Z"` to `"2001-01-01"`
* @return {string} The formatted date string in UTC time.
*/
function format_utcdate(date, shorten){
return formatUTCDate(t(date), !shorten);
}
/**
* Returns the number of milliseconds elapsed since midnight, January 1,
* 1970 Universal Coordinated Time (UTC).
* @return {number} The timestamp for now.
*/
function now() {
return Date.now();
}
/**
* Returns the timestamp for a *date* as the number of milliseconds elapsed
* since January 1, 1970 00:00:00 UTC.
* @param {Date | number} date The input Date value.
* @return {number} The timestamp value.
*/
function timestamp$1(date) {
return +t(date);
}
/**
* Creates and returns a new Date value. If no arguments are provided,
* the current date and time are used.
* @param {number} [year] The year.
* @param {number} [month=0] The (zero-based) month.
* @param {number} [date=1] The date within the month.
* @param {number} [hours=0] The hour within the day.
* @param {number} [minutes=0] The minute within the hour.
* @param {number} [seconds=0] The second within the minute.
* @param {number} [milliseconds=0] The milliseconds within the second.
* @return {Date} The Date value.
*/
function datetime(year, month, date, hours, minutes, seconds, milliseconds) {
return !arguments.length
? new Date(Date.now())
: new Date(
year,
month || 0,
date == null ? 1 : date,
hours || 0,
minutes || 0,
seconds || 0,
milliseconds || 0
);
}
/**
* Returns the year of the specified *date* according to local time.
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The year value in local time.
*/
function year(date) {
return t(date).getFullYear();
}
/**
* Returns the zero-based quarter of the specified *date* according to
* local time.
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The quarter value in local time.
*/
function quarter(date) {
return Math.floor(t(date).getMonth() / 3);
}
/**
* Returns the zero-based month of the specified *date* according to local
* time. A value of `0` indicates January, `1` indicates February, and so on.
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The month value in local time.
*/
function month(date) {
return t(date).getMonth();
}
/**
* Returns the week number of the year (0-53) for the specified *date*
* according to local time. By default, Sunday is used as the first day
* of the week. All days in a new year preceding the first Sunday are
* considered to be in week 0.
* @param {Date | number} date The input Date or timestamp value.
* @param {number} firstday The number of first day of the week (default
* `0` for Sunday, `1` for Monday and so on).
* @return {number} The week of the year in local time.
*/
function week(date, firstday) {
const i = firstday || 0;
t1.setTime(+date);
t1.setDate(t1.getDate() - (t1.getDay() + 7 - i) % 7);
t1.setHours(0, 0, 0, 0);
t0.setTime(+date);
t0.setMonth(0);
t0.setDate(1);
t0.setDate(1 - (t0.getDay() + 7 - i) % 7);
t0.setHours(0, 0, 0, 0);
const tz = (t1.getTimezoneOffset() - t0.getTimezoneOffset()) * msMinute;
return Math.floor((1 + (+t1 - +t0) - tz) / msWeek);
}
/**
* Returns the date (day of month) of the specified *date* according
* to local time.
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The date (day of month) value.
*/
function date$1(date) {
return t(date).getDate();
}
/**
* Returns the day of the year (1-366) of the specified *date* according
* to local time.
* @param {Date | number} date A date or timestamp.
* @return {number} The day of the year in local time.
*/
function dayofyear(date) {
t1.setTime(+date);
t1.setHours(0, 0, 0, 0);
t0.setTime(+t1);
t0.setMonth(0);
t0.setDate(1);
const tz = (t1.getTimezoneOffset() - t0.getTimezoneOffset()) * msMinute;
return Math.floor(1 + ((+t1 - +t0) - tz) / msDay);
}
/**
* Returns the Sunday-based day of the week (0-6) of the specified *date*
* according to local time. A value of `0` indicates Sunday, `1` indicates
* Monday, and so on.
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The day of the week value in local time.
*/
function dayofweek(date) {
return t(date).getDay();
}
/**
* Returns the hour of the day for the specified *date* according
* to local time.
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The hour value in local time.
*/
function hours(date) {
return t(date).getHours();
}
/**
* Returns the minute of the hour for the specified *date* according
* to local time.
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The minutes value in local time.
*/
function minutes(date) {
return t(date).getMinutes();
}
/**
* Returns the seconds of the minute for the specified *date* according
* to local time.
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The seconds value in local time.
*/
function seconds(date) {
return t(date).getSeconds();
}
/**
* Returns the milliseconds of the second for the specified *date* according
* to local time.
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The milliseconds value in local time.
*/
function milliseconds(date) {
return t(date).getMilliseconds();
}
/**
* Creates and returns a new Date value using Coordinated Universal Time
* (UTC). If no arguments are provided, the current date and time are used.
* @param {number} [year] The year.
* @param {number} [month=0] The (zero-based) month.
* @param {number} [date=1] The date within the month.
* @param {number} [hours=0] The hour within the day.
* @param {number} [minutes=0] The minute within the hour.
* @param {number} [seconds=0] The second within the minute.
* @param {number} [milliseconds=0] The milliseconds within the second.
* @return {Date} The Date value.
*/
function utcdatetime(year, month, date, hours, minutes, seconds, milliseconds) {
return !arguments.length
? new Date(Date.now())
: new Date(Date.UTC(
year,
month || 0,
date == null ? 1 : date,
hours || 0,
minutes || 0,
seconds || 0,
milliseconds || 0
));
}
/**
* Returns the year of the specified *date* according to Coordinated
* Universal Time (UTC).
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The year value in UTC time.
*/
function utcyear(date) {
return t(date).getUTCFullYear();
}
/**
* Returns the zero-based quarter of the specified *date* according to
* Coordinated Universal Time (UTC)
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The quarter value in UTC time.
*/
function utcquarter(date) {
return Math.floor(t(date).getUTCMonth() / 3);
}
/**
* Returns the zero-based month of the specified *date* according to
* Coordinated Universal Time (UTC). A value of `0` indicates January,
* `1` indicates February, and so on.
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The month value in UTC time.
*/
function utcmonth(date) {
return t(date).getUTCMonth();
}
/**
* Returns the week number of the year (0-53) for the specified *date*
* according to Coordinated Universal Time (UTC). By default, Sunday is
* used as the first day of the week. All days in a new year preceding the
* first Sunday are considered to be in week 0.
* @param {Date | number} date The input Date or timestamp value.
* @param {number} firstday The number of first day of the week (default
* `0` for Sunday, `1` for Monday and so on).
* @return {number} The week of the year in UTC time.
*/
function utcweek(date, firstday) {
const i = firstday || 0;
t1.setTime(+date);
t1.setUTCDate(t1.getUTCDate() - (t1.getUTCDay() + 7 - i) % 7);
t1.setUTCHours(0, 0, 0, 0);
t0.setTime(+date);
t0.setUTCMonth(0);
t0.setUTCDate(1);
t0.setUTCDate(1 - (t0.getUTCDay() + 7 - i) % 7);
t0.setUTCHours(0, 0, 0, 0);
return Math.floor((1 + (+t1 - +t0)) / msWeek);
}
/**
* Returns the date (day of month) of the specified *date* according to
* Coordinated Universal Time (UTC).
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The date (day of month) value in UTC time.
*/
function utcdate(date) {
return t(date).getUTCDate();
}
/**
* Returns the day of the year (1-366) of the specified *date* according
* to Coordinated Universal Time (UTC).
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The day of the year in UTC time.
*/
function utcdayofyear(date) {
t1.setTime(+date);
t1.setUTCHours(0, 0, 0, 0);
const t0 = Date.UTC(t1.getUTCFullYear(), 0, 1);
return Math.floor(1 + (+t1 - t0) / msDay);
}
/**
* Returns the Sunday-based day of the week (0-6) of the specified *date*
* according to Coordinated Universal Time (UTC). A value of `0` indicates
* Sunday, `1` indicates Monday, and so on.
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The day of the week in UTC time.
*/
function utcdayofweek(date) {
return t(date).getUTCDay();
}
/**
* Returns the hour of the day for the specified *date* according to
* Coordinated Universal Time (UTC).
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The hours value in UTC time.
*/
function utchours(date) {
return t(date).getUTCHours();
}
/**
* Returns the minute of the hour for the specified *date* according to
* Coordinated Universal Time (UTC).
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The minutes value in UTC time.
*/
function utcminutes(date) {
return t(date).getUTCMinutes();
}
/**
* Returns the seconds of the minute for the specified *date* according to
* Coordinated Universal Time (UTC).
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The seconds value in UTC time.
*/
function utcseconds(date) {
return t(date).getUTCSeconds();
}
/**
* Returns the milliseconds of the second for the specified *date* according to
* Coordinated Universal Time (UTC).
* @param {Date | number} date The input Date or timestamp value.
* @return {number} The milliseconds value in UTC time.
*/
function utcmilliseconds(date) {
return t(date).getUTCMilliseconds();
}
var date$2 = /*#__PURE__*/Object.freeze({
__proto__: null,
date: date$1,
datetime: datetime,
dayofweek: dayofweek,
dayofyear: dayofyear,
format_date: format_date,
format_utcdate: format_utcdate,
hours: hours,
milliseconds: milliseconds,
minutes: minutes,
month: month,
now: now,
quarter: quarter,
seconds: seconds,
timestamp: timestamp$1,
utcdate: utcdate,
utcdatetime: utcdatetime,
utcdayofweek: utcdayofweek,
utcdayofyear: utcdayofyear,
utchours: utchours,
utcmilliseconds: utcmilliseconds,
utcminutes: utcminutes,
utcmonth: utcmonth,
utcquarter: utcquarter,
utcseconds: utcseconds,
utcweek: utcweek,
utcyear: utcyear,
week: week,
year: year
});
/**
* Parses a string *value* in JSON format, constructing the JavaScript
* value or object described by the string.
* @param {string} value The input string value.
* @return {any} The parsed JSON.
*/
function parse_json(value) {
return JSON.parse(value);
}
/**
* Converts a JavaScript object or value to a JSON string.
* @param {*} value The value to convert to a JSON string.
* @return {string} The JSON string.
*/
function to_json(value) {
return JSON.stringify(value);
}
var json = /*#__PURE__*/Object.freeze({
__proto__: null,
parse_json: parse_json,
to_json: to_json
});
let source = Math.random;
function random$1() {
return source();
}
/**
* Set a seed value for random number generation.
* If the seed is a valid number, a 32-bit linear congruential generator
* with the given seed will be used to generate random values.
* If the seed is null, undefined, or not a valid number, the random
* number generator will revert to Math.random.
* @param {number} seed The random seed value. Should either be an
* integer or a fraction between 0 and 1.
*/
function seed(seed) {
source = isValid(seed) && isFinite(seed = +seed) ? lcg(seed) : Math.random;
}
function lcg(seed) {
const a = 0x19660D;
const c = 0x3C6EF35F;
const m = 1 / 0x100000000;
seed = (0 <= seed && seed < 1 ? seed / m : Math.abs(seed)) | 0;
// Random numbers using a Linear Congruential Generator with seed value
// https://en.wikipedia.org/wiki/Linear_congruential_generator
return () => (seed = a * seed + c | 0, m * (seed >>> 0));
}
/**
* Return a random floating point number between 0 (inclusive) and 1
* (exclusive). By default uses *Math.random*. Use the *seed* method
* to instead use a seeded random number generator.
* @return {number} A pseudorandom number between 0 and 1.
*/
function random() {
return random$1();
}
/**
* Tests if the input *value* is not a number (`NaN`); equivalent
* to *Number.isNaN*.
* @param {*} value The value to test.
* @return {boolean} True if the value is not a number, false otherwise.
*/
function is_nan(value) {
return Number.isNaN(value);
}
/**
* Tests if the input *value* is finite; equivalent to *Number.isFinite*.
* @param {*} value The value to test.
* @return {boolean} True if the value is finite, false otherwise.
*/
function is_finite(value) {
return Number.isFinite(value);
}
/**
* Returns the absolute value of the input *value*; equivalent to *Math.abs*.
* @param {number} value The input number value.
* @return {number} The absolute value.
*/
function abs(value) {
return Math.abs(value);
}
/**
* Returns the cube root value of the input *value*; equivalent to
* *Math.cbrt*.
* @param {number} value The input number value.
* @return {number} The cube root value.
*/
function cbrt(value) {
return Math.cbrt(value);
}
/**
* Returns the ceiling of the input *value*, the nearest integer equal to
* or greater than the input; equivalent to *Math.ceil*.
* @param {number} value The input number value.
* @return {number} The ceiling value.
*/
function ceil(value) {
return Math.ceil(value);
}
/**
* Returns the number of leading zero bits in the 32-bit binary
* representation of a number *value*; equivalent to *Math.clz32*.
* @param {number} value The input number value.
* @return {number} The leading zero bits value.
*/
function clz32(value) {
return Math.clz32(value);
}
/**
* Returns *e<sup>value</sup>*, where *e* is Euler's number, the base of the
* natural logarithm; equivalent to *Math.exp*.
* @param {number} value The input number value.
* @return {number} The base-e exponentiated value.
*/
function exp(value) {
return Math.exp(value);
}
/**
* Returns *e<sup>value</sup> - 1*, where *e* is Euler's number, the base of
* the natural logarithm; equivalent to *Math.expm1*.
* @param {number} value The input number value.
* @return {number} The base-e exponentiated value minus 1.
*/
function expm1(value) {
return Math.expm1(value);
}
/**
* Returns the floor of the input *value*, the nearest integer equal to or
* less than the input; equivalent to *Math.floor*.
* @param {number} value The input number value.
* @return {number} The floor value.
*/
function floor(value) {
return Math.floor(value);
}
/**
* Returns the nearest 32-bit single precision float representation of the
* input number *value*; equivalent to *Math.fround*. Useful for translating
* between 64-bit `Number` values and values from a `Float32Array`.
* @param {number} value The input number value.
* @return {number} The rounded value.
*/
function fround(value) {
return Math.fround(value);
}
/**
* Returns the greatest (maximum) value among the input *values*; equivalent
* to *Math.max*. This is _not_ an aggregate function, see *op.max* to
* compute a maximum value across multiple rows.
* @param {...number} values The input number values.
* @return {number} The greatest (maximum) value among the inputs.
*/
function greatest(...values) {
return Math.max(...values);
}
/**
* Returns the least (minimum) value among the input *values*; equivalent
* to *Math.min*. This is _not_ an aggregate function, see *op.min* to
* compute a minimum value across multiple rows.
* @param {...number} values The input number values.
* @return {number} The least (minimum) value among the inputs.
*/
function least(...values) {
return Math.min(...values);
}
/**
* Returns the natural logarithm (base *e*) of a number *value*; equivalent
* to *Math.log*.
* @param {number} value The input number value.
* @return {number} The base-e log value.
*/
function log(value) {
return Math.log(value);
}
/**
* Returns the base 10 logarithm of a number *value*; equivalent
* to *Math.log10*.
* @param {number} value The input number value.
* @return {number} The base-10 log value.
*/
function log10(value) {
return Math.log10(value);
}
/**
* Returns the natural logarithm (base *e*) of 1 + a number *value*;
* equivalent to *Math.log1p*.
* @param {number} value The input number value.
* @return {number} The base-e log of value + 1.
*/
function log1p(value) {
return Math.log1p(value);
}
/**
* Returns the base 2 logarithm of a number *value*; equivalent
* to *Math.log2*.
* @param {number} value The input number value.
* @return {number} The base-2 log value.
*/
function log2(value) {
return Math.log2(value);
}
/**
* Returns the *base* raised to the *exponent* power, that is,
* *base*<sup>*exponent*</sup>; equivalent to *Math.pow*.
* @param {number} base The base number value.
* @param {number} exponent The exponent number value.
* @return {number} The exponentiated value.
*/
function pow(base, exponent) {
return Math.pow(base, exponent);
}
/**
* Returns the value of a number rounded to the nearest integer;
* equivalent to *Math.round*.
* @param {number} value The input number value.
* @return {number} The rounded value.
*/
function round(value) {
return Math.round(value);
}
/**
* Returns either a positive or negative +/- 1, indicating the sign of the
* input *value*; equivalent to *Math.sign*.
* @param {number} value The input number value.
* @return {number} The sign of the value.
*/
function sign(value) {
return Math.sign(value);
}
/**
* Returns the square root of the input *value*; equivalent to *Math.sqrt*.
* @param {number} value The input number value.
* @return {number} The square root value.
*/
function sqrt(value) {
return Math.sqrt(value);
}
/**
* Returns the integer part of a number by removing any fractional digits;
* equivalent to *Math.trunc*.
* @param {number} value The input number value.
* @return {number} The truncated value.
*/
function trunc(value) {
return Math.trunc(value);
}
/**
* Converts the input *radians* value to degrees.
* @param {number} radians The input radians value.
* @return {number} The value in degrees
*/
function degrees(radians) {
return 180 * radians / Math.PI;
}
/**
* Converts the input *degrees* value to radians.
* @param {number} degrees The input degrees value.
* @return {number} The value in radians.
*/
function radians(degrees) {
return Math.PI * degrees / 180;
}
/**
* Returns the arc-cosine (in radians) of a number *value*;
* equivalent to *Math.acos*.
* @param {number} value The input number value.
* @return {number} The arc-cosine value.
*/
function acos(value) {
return Math.acos(value);
}
/**
* Returns the hyperbolic arc-cosine of a number *value*;
* equivalent to *Math.acosh*.
* @param {number} value The input number value.
* @return {number} The hyperbolic arc-cosine value.
*/
function acosh(value) {
return Math.acosh(value);
}
/**
* Returns the arc-sine (in radians) of a number *value*;
* equivalent to *Math.asin*.
* @param {number} value The input number value.
* @return {number} The arc-sine value.
*/
function asin(value) {
return Math.asin(value);
}
/**
* Returns the hyperbolic arc-sine of a number *value*;
* equivalent to *Math.asinh*.
* @param {number} value The input number value.
* @return {number} The hyperbolic arc-sine value.
*/
function asinh(value) {
return Math.asinh(value);
}
/**
* Returns the arc-tangent (in radians) of a number *value*;
* equivalent to *Math.atan*.
* @param {number} value The input number value.
* @return {number} The arc-tangent value.
*/
function atan(value) {
return Math.atan(value);
}
/**
* Returns the angle in the plane (in radians) between the positive x-axis
* and the ray from (0, 0) to the point (*x*, *y*);
* equivalent to *Math.atan2*.
* @param {number} y The y coordinate of the point.
* @param {number} x The x coordinate of the point.
* @return {number} The arc-tangent angle.
*/
function atan2(y, x) {
return Math.atan2(y, x);
}
/**
* Returns the hyperbolic arc-tangent of a number *value*;
* equivalent to *Math.atanh*.
* @param {number} value The input number value.
* @return {number} The hyperbolic arc-tangent value.
*/
function atanh(value) {
return Math.atanh(value);
}
/**
* Returns the cosine (in radians) of a number *value*;
* equivalent to *Math.cos*.
* @param {number} value The input number value.
* @return {number} The cosine value.
*/
function cos(value) {
return Math.cos(value);
}
/**
* Returns the hyperbolic cosine (in radians) of a number *value*;
* equivalent to *Math.cosh*.
* @param {number} value The input number value.
* @return {number} The hyperbolic cosine value.
*/
function cosh(value) {
return Math.cosh(value);
}
/**
* Returns the sine (in radians) of a number *value*;
* equivalent to *Math.sin*.
* @param {number} value The input number value.
* @return {number} The sine value.
*/
function sin(value) {
return Math.sin(value);
}
/**
* Returns the hyperbolic sine (in radians) of a number *value*;
* equivalent to *Math.sinh*.
* @param {number} value The input number value.
* @return {number} The hyperbolic sine value.
*/
function sinh(value) {
return Math.sinh(value);
}
/**
* Returns the tangent (in radians) of a number *value*;
* equivalent to *Math.tan*.
* @param {number} value The input number value.
* @return {number} The tangent value.
*/
function tan(value) {
return Math.tan(value);
}
/**
* Returns the hyperbolic tangent (in radians) of a number *value*;
* equivalent to *Math.tanh*.
* @param {number} value The input number value.
* @return {number} The hyperbolic tangent value.
*/
function tanh(value) {
return Math.tanh(value);
}
var math = /*#__PURE__*/Object.freeze({
__proto__: null,
abs: abs,
acos: acos,
acosh: acosh,
asin: asin,
asinh: asinh,
atan: atan,
atan2: atan2,
atanh: atanh,
cbrt: cbrt,
ceil: ceil,
clz32: clz32,
cos: cos,
cosh: cosh,
degrees: degrees,
exp: exp,
expm1: expm1,
floor: floor,
fround: fround,
greatest: greatest,
is_finite: is_finite,
is_nan: is_nan,
least: least,
log: log,
log10: log10,
log1p: log1p,
log2: log2,
pow: pow,
radians: radians,
random: random,
round: round,
sign: sign,
sin: sin,
sinh: sinh,
sqrt: sqrt,
tan: tan,
tanh: tanh,
trunc: trunc
});
/**
* @param {*} value
* @return {value is Map}
*/
function isMap(value) {
return value instanceof Map;
}
/**
* @param {*} value
* @return {value is Set}
*/
function isSet(value) {
return value instanceof Set;
}
/**
* @param {*} value
* @return {value is Map | Set}
*/
function isMapOrSet(value) {
return isMap(value) || isSet(value);
}
function array(iter) {
return Array.from(iter);
}
/**
* Returns a boolean indicating whether the *object* has the specified *key*
* as its own property (as opposed to inheriting it). If the *object* is a
* *Map* or *Set* instance, the *has* method will be invoked directly on the
* object, otherwise *Object.hasOwnProperty* is used.
* @template {string | number} K
* @template V
* @param {Map<K, V>|Set<K>|Record<K, V>} object The object, Map, or Set to
* test for property membership.
* @param {K} key The property key to test for.
* @return {boolean} True if the object has the given key, false otherwise.
*/
function has(object, key) {
return isMapOrSet(object) ? object.has(key)
: object != null ? Object.hasOwn(object, `${key}`)
: false;
}
/**
* Returns an array of a given *object*'s own enumerable property names. If
* the *object* is a *Map* instance, the *keys* method will be invoked
* directly on the object, otherwise *Object.keys* is used.
* @template {string | number} K
* @template V
* @param {Map<K, V>|Record<K, V>} object The input object or Map value.
* @return {K[]} An array of property key name strings.
*/
function keys(object) {
return isMap(object) ? array(object.keys())
: object != null ? /** @type {K[]} */(Object.keys(object))
: [];
}
/**
* Returns an array of a given *object*'s own enumerable property values. If
* the *object* is a *Map* or *Set* instance, the *values* method will be
* invoked directly on the object, otherwise *Object.values* is used.
* @template {string | number} K
* @template V
* @param {Map<K, V> | Set<V> | Record<K, V>} object The input object, Map,
* or Set value.
* @return {V[]} An array of property values.
*/
function values$1(object) {
return isMapOrSet(object) ? array(object.values())
: object != null ? Object.values(object)
: [];
}
/**
* Returns an array of a given *object*'s own enumerable keyed property
* `[key, value]` pairs. If the *object* is a *Map* or *Set* instance, the
* *entries* method will be invoked directly on the object, otherwise
* *Object.entries* is used.
* @template {string | number} K
* @template V
* @param {Map<K, V> | Set<V> | Record<K, V>} object The input object, Map,
* or Set value.
* @return {[K, V][]} An array of property values.
*/
function entries$1(object) {
return isMapOrSet(object) ? array(object.entries())
: object != null ? /** @type {[K, V][]} */(Object.entries(object))
: [];
}
/**
* Returns a new object given iterable *entries* of `[key, value]` pairs.
* This method is Arquero's version of the *Object.fromEntries* method.
* @template {string | number} K
* @template V
* @param {Iterable<[K, V]>} entries An iterable collection of `[key, value]`
* pairs, such as an array of two-element arrays or a *Map*.
* @return {Record<K, V>} An object of consolidated key-value pairs.
*/
function object(entries) {
return entries
? /** @type {Record<K, V>} */(Object.fromEntries(entries))
: NULL;
}
var object$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
entries: entries$1,
has: has,
keys: keys,
object: object,
values: values$1
});
/**
* Parses a string *value* and returns a Date instance. Beware: this method
* uses JavaScript's *Date.parse()* functionality, which is inconsistently
* implemented across browsers. That said,
* [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) formatted strings such
* as those produced by *op.format_date* and *op.format_utcdate* should be
* supported across platforms. Note that "bare" ISO date strings such as
* `"2001-01-01"` are interpreted by JavaScript as indicating midnight of
* that day in Coordinated Universal Time (UTC), *not* local time. To
* indicate the local timezone, an ISO string can include additional time
* components and no `Z` suffix: `"2001-01-01T00:00"`.
* @param {*} value The input value.
* @return {Date} The parsed date value.
*/
function parse_date(value) {
return value == null ? value : new Date(value);
}
/**
* Parses a string *value* and returns a floating point number.
* @param {*} value The input value.
* @return {number} The parsed number value.
*/
function parse_float(value) {
return value == null ? value : Number.parseFloat(value);
}
/**
* Parses a string *value* and returns an integer of the specified radix
* (the base in mathematical numeral systems).
* @param {*} value The input value.
* @param {number} [radix] An integer between 2 and 36 that represents the
* radix (the base in mathematical numeral systems) of the string. Be
* careful: this does not default to 10! If *radix* is `undefined`, `0`,
* or unspecified, JavaScript assumes the following: If the input string
* begins with `"0x"` or `"0X"` (a zero, followed by lowercase or
* uppercase X), the radix is assumed to be 16 and the rest of the string
* is parsed as a hexidecimal number. If the input string begins with `"0"`
* (a zero), the radix is assumed to be 8 (octal) or 10 (decimal). Exactly
* which radix is chosen is implementation-dependent. If the input string
* begins with any other value, the radix is 10 (decimal).
* @return {number} The parsed integer value.
*/
function parse_int(value, radix) {
return value == null ? value : Number.parseInt(value, radix);
}
/**
* Determines whether a string *value* ends with the characters of a
* specified *search* string, returning `true` or `false` as appropriate.
* @param {any} value The input string value.
* @param {string} search The search string to test for.
* @param {number} [length] If provided, used as the length of *value*
* (default `value.length`).
* @return {boolean} True if the value ends with the search string,
* false otherwise.
*/
function endswith$1(value, search, length) {
return value == null ? false : String(value).endsWith(search, length);
}
/**
* Retrieves the result of matching a string *value* against a regular
* expression *regexp*. If no *index* is specified, returns an array
* whose contents depend on the presence or absence of the regular
* expression global (`g`) flag, or `null` if no matches are found. If the
* `g` flag is used, all results m