functionalscript 0.11.8 → 0.11.9

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.11.8",
3
+ "version": "0.11.9",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "**/*.js",
@@ -13,7 +13,7 @@
13
13
  "test": "tsc && node --test --experimental-strip-types --experimental-test-coverage --test-coverage-include=**/module.f.ts",
14
14
  "index": "node ./fjs/module.ts r ./dev/index/module.f.ts",
15
15
  "fst": "node ./fjs/module.ts t",
16
- "fjs": "node ./fjs/module.ts",
16
+ "start": "node ./fjs/module.ts",
17
17
  "ci-update": "node ./fjs/module.ts r ./ci/module.f.ts",
18
18
  "update": "git clean -fdx && npm install && npm run index && npm run ci-update",
19
19
  "website": "node --experimental-strip-types ./fjs/module.ts r ./website/module.f.ts"
@@ -1,5 +1,5 @@
1
1
  import { bitLength, max } from "../bigint/module.f.js";
2
- import { empty, isVec, length, listToVec, msb, msbCmp, uint, unpack, vec, vec8 } from "../bit_vec/module.f.js";
2
+ import { empty, isVec, length, listToVec, msb, uint, unpack, vec, vec8 } from "../bit_vec/module.f.js";
3
3
  import { identity } from "../function/module.f.js";
4
4
  import { encode as b128encode, decode as b128decode } from "../base128/module.f.js";
5
5
  const pop = msb.popFront;
@@ -163,7 +163,7 @@ export const decodeSequence = (v) => {
163
163
  return result;
164
164
  };
165
165
  /** Encodes a SET payload with canonical byte ordering. */
166
- export const encodeSet = genericEncodeSequence(v => v.toSorted((a, b) => msbCmp(a)(b)));
166
+ export const encodeSet = genericEncodeSequence(v => v.toSorted((a, b) => msb.cmp(a)(b)));
167
167
  /** Decodes a SET payload. */
168
168
  export const decodeSet = decodeSequence;
169
169
  // encode
@@ -153,6 +153,15 @@ export type BitOrder = {
153
153
  readonly xor: Reduce;
154
154
  readonly unpackPopFront: PopFront<Unpacked>;
155
155
  readonly norm: NormOp;
156
+ /**
157
+ * Lexically compares two vectors.
158
+ *
159
+ * a < b => -1
160
+ * a > b => 1
161
+ * a === b => 0
162
+ */
163
+ readonly cmp: (a: Vec) => (b: Vec) => Sign;
164
+ readonly unpackSplit: (len: bigint) => (u: Unpacked) => readonly [bigint, bigint];
156
165
  };
157
166
  /**
158
167
  * Implements operations for handling vectors in a least-significant-bit (LSb) first order.
@@ -185,7 +194,7 @@ export declare const u8ListToVec: ({ concat }: BitOrder) => (list: List<number>)
185
194
  * @param v The vector to be converted.
186
195
  * @returns A thunk that produces a list of unsigned 8-bit integers.
187
196
  */
188
- export declare const u8List: ({ unpackPopFront }: BitOrder) => (v: Vec) => Thunk<number>;
197
+ export declare const u8List: ({ unpackSplit }: BitOrder) => (v: Vec) => Thunk<number>;
189
198
  /**
190
199
  * Concatenates a list of vectors using the provided bit order.
191
200
  */
@@ -195,14 +204,4 @@ export declare const listToVec: ({ concat }: BitOrder) => (list: List<Vec>) => V
195
204
  */
196
205
  export declare const repeat: Fold<bigint, Vec>;
197
206
  export declare const isVec: <T>(v: Vec | T) => v is Vec;
198
- /**
199
- * Lexically compares two vectors based on their unsigned integer values,
200
- * normalizing them to the same length. If the values are equal,
201
- * the shorter vector is considered smaller.
202
- *
203
- * a < b => -1
204
- * a > b => 1
205
- * a === b => 0
206
- */
207
- export declare const msbCmp: (av: Vec) => (bv: Vec) => Sign;
208
207
  export {};
