double-double
Version:
Pure double-double precision functions *with strict error bounds*.
94 lines (75 loc) • 2.42 kB
text/typescript
import { significand } from "./significand.js";
/**
* Returns the lowest set bit of the given value in [1, (2**31)-1],
* i.e. from 1 up to 2147483647 else if no bit is set (input === 0) returns
* NaN, otherwise if the number is out of range returns a non-finite
* number.
* See https://stackoverflow.com/a/35190288/2010061
* @internal
*/
function getLowestSetBit_(a: number) {
return Math.log2(a & -a);
}
/**
* Returns the lowest set bit of the given number's significand (where the lsb
* is bit 0 and the msb is bit 52). If no bit is set (input === 0 or +-inf or
* NaN) returns NaN.
* See https://stackoverflow.com/a/35190288/2010061
*/
function getLowestSetBit(a: number) {
if (a === 0 || !Number.isFinite(a)) {
// There is no lowest set bit
return NaN;
}
// Note: the significand includes the hidden bit!
const s = significand(a);
const len = s.length;
for (let i=len-1; i>=0; i--) {
if (s[i] === 0) { continue; }
const l = getLowestSetBit_(s[i]);
if (Number.isFinite(l)) {
return (8*(len-i-1)) + l;
}
}
return NaN;
}
/**
* Returns the highest set bit of the given value in [1, 255], i.e. from 1 up
* to 255. If the input number === 0 returns NaN.
* See https://stackoverflow.com/a/35190288/2010061
* @internal
*/
function getHighestSetBit_(a: number) {
return a >= 128 ? 7
: a >= 64 ? 6
: a >= 32 ? 5
: a >= 16 ? 4
: a >= 8 ? 3
: a >= 4 ? 2
: a >= 2 ? 1
: a >= 1 ? 0
: NaN;
}
/**
* Returns the highest set bit of the given double. If no bit is set (input
* === 0 or +/-inf or NaN) returns NaN.
* See https://stackoverflow.com/a/35190288/2010061
*/
function getHighestSetBit(a: number): number {
if (a === 0 || !Number.isFinite(a)) {
// There is no lowest set bit
return NaN;
}
// At this point there must be a highest set bit (always === 52 if the
// number is not a subnormal.
const s = significand(a);
const len = s.length;
for (let i=0; i<len; i++) {
const l = getHighestSetBit_(s[i]);
if (Number.isFinite(l)) {
return (8*(len-i-1)) + l;
}
}
return NaN;
}
export { getLowestSetBit, getHighestSetBit }