UNPKG

sketches-js-hassy

Version:

TypeScript implementation of DDSketch, a distributed quantile sketch algorithm

96 lines (95 loc) 4.5 kB
"use strict"; /* * Unless explicitly stated otherwise all files in this repository are licensed * under the Apache 2.0 license (see LICENSE). * This product includes software developed at Datadog (https://www.datadoghq.com/). * Copyright 2020 Datadog, Inc. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.KeyMapping = void 0; var index_1 = require("./index"); var compiled_1 = require("../proto/compiled"); // 1.1125369292536007e-308 var MIN_SAFE_FLOAT = Math.pow(2, -1023); var MAX_SAFE_FLOAT = Number.MAX_VALUE; /** * A mapping between values and integer indices that imposes relative accuracy * guarantees. Specifically, for any value `minPossible() < value < * maxPossible` implementations of `KeyMapping` must be such that * `value(key(v))` is close to `v` with a relative error that is less than * `relativeAccuracy`. * * In implementations of KeyMapping, there is generally a trade-off between the * cost of computing the key and the number of keys that are required to cover a * given range of values (memory optimality). The most memory-optimal mapping is * the LogarithmicMapping, but it requires the costly evaluation of the logarithm * when computing the index. Other mappings can approximate the logarithmic * mapping, while being less computationally costly. */ var KeyMapping = /** @class */ (function () { function KeyMapping(relativeAccuracy, offset) { if (offset === void 0) { offset = 0; } if (relativeAccuracy <= 0 || relativeAccuracy >= 1) { throw Error('Relative accuracy must be between 0 and 1 when initializing a KeyMapping'); } this.relativeAccuracy = relativeAccuracy; this._offset = offset; var gammaMantissa = (2 * relativeAccuracy) / (1 - relativeAccuracy); this.gamma = 1 + gammaMantissa; this._multiplier = 1 / Math.log1p(gammaMantissa); this.minPossible = MIN_SAFE_FLOAT * this.gamma; this.maxPossible = MAX_SAFE_FLOAT / this.gamma; } KeyMapping.fromGammaOffset = function (gamma, indexOffset) { var relativeAccuracy = (gamma - 1) / (gamma + 1); return new this(relativeAccuracy, indexOffset); }; /** Retrieve the key specifying the bucket for a `value` */ KeyMapping.prototype.key = function (value) { return Math.ceil(this._logGamma(value)) + this._offset; }; /** Retrieve the value represented by the bucket at `key` */ KeyMapping.prototype.value = function (key) { return this._powGamma(key - this._offset) * (2 / (1 + this.gamma)); }; KeyMapping.prototype.toProto = function () { return compiled_1.IndexMapping.create({ gamma: this.gamma, indexOffset: this._offset, interpolation: this._protoInterpolation() }); }; KeyMapping.fromProto = function (protoMapping) { if (!protoMapping || /* Double equals (==) is intentional here to check for * `null` | `undefined` without including `0` */ protoMapping.gamma == null || protoMapping.indexOffset == null) { throw Error('Failed to decode mapping from protobuf'); } var interpolation = protoMapping.interpolation, gamma = protoMapping.gamma, indexOffset = protoMapping.indexOffset; switch (interpolation) { case compiled_1.IndexMapping.Interpolation.NONE: return index_1.LogarithmicMapping.fromGammaOffset(gamma, indexOffset); case compiled_1.IndexMapping.Interpolation.LINEAR: return index_1.LinearlyInterpolatedMapping.fromGammaOffset(gamma, indexOffset); case compiled_1.IndexMapping.Interpolation.CUBIC: return index_1.CubicallyInterpolatedMapping.fromGammaOffset(gamma, indexOffset); default: throw Error('Unrecognized mapping when decoding from protobuf'); } }; /** Return (an approximation of) the logarithm of the value base gamma */ KeyMapping.prototype._logGamma = function (value) { return Math.log2(value) * this._multiplier; }; /** Return (an approximation of) gamma to the power value */ KeyMapping.prototype._powGamma = function (value) { return Math.pow(2, value / this._multiplier); }; KeyMapping.prototype._protoInterpolation = function () { return compiled_1.IndexMapping.Interpolation.NONE; }; return KeyMapping; }()); exports.KeyMapping = KeyMapping;