@@ -107,12 +107,13 @@ const op = (norm) => (op) => ap => bp => {
107
107
  const { a, b } = norm(au)(bu)(len);
108
108
  return vec(len)(op(a)(b));
109
109
  };
110
- const bo = ({ front, removeFront, concat, rawPopFront, norm }) => {
110
+ const bo = ({ front, removeFront, concat, norm, uintCmp, unpackSplit }) => {
111
111
  const unpackPopFront = (len) => {
112
112
  const m = mask(len);
113
+ const us = unpackSplit(len);
113
114
  return (v) => {
114
- const [uint, rest] = rawPopFront(len)(v);
115
- return [uint & m, rest];
115
+ const [uint, rest] = us(v);
116
+ return [uint & m, { length: v.length - len, uint: rest }];
116
117
  };
117
118
  };
118
119
  return {
@@ -129,6 +130,16 @@ const bo = ({ front, removeFront, concat, rawPopFront, norm }) => {
129
130
  };
130
131
  },
131
132
  norm,
133
+ cmp: a => b => {
134
+ const au = unpack(a);
135
+ const bu = unpack(b);
136
+ const al = au.length;
137
+ const bl = bu.length;
138
+ const { a: aui, b: bui } = norm(au)(bu)(min(al)(bl));
139
+ const c = uintCmp(aui)(bui);
140
+ return c === 0 ? cmp(al)(bl) : c;
141
+ },
142
+ unpackSplit,
132
143
  };
133
144
  };
134
145
  /**
@@ -153,7 +164,11 @@ export const lsb = bo({
153
164
  return vec(al + bl)((bu << al) | au);
154
165
  },
155
166
  norm: ({ uint: a }) => ({ uint: b }) => () => ({ a, b }),
156
- rawPopFront: len => ({ length, uint }) => [uint, { length: length - len, uint: uint >> len }]
167
+ uintCmp: a => b => {
168
+ const diff = a ^ b;
169
+ return diff === 0n ? 0 : (a & (diff & -diff)) === 0n ? -1 : 1;
170
+ },
171
+ unpackSplit: len => ({ uint }) => [uint, uint >> len]
157
172
  });
158
173
  /**
159
174
  * Implements operations for handling vectors in a most-significant-bit (MSb) first order.
@@ -176,10 +191,8 @@ export const msb = bo({
176
191
  },
177
192
  concat: flip(lsb.concat),
178
193
  norm: ({ length: al, uint: a }) => ({ length: bl, uint: b }) => len => ({ a: a << (len - al), b: b << (len - bl) }),
179
- rawPopFront: len => ({ length, uint }) => {
180
- const d = length - len;
181
- return [uint >> d, { length: d, uint }];
182
- }
194
+ uintCmp: cmp,
195
+ unpackSplit: len => ({ length, uint }) => [uint >> (length - len), uint]
183
196
  });
184
197
  /**
185
198
  * Converts a list of unsigned 8-bit integers to a bit vector using the provided bit order.
@@ -223,16 +236,30 @@ export const u8ListToVec = ({ concat }) => (list) => {
223
236
  * @param v The vector to be converted.
224
237
  * @returns A thunk that produces a list of unsigned 8-bit integers.
225
238
  */
226
- export const u8List = ({ unpackPopFront }) => {
227
- const pf = unpackPopFront(8n);
228
- const f = (u) => () => {
229
- if (u.length <= 0n) {
230
- return null;
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
+ ];
231
260
  }
232
- const [first, tail] = pf(u);
233
- return { first: Number(first), tail: f(tail) };
234
261
  };
235
- return v => f(unpack(v));
262
+ return f([unpack(v), undefined]);
236
263
  };
237
264
  /**
238
265
  * Concatenates a list of vectors using the provided bit order.
@@ -243,21 +270,3 @@ export const listToVec = ({ concat }) => fold(flip(concat))(empty);
243
270
  */
