Skip to content

Commit 02073c9

Browse files
authored
remove the libraries for frexp and ldexp and inline the functions (#16)
1 parent 8a053bb commit 02073c9

17 files changed

+165
-738
lines changed

LICENSE-3rdparty.csv

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ dev,jest,MIT,Facebook
88
dev,prettier,MIT,James Long
99
dev,ts-jest,MIT,Kulshekhar Kabra
1010
dev,typescript,Apache-2.0,Copyright Microsoft Corporation
11-
import,@stdlib/math-base-special-frexp,Apache-2.0,Copyright 2016-2021 The Stdlib Authors
12-
import,@stdlib/math-base-special-ldexp,Apache-2.0,Copyright 2016-2021 The Stdlib Authors
11+
float64-frexp,https://github.com/math-io/float64-frexp,MIT,The Compute.io Authors
12+
float64-ldexp,https://github.com/math-io/float64-ldexp,MIT,The Compute.io Authors
1313
import,protobufjs,BSD-3-Clause,Daniel Wirtz

package.json

-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@
3232
"generate:proto": "pbjs -t static-module -w commonjs -o src/ddsketch/proto/compiled.js src/ddsketch/proto/DDSketch.proto && pbts -o src/ddsketch/proto/compiled.d.ts src/ddsketch/proto/compiled.js"
3333
},
3434
"dependencies": {
35-
"@stdlib/math-base-special-frexp": "^0.0.4",
36-
"@stdlib/math-base-special-ldexp": "^0.0.4",
3735
"protobufjs": "^6.10.2"
3836
},
3937
"devDependencies": {

src/ddsketch/mapping/CubicallyInterpolatedMapping.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
*/
77

88
import { KeyMapping } from './KeyMapping';
9-
import frexp from '@stdlib/math-base-special-frexp';
10-
import ldexp from '@stdlib/math-base-special-ldexp';
9+
import { frexp, ldexp } from '../math';
1110
import { IndexMapping as IndexMappingProto } from '../proto/compiled';
1211

1312
/**

src/ddsketch/mapping/LinearlyInterpolatedMapping.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
*/
77

88
import { KeyMapping } from './KeyMapping';
9-
import frexp from '@stdlib/math-base-special-frexp';
10-
import ldexp from '@stdlib/math-base-special-ldexp';
9+
import { frexp, ldexp } from '../math';
1110
import { IndexMapping as IndexMappingProto } from '../proto/compiled';
1211

1312
/**

src/ddsketch/math.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed
3+
* under the Apache 2.0 license (see LICENSE).
4+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
5+
* Copyright 2020 Datadog, Inc.
6+
*/
7+
8+
/**
9+
* Splits a double-precision floating-point number into a normalized fraction
10+
* and an integer power of two.
11+
*/
12+
export function frexp(value: number): [number, number] {
13+
if (value === 0 || !Number.isFinite(value)) return [value, 0];
14+
15+
const absValue = Math.abs(value);
16+
17+
let exponent = Math.max(-1023, Math.floor(Math.log2(absValue)) + 1);
18+
let mantissa = absValue * Math.pow(2, -exponent);
19+
20+
while (mantissa < 0.5) {
21+
mantissa *= 2;
22+
exponent--;
23+
}
24+
25+
while (mantissa >= 1) {
26+
mantissa *= 0.5;
27+
exponent++;
28+
}
29+
30+
if (value < 0) {
31+
mantissa = -mantissa;
32+
}
33+
34+
return [mantissa, exponent];
35+
}
36+
37+
/**
38+
* Multiplies a double-precision floating-point number by an integer power of
39+
* two; i.e., x = frac * 2^exp.
40+
*/
41+
export function ldexp(mantissa: number, exponent: number): number {
42+
const iterations = Math.min(3, Math.ceil(Math.abs(exponent) / 1023));
43+
44+
let result = mantissa;
45+
46+
for (let i = 0; i < iterations; i++) {
47+
result *= Math.pow(2, Math.floor((exponent + i) / iterations));
48+
}
49+
50+
return result;
51+
}

src/types/math-float64-frexp/index.d.ts

-12
This file was deleted.

src/types/math-float64-ldexp/index.d.ts

-12
This file was deleted.

test/fixtures/math/frexp/x_-1e3_1e3.json

+1
Large diffs are not rendered by default.

test/fixtures/math/frexp/x_1e-200_1e-308.json

+1
Large diffs are not rendered by default.

test/fixtures/math/frexp/x_1e-310_5e-324.json

+1
Large diffs are not rendered by default.

test/fixtures/math/frexp/x_1e200_1e308.json

+1
Large diffs are not rendered by default.

test/fixtures/math/ldexp/large.json

+1
Large diffs are not rendered by default.

test/fixtures/math/ldexp/medium.json

+1
Large diffs are not rendered by default.

test/fixtures/math/ldexp/small.json

+1
Large diffs are not rendered by default.

test/fixtures/math/ldexp/subnormal.json

+1
Large diffs are not rendered by default.

test/math.test.ts

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed
3+
* under the Apache 2.0 license (see LICENSE).
4+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
5+
* Copyright 2020 Datadog, Inc.
6+
*/
7+
8+
import { frexp, ldexp } from '../src/ddsketch/math';
9+
10+
describe('math', () => {
11+
describe('frexp', () => {
12+
const small = require('./fixtures/math/frexp/x_1e-200_1e-308.json');
13+
const medium = require('./fixtures/math/frexp/x_-1e3_1e3.json');
14+
const large = require('./fixtures/math/frexp/x_1e200_1e308.json');
15+
const subnormal = require('./fixtures/math/frexp/x_1e-310_5e-324.json');
16+
17+
it('should split a floating-point number into a normalized fraction and an integer power of two (small `x`)', () => {
18+
const expected = small.expected;
19+
const x = small.x;
20+
21+
for (let i = 0; i < x.length; i++ ) {
22+
expect(frexp(x[i])).toEqual(expected[i]);
23+
}
24+
});
25+
26+
it('should split a floating-point number into a normalized fraction and an integer power of two (medium `x`)', () => {
27+
const expected = medium.expected;
28+
const x = medium.x;
29+
30+
for (let i = 0; i < x.length; i++ ) {
31+
expect(frexp(x[i])).toEqual(expected[i]);
32+
}
33+
});
34+
35+
it('should split a floating-point number into a normalized fraction and an integer power of two (large `x`)', () => {
36+
const expected = large.expected;
37+
const x = large.x;
38+
39+
for (let i = 0; i < x.length; i++ ) {
40+
expect(frexp(x[i])).toEqual(expected[i]);
41+
}
42+
});
43+
44+
it('should split a floating-point number into a normalized fraction and an integer power of two (subnormal `x`)', () => {
45+
const expected = subnormal.expected;
46+
const x = subnormal.x;
47+
48+
for (let i = 0; i < x.length; i++ ) {
49+
expect(frexp(x[i])).toEqual(expected[i]);
50+
}
51+
});
52+
})
53+
54+
describe('ldexp', () => {
55+
const small = require('./fixtures/math/ldexp/small.json');
56+
const medium = require('./fixtures/math/ldexp/medium.json');
57+
const large = require('./fixtures/math/ldexp/large.json');
58+
const subnormal = require('./fixtures/math/ldexp/subnormal.json');
59+
60+
it('should multiply a number by an integer power of two (small values)', () => {
61+
const expected = small.expected;
62+
const frac = small.frac;
63+
const exp = small.exp;
64+
65+
for (let i = 0; i < frac.length; i++ ) {
66+
expect(ldexp(frac[i], exp[i])).toEqual(expected[i]);
67+
}
68+
});
69+
70+
it('should multiply a number by an integer power of two (medium values)', () => {
71+
const expected = medium.expected;
72+
const frac = medium.frac;
73+
const exp = medium.exp;
74+
75+
for (let i = 0; i < frac.length; i++ ) {
76+
expect(ldexp(frac[i], exp[i])).toEqual(expected[i]);
77+
}
78+
});
79+
80+
it('should multiply a number by an integer power of two (large values)', () => {
81+
const expected = large.expected;
82+
const frac = large.frac;
83+
const exp = large.exp;
84+
85+
for (let i = 0; i < frac.length; i++ ) {
86+
expect(ldexp(frac[i], exp[i])).toEqual(expected[i]);
87+
}
88+
});
89+
90+
it('should multiply a number by an integer power of two (subnormals)', () => {
91+
const expected = subnormal.expected;
92+
const frac = subnormal.frac;
93+
const exp = subnormal.exp;
94+
95+
for (let i = 0; i < frac.length; i++ ) {
96+
expect(ldexp(frac[i], exp[i])).toEqual(expected[i]);
97+
}
98+
});
99+
});
100+
});

0 commit comments

Comments
 (0)