functionalscript 0.12.6 → 0.12.7

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.12.6",
3
+ "version": "0.12.7",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "**/*.js",
@@ -188,6 +188,16 @@ export declare const msb: BitOrder;
188
188
  * @returns The resulting vector based on the provided bit order.
189
189
  */
190
190
  export declare const u8ListToVec: ({ unpackConcat }: BitOrder) => (list: List<number>) => Vec;
191
+ /**
192
+ * Chunks a bit vector into fixed-size pieces of `n` bits using the provided bit order.
193
+ * The last chunk may be smaller than `n` bits if the vector length is not a multiple of `n`.
194
+ *
195
+ * @param bitOrder The bit order for the conversion.
196
+ * @param n The chunk size in bits.
197
+ * @param v The vector to be chunked.
198
+ * @returns A thunk that produces a list of bit vectors, each representing one chunk.
199
+ */
200
+ export declare const chunkList: ({ unpackSplit }: BitOrder) => (n: bigint) => (v: Vec) => Thunk<Vec>;
191
201
  /**
192
202
  * Converts a bit vector to a list of unsigned 8-bit integers based on the provided bit order.
193
203
  *
@@ -195,7 +205,7 @@ export declare const u8ListToVec: ({ unpackConcat }: BitOrder) => (list: List<nu
195
205
  * @param v The vector to be converted.
196
206
  * @returns A thunk that produces a list of unsigned 8-bit integers.
197
207
  */
198
- export declare const u8List: ({ unpackSplit }: BitOrder) => (v: Vec) => Thunk<number>;
208
+ export declare const u8List: (bo: BitOrder) => (v: Vec) => Thunk<number>;
199
209
  /**
200
210
  * Concatenates a list of vectors using the provided bit order.
201
211
  */
@@ -21,9 +21,9 @@
21
21
  *
22
22
  * @module
23
23
  */
24
- import { bitLength, mask, max, min, xor } from "../bigint/module.f.js";
24
+ import { bitLength, divUp, mask, max, min, xor } from "../bigint/module.f.js";
25
25
  import { flip } from "../function/module.f.js";
26
- import { fold, iterable } from "../list/module.f.js";
26
+ import { fold, iterable, map } from "../list/module.f.js";
27
27
  import { asBase, asNominal } from "../nominal/module.f.js";
28
28
  import { repeat as mRepeat } from "../monoid/module.f.js";
29
29
  import { cmp } from "../function/compare/module.f.js";
@@ -230,37 +230,54 @@ export const u8ListToVec = ({ unpackConcat }) => (list) => {
230
230
  return pack(result.reduce((p, c) => unpackConcat(c)(p), unpackEmpty));
231
231
  };
232
232
  /**
233
- * Converts a bit vector to a list of unsigned 8-bit integers based on the provided bit order.
233
+ * Chunks a bit vector into fixed-size pieces of `n` bits using the provided bit order.
234
+ * The last chunk may be smaller than `n` bits if the vector length is not a multiple of `n`.
234
235
  *
235
236
  * @param bitOrder The bit order for the conversion.
236
- * @param v The vector to be converted.
237
- * @returns A thunk that produces a list of unsigned 8-bit integers.
237
+ * @param n The chunk size in bits.
238
+ * @param v The vector to be chunked.
239
+ * @returns A thunk that produces a list of bit vectors, each representing one chunk.
238
240
  */