244
271
  export const repeat = mRepeat({ identity: empty, operation: lsb.concat });
245
272
  export const isVec = (v) => typeof v === 'bigint';
246
- /**
247
- * Lexically compares two vectors based on their unsigned integer values,
248
- * normalizing them to the same length. If the values are equal,
249
- * the shorter vector is considered smaller.
250
- *
251
- * a < b => -1
252
- * a > b => 1
253
- * a === b => 0
254
- */
255
- export const msbCmp = (av) => (bv) => {
256
- const au = unpack(av);
257
- const bu = unpack(bv);
258
- const al = au.length;
259
- const bl = bu.length;
260
- const { a, b } = msb.norm(au)(bu)(min(al)(bl));
261
- const result = cmp(a)(b);
262
- return result !== 0 ? result : cmp(al)(bl);
263
- };
@@ -37,6 +37,7 @@ declare const _default: {
37
37
  lsbXor: () => void;
38
38
  msbXor: () => void;
39
39
  repeat: () => void;
40
+ lsbCmp: () => void;
40
41
  msbCmp: () => void;
41
42
  u8ListToVec: () => () => void;
42
43
  u8ListUnaligned: () => void;
@@ -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, msbCmp, u8ListToVec, u8List } from "./module.f.js";
3
+ import { length, empty, uint, vec, lsb, msb, repeat, vec8, u8ListToVec, u8List } 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
@@ -430,9 +430,23 @@ export default {
430
430
  throw 'repeat failed';
431
431
  }
432
432
  },
433
+ lsbCmp: () => {
434
+ const c = (a) => (b) => (r) => {
435
+ const result = lsb.cmp(a)(b);
436
+ if (result !== r) {
437
+ throw `result: ${result}, expected: ${r}`;
438
+ }
439
+ };
440
+ c(vec(4n)(0x5n))(vec(4n)(0x5n))(0); // [1,0,1,0] == [1,0,1,0]
441
+ c(vec(4n)(0x5n))(vec(4n)(0x6n))(1); // bit0: 1 > 0
442
+ c(vec(4n)(0x6n))(vec(4n)(0x5n))(-1); // bit0: 0 < 1
443
+ c(vec(4n)(0x5n))(vec(5n)(0x5n))(-1); // equal prefix, shorter is less
444
+ c(vec(5n)(0x5n))(vec(4n)(0x5n))(1); // equal prefix, longer is greater
445
+ c(vec(4n)(0x5n))(vec(5n)(0xan))(1); // bit0: 1 > 0
446
+ },
433
447
  msbCmp: () => {
434
448
  const c = (a) => (b) => (r) => {
435
- const result = msbCmp(a)(b);
449
+ const result = msb.cmp(a)(b);
436
450
  if (result !== r) {
437
451
  throw `result: ${result}, expected: ${r}`;
438
452
  }
@@ -451,7 +465,7 @@ export default {
451
465
  const m = u8List(msb)(x);
452
466
  const y = toArray(m);
453
467
  if (y.length !== 131_071) {
454
- throw y.length;
468
+ throw `y.lenght: ${y.length}`;
455
469
  }
456
470
  };
457
471
  },
@@ -459,7 +473,7 @@ export default {
459
473
  const x = vec(9n)(0x83n);
460
474
  const a = toArray(u8List(msb)(x));
461
475
  if (a.length !== 2) {
462
- throw a;
476
+ throw `a.lenght: ${a.length}`;
463
477
  }
464
478
  const [a0, a1] = a;
465
479
  if (a0 !== 0x41) {
@@ -4,7 +4,7 @@ type NotLazy<T> = Result<T> | Concat<T> | readonly T[];
4
4
  type Empty = null;
5
5
  export type Result<T> = Empty | NonEmpty<T>;
6
6
  export type Thunk<T> = () => List<T>;
7
- type NonEmpty<T> = {
7
+ export type NonEmpty<T> = {
8
8
  readonly first: T;
9
9
  readonly tail: List<T>;
10
10
  };