functionalscript 0.0.569 → 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 +1 -1
- package/types/bigint/README.md +35 -0
- package/types/bigint/module.f.cjs +54 -8
- package/types/bigint/test.f.cjs +66 -2
package/package.json
CHANGED
|
@@ -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,17 +44,61 @@ const scalar_mul = ({ 0: _0, add }) => a => n => {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
+
}
|
|
75
|
+
let result = 1n
|
|
76
|
+
let i = 1n
|
|
77
|
+
while (true) {
|
|
78
|
+
const n = v >> i
|
|
79
|
+
if (n === 0n) {
|
|
80
|
+
// overshot
|
|
81
|
+
break
|
|
82
|
+
}
|
|
83
|
+
v = n
|
|
84
|
+
result += i
|
|
85
|
+
i <<= 1n
|
|
86
|
+
}
|
|
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) {
|
|
90
|
+
i >>= 1n
|
|
91
|
+
const n = v >> i
|
|
92
|
+
if (n !== 0n) {
|
|
93
|
+
result += i
|
|
94
|
+
v = n
|
|
95
|
+
}
|
|
54
96
|
}
|
|
55
|
-
return
|
|
97
|
+
return result
|
|
56
98
|
}
|
|
57
99
|
|
|
100
|
+
const log2 = (/** @type {bigint} */v) => v <= 0n ? -1n : bitLen(v) - 1n
|
|
101
|
+
|
|
58
102
|
module.exports = {
|
|
59
103
|
/** @readonly */
|
|
60
104
|
addition,
|
|
@@ -70,4 +114,6 @@ module.exports = {
|
|
|
70
114
|
scalar_mul,
|
|
71
115
|
/** @readonly */
|
|
72
116
|
log2,
|
|
117
|
+
/** @readonly */
|
|
118
|
+
bitLen,
|
|
73
119
|
}
|
package/types/bigint/test.f.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { sum, abs, serialize, log2 } = require('./module.f.cjs')
|
|
1
|
+
const { sum, abs, serialize, log2, bitLen } = require('./module.f.cjs')
|
|
2
2
|
|
|
3
3
|
module.exports = {
|
|
4
4
|
sum: () => {
|
|
@@ -69,6 +69,70 @@ module.exports = {
|
|
|
69
69
|
() => {
|
|
70
70
|
const result = log2(16n)
|
|
71
71
|
if (result !== 4n) { throw result }
|
|
72
|
+
},
|
|
73
|
+
() => {
|
|
74
|
+
// max for Bun (131_072 Bytes)
|
|
75
|
+
const v = 1_048_575n
|
|
76
|
+
const result = log2(1n << v)
|
|
77
|
+
if (result !== v) { throw result }
|
|
78
|
+
},
|
|
79
|
+
],
|
|
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
|
|
72
92
|
}
|
|
73
|
-
|
|
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: {
|
|
103
|
+
0: () => {
|
|
104
|
+
const s = bitLen(0n)
|
|
105
|
+
if (s !== 0n) { throw s }
|
|
106
|
+
},
|
|
107
|
+
m: () => {
|
|
108
|
+
let i = 0n
|
|
109
|
+
while (i < 10_000n) {
|
|
110
|
+
const s = bitLen(1n << i)
|
|
111
|
+
if (s !== i + 1n) { throw [s, i] }
|
|
112
|
+
i += 1n
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
big: () => {
|
|
116
|
+
const s = bitLen(1n << 1_000_000n)
|
|
117
|
+
if (s !== 1_000_001n) { throw s }
|
|
118
|
+
},
|
|
119
|
+
neg: [
|
|
120
|
+
() => {
|
|
121
|
+
const s = bitLen(-1n)
|
|
122
|
+
if (s !== 1n) { throw s }
|
|
123
|
+
},
|
|
124
|
+
() => {
|
|
125
|
+
const s = bitLen(-2n)
|
|
126
|
+
if (s !== 2n) { throw s }
|
|
127
|
+
},
|
|
128
|
+
() => {
|
|
129
|
+
const s = bitLen(-3n)
|
|
130
|
+
if (s !== 2n) { throw s }
|
|
131
|
+
},
|
|
132
|
+
() => {
|
|
133
|
+
const s = bitLen(-4n)
|
|
134
|
+
if (s !== 3n) { throw s }
|
|
135
|
+
},
|
|
136
|
+
]
|
|
137
|
+
}
|
|
74
138
|
}
|