functionalscript 0.0.570 → 0.0.572

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.572",
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,41 @@ 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 }
50
- let result = 1n
47
+ /**
48
+ * Calculates the base-2 logarithm (floor).
49
+ *
50
+ * This function returns the integer part of the logarithm. For example:
51
+ * - `log2(1n)` returns `0n`,
52
+ * - `log2(2n)` returns `1n`,
53
+ * - `log2(15n)` returns `3n`.
54
+ *
55
+ * @param {bigint} v - The input BigInt.
56
+ * @returns {bigint} The base-2 logarithm (floor) of the input BigInt, or `-1n` if the input is less than or equal to 0.
57
+ *
58
+ * @remarks
59
+ * The function operates in two phases:
60
+ * 1. **Fast Doubling Phase:** Uses exponential steps to quickly narrow down the range
61
+ * of the most significant bit.
62
+ * 2. **Binary Search Phase:** Refines the result by halving the step size and incrementally
63
+ * determining the exact value of the logarithm.
64
+ */
65
+ const log2 = v => {
66
+ if (v <= 0n) { return -1n }
67
+ let result = 0n
51
68
  let i = 1n
52
69
  while (true) {
53
70
  const n = v >> i
54
71
  if (n === 0n) {
72
+ // overshot
55
73
  break
56
74
  }
57
75
  v = n
58
76
  result += i
59
77
  i <<= 1n
60
78
  }
61
- while (i !== 0n) {
79
+ // We know that `v` is not 0 so it doesn't make sense to check `n` when `i` is 0.
80
+ // Because of this, We check if `i` is greater than 1 before we divide it by 2.
81
+ while (i !== 1n) {
62
82
  i >>= 1n
63
83
  const n = v >> i
64
84
  if (n !== 0n) {
@@ -69,7 +89,33 @@ const bit_len = (/** @type {bigint} */v) => {
69
89
  return result
70
90
  }
71
91
 
72
- const log2 = (/** @type {bigint} */v) => v <= 0n ? -1n : bit_len(v) - 1n
92
+ /**
93
+ * Calculates the bit length of a given BigInt.
94
+ *
95
+ * The bit length of a number is the number of bits required to represent its absolute value in binary,
96
+ * excluding leading zeros. For example:
97
+ * - `0n` has a bit length of 0 (it has no bits).
98
+ * - `1n` (binary `1`) has a bit length of 1.
99
+ * - `255n` (binary `11111111`) has a bit length of 8.
100
+ * - `-255n` (absolute value `255`, binary `11111111`) also has a bit length of 8.
101
+ *
102
+ * The function handles both positive and negative numbers. For negative inputs, the bit length is calculated
103
+ * based on the absolute value of the number. Zero has a bit length of 0.
104
+ *
105
+ * @param {bigint} v - The input BigInt.
106
+ * @returns {bigint} The bit length of the input BigInt.
107
+ *
108
+ * @remark
109
+ * The function uses the `log2` function to calculate the position of the most significant bit(MSB)
110
+ * and adds `1n` to account for the MSB itself.For negative numbers, the absolute value is used.
111
+ */
112
+ const bitLength = v => {
113
+ if (v <= 0n) {
114
+ if (v === 0n) { return 0n }
115
+ v = -v
116
+ }
117
+ return log2(v) + 1n
118
+ }
73
119
 
74
120
  module.exports = {
75
121
  /** @readonly */
@@ -87,5 +133,5 @@ module.exports = {
87
133
  /** @readonly */
88
134
  log2,
89
135
  /** @readonly */
90
- bit_len,
136
+ bitLength,
91
137
  }
@@ -1,4 +1,4 @@
1
- const { sum, abs, serialize, log2, bit_len } = require('./module.f.cjs')
1
+ const { sum, abs, serialize, log2, bitLength } = 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 = bitLength(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 = bitLength(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 = bitLength(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 = bitLength(-1n)
100
122
  if (s !== 1n) { throw s }
101
123
  },
102
124
  () => {
103
- const s = bit_len(-2n)
125
+ const s = bitLength(-2n)
104
126
  if (s !== 2n) { throw s }
105
127
  },
106
128
  () => {
107
- const s = bit_len(-3n)
129
+ const s = bitLength(-3n)
108
130
  if (s !== 2n) { throw s }
109
131
  },
110
132
  () => {
111
- const s = bit_len(-4n)
133
+ const s = bitLength(-4n)
112
134
  if (s !== 3n) { throw s }
113
135
  },
114
136
  ]