binary-structures-values 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23,6 +23,7 @@ export declare class BitStreamReader {
23
23
  readInt16(): number;
24
24
  readInt32(): number;
25
25
  readBigInt(): bigint;
26
+ readBigFloat(): number | [bigint, bigint];
26
27
  readFloat32(): number;
27
28
  readFloat64(): number;
28
29
  readString(): string;
@@ -227,6 +227,32 @@ class BitStreamReader {
227
227
  this.bitPosition = currentBitPos;
228
228
  return (result & 1n) === 0n ? result >> 1n : -((result + 1n) >> 1n);
229
229
  }
230
+ readBigFloat() {
231
+ const mantissa = this.readBigInt();
232
+ if (mantissa === 0n)
233
+ return 0;
234
+ const exponent = this.readBigInt();
235
+ // Fast path for common cases
236
+ if (exponent === 0n) {
237
+ const numValue = Number(mantissa);
238
+ return BigInt(numValue) === mantissa ? numValue : [mantissa, exponent];
239
+ }
240
+ if (exponent > 0n) {
241
+ const value = mantissa * (10n ** exponent);
242
+ const numValue = Number(value);
243
+ return BigInt(numValue) === value ? numValue : [mantissa, exponent];
244
+ }
245
+ // Negative exponent
246
+ const denom = 10n ** (-exponent);
247
+ const numValue = mantissa % denom === 0n
248
+ ? Number(mantissa / denom)
249
+ : Number(mantissa) / Number(denom);
250
+ // Exact check via reconstruction
251
+ return (Number.isFinite(numValue) &&
252
+ BigInt(Math.round(numValue * Number(denom))) === mantissa)
253
+ ? numValue
254
+ : [mantissa, exponent];
255
+ }
230
256
  readFloat32() {
231
257
  const data = this.byteArray;
232
258
  let pos = this.bitPosition;
@@ -22,6 +22,7 @@ export declare class BitStreamWriter {
22
22
  writeInt16(value: number): void;
23
23
  writeInt32(value: number): void;
24
24
  writeBigInt(value: bigint): void;
25
+ writeBigFloat(value: number | string | [bigint, bigint] | [number, bigint] | [number, number]): void;
25
26
  dumpBytes(label: string, bytes: Uint8Array): void;
26
27
  writeFloat32(value: number): void;
27
28
  writeFloat64(value: number): void;
@@ -208,6 +208,39 @@ class BitStreamWriter {
208
208
  } while (val !== 0n);
209
209
  this.bitPosition = currentBitPos;
210
210
  }
211
+ writeBigFloat(value) {
212
+ // slightly slower
213
+ let mantissa;
214
+ let exponent;
215
+ if (typeof value === 'number') {
216
+ const str = value.toExponential();
217
+ const match = str.match(/^(-?)(\d+\.?\d*)e([+-]?\d+)$/);
218
+ if (!match)
219
+ throw new Error(`Invalid number format: ${str}`);
220
+ const [, sign, man, exp] = match;
221
+ mantissa = BigInt(sign + man.replace('.', ''));
222
+ exponent = BigInt(parseInt(exp) - (man.includes('.') ? man.split('.')[1].length : 0));
223
+ }
224
+ else if (typeof value === 'string') {
225
+ const match = value.match(/^(-?)(\d+)\.(\d+)$/);
226
+ if (!match)
227
+ throw new Error(`Invalid string number format, expected decimal like 123.456: ${value}`);
228
+ const [, sign, intPart, fracPart] = match;
229
+ const mantissaStr = sign + intPart + fracPart;
230
+ exponent = BigInt(-fracPart.length);
231
+ mantissa = BigInt(mantissaStr);
232
+ }
233
+ else if (Array.isArray(value)) {
234
+ const [man, exp] = value;
235
+ mantissa = typeof man === 'bigint' ? man : BigInt(man);
236
+ exponent = typeof exp === 'bigint' ? exp : BigInt(exp);
237
+ }
238
+ else {
239
+ throw new Error(`Unsupported value type for writeBigFloat: ${typeof value}`);
240
+ }
241
+ this.writeBigInt(mantissa);
242
+ this.writeBigInt(exponent);
243
+ }
211
244
  dumpBytes(label, bytes) {
212
245
  console.log(label, Array.from(bytes).map(b => b.toString(2).padStart(8, '0')).join(' '));
213
246
  }
@@ -23,6 +23,7 @@ export declare class BitStreamReader {
23
23
  readInt16(): number;
24
24
  readInt32(): number;
25
25
  readBigInt(): bigint;
26
+ readBigFloat(): number | [bigint, bigint];
26
27
  readFloat32(): number;
27
28
  readFloat64(): number;
28
29
  readString(): string;
@@ -224,6 +224,32 @@ export class BitStreamReader {
224
224
  this.bitPosition = currentBitPos;
225
225
  return (result & 1n) === 0n ? result >> 1n : -((result + 1n) >> 1n);
226
226
  }
227
+ readBigFloat() {
228
+ const mantissa = this.readBigInt();
229
+ if (mantissa === 0n)
230
+ return 0;
231
+ const exponent = this.readBigInt();
232
+ // Fast path for common cases
233
+ if (exponent === 0n) {
234
+ const numValue = Number(mantissa);
235
+ return BigInt(numValue) === mantissa ? numValue : [mantissa, exponent];
236
+ }
237
+ if (exponent > 0n) {
238
+ const value = mantissa * (10n ** exponent);
239
+ const numValue = Number(value);
240
+ return BigInt(numValue) === value ? numValue : [mantissa, exponent];
241
+ }
242
+ // Negative exponent
243
+ const denom = 10n ** (-exponent);
244
+ const numValue = mantissa % denom === 0n
245
+ ? Number(mantissa / denom)
246
+ : Number(mantissa) / Number(denom);
247
+ // Exact check via reconstruction
248
+ return (Number.isFinite(numValue) &&
249
+ BigInt(Math.round(numValue * Number(denom))) === mantissa)
250
+ ? numValue
251
+ : [mantissa, exponent];
252
+ }
227
253
  readFloat32() {
228
254
  const data = this.byteArray;
229
255
  let pos = this.bitPosition;
@@ -22,6 +22,7 @@ export declare class BitStreamWriter {
22
22
  writeInt16(value: number): void;
23
23
  writeInt32(value: number): void;
24
24
  writeBigInt(value: bigint): void;
25
+ writeBigFloat(value: number | string | [bigint, bigint] | [number, bigint] | [number, number]): void;
25
26
  dumpBytes(label: string, bytes: Uint8Array): void;
26
27
  writeFloat32(value: number): void;
27
28
  writeFloat64(value: number): void;
@@ -209,6 +209,39 @@ export class BitStreamWriter {
209
209
  } while (val !== 0n);
210
210
  this.bitPosition = currentBitPos;
211
211
  }
212
+ writeBigFloat(value) {
213
+ // slightly slower
214
+ let mantissa;
215
+ let exponent;
216
+ if (typeof value === 'number') {
217
+ const str = value.toExponential();
218
+ const match = str.match(/^(-?)(\d+\.?\d*)e([+-]?\d+)$/);
219
+ if (!match)
220
+ throw new Error(`Invalid number format: ${str}`);
221
+ const [, sign, man, exp] = match;
222
+ mantissa = BigInt(sign + man.replace('.', ''));
223
+ exponent = BigInt(parseInt(exp) - (man.includes('.') ? man.split('.')[1].length : 0));
224
+ }
225
+ else if (typeof value === 'string') {
226
+ const match = value.match(/^(-?)(\d+)\.(\d+)$/);
227
+ if (!match)
228
+ throw new Error(`Invalid string number format, expected decimal like 123.456: ${value}`);
229
+ const [, sign, intPart, fracPart] = match;
230
+ const mantissaStr = sign + intPart + fracPart;
231
+ exponent = BigInt(-fracPart.length);
232
+ mantissa = BigInt(mantissaStr);
233
+ }
234
+ else if (Array.isArray(value)) {
235
+ const [man, exp] = value;
236
+ mantissa = typeof man === 'bigint' ? man : BigInt(man);
237
+ exponent = typeof exp === 'bigint' ? exp : BigInt(exp);
238
+ }
239
+ else {
240
+ throw new Error(`Unsupported value type for writeBigFloat: ${typeof value}`);
241
+ }
242
+ this.writeBigInt(mantissa);
243
+ this.writeBigInt(exponent);
244
+ }
212
245
  dumpBytes(label, bytes) {
213
246
  console.log(label, Array.from(bytes).map(b => b.toString(2).padStart(8, '0')).join(' '));
214
247
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "binary-structures-values",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "main": "./dist/cjs/index.js",
5
5
  "scripts": {
6
6
  "build": "tsc && tsc -p tsconfig.cjs.json",