Skip to content

Commit

Permalink
feat(binary): add endianess detection, 64bit float/int/uint conv
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Feb 10, 2020
1 parent 2efaa7a commit 856e035
Showing 1 changed file with 93 additions and 5 deletions.
98 changes: 93 additions & 5 deletions packages/binary/src/float.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
const F32 = new Float32Array(1);
const I32 = new Int32Array(F32.buffer);
const U32 = new Uint32Array(F32.buffer);
const F64 = new Float64Array(1);
const F32 = new Float32Array(F64.buffer);
const I32 = new Int32Array(F64.buffer);
const U32 = new Uint32Array(F64.buffer);

/**
* This value is true iff the environment is Little Endian.
*/
export const IS_LE = ((F64[0] = 2), U32[1] === 0x40000000);

export const floatToIntBits = (x: number) => ((F32[0] = x), I32[0]);

Expand All @@ -11,8 +17,50 @@ export const intBitsToFloat = (x: number) => ((I32[0] = x), F32[0]);
export const uintBitsToFloat = (x: number) => ((U32[0] = x), F32[0]);

/**
* Converts given float into a sortable integer representation, using
* raw bitwise conversion via {@link floatToIntBits}.
* Returns i32 representation of f64 as [hi, lo] tuple (takes
* environment's Little Endianess into account).
*
* @param x
*/
export const floatToIntBits64 = (x: number): [number, number] => (
(F64[0] = x), IS_LE ? [I32[1], I32[0]] : [I32[0], I32[1]]
);

/**
* Returns u32 representation of f64 as [hi, lo] tuple (takes
* environment's Little Endianess into account).
*
* @param x
*/
export const floatToUintBits64 = (x: number): [number, number] => (
(F64[0] = x), IS_LE ? [U32[1], U32[0]] : [U32[0], U32[1]]
);

/**
* Reverse op of {@link floatToIntBits64}.
*
* @param hi
* @param lo
*/
export const intBitsToFloat64 = (hi: number, lo: number) => {
IS_LE ? ((I32[1] = hi), (I32[0] = lo)) : ((I32[0] = hi), (I32[1] = lo));
return F64[0];
};

/**
* Reverse op of {@link floatToUintBits64}.
*
* @param hi
* @param lo
*/
export const uintBitsToFloat64 = (hi: number, lo: number) => {
IS_LE ? ((U32[1] = hi), (U32[0] = lo)) : ((U32[0] = hi), (U32[1] = lo));
return F64[0];
};

/**
* Converts given float (f32) into a sortable integer representation,
* using raw bitwise conversion via {@link floatToIntBits}.
*
* {@link https://github.com/tzaeschke/phtree/blob/master/PhTreeRevisited.pdf}
* (page 3)
Expand All @@ -27,24 +75,64 @@ export const floatToSortableInt = (x: number) => {

const clamp11 = (x: number) => (x < -1 ? -1 : x > 1 ? 1 : x);

/**
* Converts normalized float ([-1..1] range) to u8.
*
* @param x
*/
export const f32u8 = (x: number) => (clamp11(x) * 0x7f) & 0xff;

/**
* Converts normalized float ([-1..1] range) to u16.
*
* @param x
*/
export const f32u16 = (x: number) => (clamp11(x) * 0x7fff) & 0xffff;

/**
* Converts normalized float ([-1..1] range) to u24.
*
* @param x
*/
export const f32u24 = (x: number) => (clamp11(x) * 0x7fffff) & 0xffffff;

/**
* Converts normalized float ([-1..1] range) to u32.
*
* @param x
*/
export const f32u32 = (x: number) => (clamp11(x) * 0x7fffffff) >>> 0;

/**
* Reverse op of {@link f32u8}.
*
* @param x
*/
export const u8f32 = (x: number) => (
(x &= 0xff), (x | ((x >> 7) * 0xffffff00)) / 0x7f
);

/**
* Reverse op of {@link f32u16}.
*
* @param x
*/
export const u16f32 = (x: number) => (
(x &= 0xffff), (x | ((x >> 15) * 0xffff0000)) / 0x7fff
);

/**
* Reverse op of {@link f32u24}.
*
* @param x
*/
export const u24f32 = (x: number) => (
(x &= 0xffffff), (x | ((x >> 23) * 0xff000000)) / 0x7fffff
);

/**
* Reverse op of {@link f32u32}.
*
* @param x
*/
export const u32f32 = (x: number) => (x | 0) / 0x7fffffff;

0 comments on commit 856e035

Please sign in to comment.