functionalscript 0.0.570 → 0.0.571

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.0.570",
3
+ "version": "0.0.571",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "scripts": {
6
6
  "tsc": "tsc",
@@ -0,0 +1,35 @@
1
+ # BigInt
2
+
3
+ Bun has a `bigint` size limitation. It's `1_048_575` bits (`1024 ** 2`) or `131_072` Bytes.
4
+
5
+ ## Benchmarks
6
+
7
+ ### bitLen vs toString(2).length (2024/11/25)
8
+
9
+ |Framework|bitLen |toString(2).length|
10
+ |---------|------------------|------------------|
11
+ |Bun |1.781681 |2.079615 |
12
+ |Deno 1 |0.710344 |1.917003 |
13
+ |Deno 2 |0.986602 |2.286932 |
14
+ |Node 16 |1.521150 |2.330505 |
15
+ |Node 18 |1.393006 |2.312573 |
16
+ |Node 20 |1.055315 |2.320039 |
17
+ |Node 22 |0.983075 |2.336697 |
18
+ |Node 23 |0.699960 |1.872965 |
19
+
20
+ `bitLen` wins.
21
+
22
+ ### Minus vs Not
23
+
24
+ |Framework|minus `-` |not `~` |
25
+ |---------|------------------|------------------|
26
+ |Bun |86.269967 | 80.372970 |
27
+ |Deno 1 |18.754810 | 59.498217 |
28
+ |Deno 2 |17.262486 | 57.157273 |
29
+ |Node 16 |70.350582 |121.023162 |
30
+ |Node 18 |61.039463 | 99.369215 |
31
+ |Node 20 |16.908695 | 63.335552 |
32
+ |Node 22 |19.546644 | 59.034978 |
33
+ |Node 23 |18.246697 | 58.825815 |
34
+
35
+ `-` wins.
@@ -44,21 +44,49 @@ const scalar_mul = ({ 0: _0, add }) => a => n => {
44
44
  }
45
45
  }
46
46
 
47
- const bit_len = (/** @type {bigint} */v) => {
48
- if (v < 0n) { v = -v }
49
- if (v === 0n) { return 0n }
47
+ /**
48
+ * Calculates the bit length of a given BigInt.
49
+ *
50
+ * The bit length of a number is the number of bits required to represent it in binary,
51
+ * excluding leading zeros. For example:
52
+ * - `0n` (binary `...0`) has a bit length of 0.
53
+ * - `1n` (binary `...0_1`) has a bit length of 1.
54
+ * - `255n` (binary `...0_11111111`) has a bit length of 8.
55
+ *
56
+ * Negative inputs are converted to their absolute values before calculation. For example:
57
+ * - `-255n` has a bit length of 8.
58
+ * - `-1n` has a bit length of 1.
59
+ *
60
+ * @param {bigint} v - The input BigInt. It can be positive, negative, or zero.
61
+ * @returns {bigint} The bit length of the input BigInt.
62
+ *
63
+ * @remarks
64
+ * This function determines the bit length in two phases:
65
+ * 1. **Fast Doubling Phase:** Quickly identifies the range of the most significant bit using exponential steps.
66
+ * 2. **Binary Search Phase:** Refines the result to precisely count all significant bits.
67
+ *
68
+ * The algorithm operates with logarithmic complexity, making it efficient for very large BigInts.
69
+ */
70
+ const bitLen = v => {
71
+ if (v <= 0n) {
72
+ if (v === 0n) { return 0n }
73
+ v = -v
74
+ }
50
75
  let result = 1n
51
76
  let i = 1n
52
77
  while (true) {
53
78
  const n = v >> i
54
79
  if (n === 0n) {
80
+ // overshot
55
81
  break
56
82
  }
57
83
  v = n
58
84
  result += i
59
85
  i <<= 1n
60
86
  }
61
- while (i !== 0n) {
87
+ // We know that `v` is not 0 so it doesn't make sense to check `n` when `i` is 0.
88
+ // Because of this, We check if `i` is greater than 1 before we divide it by 2.
89
+ while (i !== 1n) {
62
90
  i >>= 1n
63
91
  const n = v >> i
64
92
  if (n !== 0n) {
@@ -69,7 +97,7 @@ const bit_len = (/** @type {bigint} */v) => {
69
97
  return result
70
98
  }
71
99
 
72
- const log2 = (/** @type {bigint} */v) => v <= 0n ? -1n : bit_len(v) - 1n
100
+ const log2 = (/** @type {bigint} */v) => v <= 0n ? -1n : bitLen(v) - 1n
73
101
 
74
102
  module.exports = {
75
103
  /** @readonly */
@@ -87,5 +115,5 @@ module.exports = {
87
115
  /** @readonly */
88
116
  log2,
89
117
  /** @readonly */
90
- bit_len,
118
+ bitLen,
91
119
  }
@@ -1,4 +1,4 @@
1
- const { sum, abs, serialize, log2, bit_len } = require('./module.f.cjs')
1
+ const { sum, abs, serialize, log2, bitLen } = require('./module.f.cjs')
2
2
 
3
3
  module.exports = {
4
4
  sum: () => {
@@ -75,40 +75,62 @@ module.exports = {
75
75
  const v = 1_048_575n
76
76
  const result = log2(1n << v)
77
77
  if (result !== v) { throw result }
78
- }
78
+ },
79
79
  ],
80
- bit_len: {
80
+ toString2: () => {
81
+ // max for Bun (131_072 Bytes)
82
+ const v = 1_048_575n
83
+ const result = (1n << v).toString(2).length - 1
84
+ if (result !== 1_048_575) { throw result }
85
+ },
86
+ minus: () => {
87
+ let i = 0n
88
+ while (i < 1_048_575n) {
89
+ const s = -i
90
+ if (i !== -s) { throw [i, s] }
91
+ i += 1n
92
+ }
93
+ },
94
+ not: () => {
95
+ let i = 0n
96
+ while (i < 1_048_575n) {
97
+ const s = ~i
98
+ if (i !== ~s) { throw [i, s] }
99
+ i += 1n
100
+ }
101
+ },
102
+ bitLen: {
81
103
  0: () => {
82
- const s = bit_len(0n)
104
+ const s = bitLen(0n)
83
105
  if (s !== 0n) { throw s }
84
106
  },
85
107
  m: () => {
86
108
  let i = 0n
87
109
  while (i < 10_000n) {
88
- const s = bit_len(1n << i)
110
+ const s = bitLen(1n << i)
89
111
  if (s !== i + 1n) { throw [s, i] }
90
112
  i += 1n
91
113
  }
92
114
  },
93
115
  big: () => {
94
- const s = bit_len(1n << 1_000_000n)
116
+ const s = bitLen(1n << 1_000_000n)
95
117
  if (s !== 1_000_001n) { throw s }
96
118
  },
97
119
  neg: [
98
120
  () => {
99
- const s = bit_len(-1n)
121
+ const s = bitLen(-1n)
100
122
  if (s !== 1n) { throw s }
101
123
  },
102
124
  () => {
103
- const s = bit_len(-2n)
125
+ const s = bitLen(-2n)
104
126
  if (s !== 2n) { throw s }
105
127
  },
106
128
  () => {
107
- const s = bit_len(-3n)
129
+ const s = bitLen(-3n)
108
130
  if (s !== 2n) { throw s }
109
131
  },
110
132
  () => {
111
- const s = bit_len(-4n)
133
+ const s = bitLen(-4n)
112
134
  if (s !== 3n) { throw s }
113
135
  },
114
136
  ]