Skip to content

Commit

Permalink
Refactor the mapping to be the same as reference implementation, remo…
Browse files Browse the repository at this point in the history
…ve unused implementations
  • Loading branch information
Sytten committed Feb 12, 2021
1 parent b06df3c commit 415a046
Show file tree
Hide file tree
Showing 14 changed files with 110 additions and 898 deletions.
4 changes: 0 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@
"prepack": "yarn build",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"math-float64-frexp": "^1.0.0",
"math-float64-ldexp": "^1.0.1"
},
"devDependencies": {
"@types/jest": "^26.0.14",
"@typescript-eslint/eslint-plugin": "^4.2.0",
Expand Down
14 changes: 7 additions & 7 deletions src/ddsketch/DDSketch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
*/

import { Bin, DenseStore } from './store';
import { Mapping, LogarithmicMapping } from './mapping';
import { IndexMapping, LogarithmicMapping } from './mapping';

const DEFAULT_RELATIVE_ACCURACY = 0.01;

interface BaseSketchConfig {
/** The mapping between values and indicies for the sketch */
mapping: Mapping;
mapping: IndexMapping;
/** Storage for values */
store: DenseStore;
}

/** Base class for DDSketch*/
class BaseDDSketch {
/** The mapping between values and indicies for the sketch */
mapping: Mapping;
mapping: IndexMapping;
/** Storage for values */
store: DenseStore;
/** The minimum value seen by the sketch */
Expand Down Expand Up @@ -52,8 +52,8 @@ class BaseDDSketch {
*/
accept(value: number, weight = 1): void {
if (
value < this.mapping.minPossible ||
value > this.mapping.maxPossible
value < this.mapping.minIndexableValue ||
value > this.mapping.maxIndexableValue
) {
throw new Error(
'Input value is outside the range that is tracked by the sketch'
Expand All @@ -64,7 +64,7 @@ class BaseDDSketch {
throw new Error('Weight must be a positive number');
}

const key = this.mapping.key(value);
const key = this.mapping.index(value);
this.store.add(key, weight);

/* Keep track of summary stats */
Expand Down Expand Up @@ -136,7 +136,7 @@ class BaseDDSketch {
* @param sketch The sketch to be merged into the caller sketch
*/
mergeable(sketch: DDSketch): boolean {
return this.mapping.gamma === sketch.mapping.gamma;
return this.mapping.equals(sketch.mapping);
}

/*
Expand Down
86 changes: 0 additions & 86 deletions src/ddsketch/mapping/CubicallyInterpolatedMapping.ts

This file was deleted.

82 changes: 0 additions & 82 deletions src/ddsketch/mapping/KeyMapping.ts

This file was deleted.

69 changes: 0 additions & 69 deletions src/ddsketch/mapping/LinearlyInterpolatedMapping.ts

This file was deleted.

55 changes: 40 additions & 15 deletions src/ddsketch/mapping/LogarithmicMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,57 @@
* Copyright 2021 GraphMetrics for modifications
*/

import { KeyMapping, MIN_INT_16, MAX_INT_16 } from './KeyMapping';
import {
EXP_OVERFLOW,
MAX_INT_16,
MIN_INT_16,
MIN_SAFE_FLOAT,
withinTolerance
} from './helpers';
import { IndexMapping } from './types';

/**
* A memory-optimal KeyMapping, i.e., given a targeted relative accuracy, it
* requires the least number of keys to cover a given range of values. This is
* done by logarithmically mapping floating-point values to integers.
*/
export class LogarithmicMapping extends KeyMapping {
constructor(relativeAccuracy: number, offset = 0) {
super(relativeAccuracy, offset);
this._multiplier *= Math.log(2);
this.minPossible = Math.max(
Math.pow(2, (MIN_INT_16 - this._offset) / this._multiplier + 1),
this.minPossible
export class LogarithmicMapping implements IndexMapping {
public readonly relativeAccuracy: number;
public readonly minIndexableValue: number;
public readonly maxIndexableValue: number;
private readonly multiplier: number;

constructor(relativeAccuracy: number) {
this.relativeAccuracy = relativeAccuracy;
this.multiplier =
1 / Math.log1p((2 * relativeAccuracy) / (1 - relativeAccuracy));
this.minIndexableValue = Math.max(
Math.exp(MIN_INT_16 / this.multiplier + 1),
(MIN_SAFE_FLOAT * (1 + relativeAccuracy)) / (1 - relativeAccuracy)
);
this.maxPossible = Math.min(
Math.pow(2, (MAX_INT_16 - this._offset) / this._multiplier - 1),
this.maxPossible
this.maxIndexableValue = Math.min(
Math.exp(MAX_INT_16 / this.multiplier - 1),
Math.exp(EXP_OVERFLOW) / (1 + relativeAccuracy)
);
}

_logGamma(value: number): number {
return Math.log2(value) * this._multiplier;
public index(value: number): number {
const index = Math.log(value) * this.multiplier;
if (index >= 0) {
return ~~index;
} else {
return ~~index - 1; // faster than Math.Floor
}
}

public value(index: number): number {
return Math.exp(index / this.multiplier) * (1 + this.relativeAccuracy);
}

_powGamma(value: number): number {
return Math.pow(2, value / this._multiplier);
public equals(other: IndexMapping): boolean {
if (!(other instanceof LogarithmicMapping)) {
return false;
}
return withinTolerance(this.multiplier, other.multiplier, 1e-12);
}
}
Loading

0 comments on commit 415a046

Please sign in to comment.