239
- export const u8List = ({ unpackSplit }) => (v) => {
240
- if (v === empty) {
241
- return () => null;
242
- }
243
- const f = (stack) => () => {
244
- while (true) {
245
- const [first, rest] = stack;
246
- const { length, uint } = first;
247
- if (length <= 8n) {
248
- // the last unpack split is required to align data.
249
- const v = length < 8n ? unpackSplit(8n)(first)[0] : uint;
250
- return { first: Number(v), tail: rest !== undefined ? f(rest) : null };
251
- }
252
- // `length` is bigger than `8n` so `newLen` is `8n` or bigger.
253
- const aLength = ((length + 7n) >> 4n) << 3n;
254
- const bLength = length - aLength;
255
- const [a, b] = unpackSplit(aLength)(first);
256
- stack = [
257
- { length: aLength, uint: a & mask(aLength) },
258
- [{ length: bLength, uint: b & mask(bLength) }, rest],
259
- ];
241
+ export const chunkList = ({ unpackSplit }) => (n) => {
242
+ const divUpN2 = divUp(n << 1n);
243
+ return v => {
244
+ if (v === empty) {
245
+ return () => null;
260
246
  }
247
+ const f = (stack) => () => {
248
+ while (true) {
249
+ const [first, rest] = stack;
250
+ const { length } = first;
251
+ if (length <= n) {
252
+ return { first: pack(first), tail: rest !== undefined ? f(rest) : null };
253
+ }
254
+ const aLength = divUpN2(length) * n;
255
+ const bLength = length - aLength;
256
+ const [a, b] = unpackSplit(aLength)(first);
257
+ stack = [
258
+ { length: aLength, uint: a & mask(aLength) },
259
+ [{ length: bLength, uint: b & mask(bLength) }, rest],
260
+ ];
261
+ }
262
+ };
263
+ return f([unpack(v), undefined]);
261
264
  };
262
- return f([unpack(v), undefined]);
263
265
  };
266
+ const vecToU8 = ({ unpackSplit }) => {
267
+ const unpackSplit8 = unpackSplit(8n);
268
+ return chunk => {
269
+ const u = unpack(chunk);
270
+ return Number(u.length < 8n ? unpackSplit8(u)[0] : u.uint);
271
+ };
272
+ };
273
+ /**
274
+ * Converts a bit vector to a list of unsigned 8-bit integers based on the provided bit order.
275
+ *
276
+ * @param bitOrder The bit order for the conversion.
277
+ * @param v The vector to be converted.
278
+ * @returns A thunk that produces a list of unsigned 8-bit integers.
279
+ */
280
+ export const u8List = (bo) => (v) => map(vecToU8(bo))(chunkList(bo)(8n)(v));
264
281
  /**
265
282
  * Concatenates a list of vectors using the provided bit order.
266
283
  */
@@ -41,5 +41,12 @@ declare const _default: {
41
41
  msbCmp: () => void;
42
42
  u8ListToVec: () => () => void;
43
43
  u8ListUnaligned: () => void;
44
+ chunkList: {
45
+ empty: () => void;
46
+ lsb_aligned: () => void;
47
+ msb_aligned: () => void;
48
+ lsb_unaligned: () => void;
49
+ msb_unaligned: () => void;
50
+ };
44
51
  };
45
52
  export default _default;
@@ -1,6 +1,6 @@
1
1
  import { mask } from "../bigint/module.f.js";
2
2
  import { asBase, asNominal } from "../nominal/module.f.js";
3
- import { length, empty, uint, vec, lsb, msb, repeat, vec8, u8ListToVec, u8List } from "./module.f.js";
3
+ import { length, empty, uint, vec, lsb, msb, repeat, vec8, u8ListToVec, u8List, chunkList } from "./module.f.js";
4
4
  import { repeat as listRepeat, toArray } from "../list/module.f.js";
5
5
  const unsafeVec = (a) => asNominal(a);
6
6
  // 0x8 = 0b1000 = 0 + 8
@@ -482,5 +482,73 @@ export default {
482
482
  if (a1 !== 0x80) {
483
483
  throw `a1: ${a1.toString(16)}`;
484
484
  }
485
- }
485
+ },
486
+ chunkList: {
487
+ empty: () => {
488
+ const chunks = toArray(chunkList(lsb)(4n)(empty));
489
+ if (chunks.length !== 0) {
490
+ throw chunks.length;
491
+ }
492
+ },
493
+ // 8-bit vector 0xF5 = 0b1111_0101, aligned to 4-bit chunks
494
+ lsb_aligned: () => {
495
+ const chunks = toArray(chunkList(lsb)(4n)(vec(8n)(0xf5n)));
496
+ // LSB: low nibble first — bits 0-3 = 0101 = 5, bits 4-7 = 1111 = 15
497
+ if (chunks.length !== 2) {
498
+ throw chunks.length;
499
+ }
500
+ if (length(chunks[0]) !== 4n || uint(chunks[0]) !== 5n) {
501
+ throw chunks[0];
502
+ }
503
+ if (length(chunks[1]) !== 4n || uint(chunks[1]) !== 0xfn) {
504
+ throw chunks[1];
505
+ }
506
+ },
507
+ msb_aligned: () => {
508
+ const chunks = toArray(chunkList(msb)(4n)(vec(8n)(0xf5n)));
509
+ // MSB: high nibble first — bits 0-3 = 1111 = 15, bits 4-7 = 0101 = 5
510
+ if (chunks.length !== 2) {
511
+ throw chunks.length;
512
+ }
513
+ if (length(chunks[0]) !== 4n || uint(chunks[0]) !== 0xfn) {
514
+ throw chunks[0];
515
+ }
516
+ if (length(chunks[1]) !== 4n || uint(chunks[1]) !== 5n) {
517
+ throw chunks[1];
518
+ }
519
+ },
520
+ // 10-bit vector 0x1B5 = 0b01_1011_0101, unaligned to 4-bit chunks (last chunk is 2 bits)
521
+ lsb_unaligned: () => {
522
+ const chunks = toArray(chunkList(lsb)(4n)(vec(10n)(0x1b5n)));
523
+ // LSB: bits 0-3 = 0101 = 5, bits 4-7 = 1011 = 11, bits 8-9 = 01 = 1
524
+ if (chunks.length !== 3) {
525
+ throw chunks.length;
526
+ }
527
+ if (length(chunks[0]) !== 4n || uint(chunks[0]) !== 5n) {
528
+ throw chunks[0];
529
+ }
530
+ if (length(chunks[1]) !== 4n || uint(chunks[1]) !== 0xbn) {
531
+ throw chunks[1];
532
+ }
533
+ if (length(chunks[2]) !== 2n || uint(chunks[2]) !== 1n) {
534
+ throw chunks[2];
535
+ }
536
+ },
537
+ msb_unaligned: () => {
538
+ const chunks = toArray(chunkList(msb)(4n)(vec(10n)(0x1b5n)));
539
+ // MSB: bits 0-3 = 0110 = 6, bits 4-7 = 1101 = 13, bits 8-9 = 01 = 1
540
+ if (chunks.length !== 3) {
541
+ throw chunks.length;
542
+ }
543
+ if (length(chunks[0]) !== 4n || uint(chunks[0]) !== 6n) {
544
+ throw chunks[0];
545
+ }
546
+ if (length(chunks[1]) !== 4n || uint(chunks[1]) !== 0xdn) {
547
+ throw chunks[1];
548
+ }
549
+ if (length(chunks[2]) !== 2n || uint(chunks[2]) !== 1n) {
550
+ throw chunks[2];
551
+ }
552
+ },
553
+ },
486
554
  };