nomen-lang 0.0.7 → 0.0.8

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.
Files changed (118) hide show
  1. package/NOMEN_AGENTS.md +235 -0
  2. package/core/System/Ansi.nm +150 -0
  3. package/core/System/Array.nm +358 -0
  4. package/core/System/BigInt.nm +887 -0
  5. package/core/System/Buffer.nm +526 -0
  6. package/core/System/Channel.nm +198 -0
  7. package/core/System/ClassBuffer.nm +229 -0
  8. package/core/System/Console.nm +211 -0
  9. package/core/System/Controls/Button.nm +138 -0
  10. package/core/System/Controls/CheckBox.nm +158 -0
  11. package/core/System/Controls/Container.nm +1562 -0
  12. package/core/System/Controls/Control.nm +28 -0
  13. package/core/System/Controls/Geometry.nm +101 -0
  14. package/core/System/Controls/Layout.nm +228 -0
  15. package/core/System/Controls/LayoutParams.nm +50 -0
  16. package/core/System/Controls/Text.nm +129 -0
  17. package/core/System/Controls/TextBox.nm +157 -0
  18. package/core/System/Controls/Window.nm +280 -0
  19. package/core/System/Disposable.nm +8 -0
  20. package/core/System/Enumerable.nm +10 -0
  21. package/core/System/Equatable.nm +10 -0
  22. package/core/System/Graph.nm +68 -0
  23. package/core/System/Hashable.nm +13 -0
  24. package/core/System/Init.nm +21 -0
  25. package/core/System/LinkedList.nm +64 -0
  26. package/core/System/List.nm +44 -0
  27. package/core/System/Map.nm +153 -0
  28. package/core/System/Math.nm +54 -0
  29. package/core/System/Mutex.nm +78 -0
  30. package/core/System/Nursery.nm +27 -0
  31. package/core/System/Sendable.nm +9 -0
  32. package/core/System/Set.nm +97 -0
  33. package/core/System/Stream/Directory.nm +176 -0
  34. package/core/System/Stream/File.nm +432 -0
  35. package/core/System/Stream/Http.nm +453 -0
  36. package/core/System/String.nm +154 -0
  37. package/core/System/StringBuilder.nm +249 -0
  38. package/core/System/Stringable.nm +8 -0
  39. package/core/System/Task.nm +263 -0
  40. package/core/System/Test.nm +241 -0
  41. package/core/System/Text/Json.nm +377 -0
  42. package/core/System/Text/JsonTree.nm +187 -0
  43. package/core/System/Text/Regex.nm +655 -0
  44. package/core/System/Time.nm +112 -0
  45. package/core/System/Tree.nm +70 -0
  46. package/core/System/Viewable.nm +27 -0
  47. package/core/System/bool.nm +66 -0
  48. package/core/System/char.nm +42 -0
  49. package/core/System/float.nm +43 -0
  50. package/core/System/int.nm +54 -0
  51. package/core/System/int64.nm +42 -0
  52. package/core/System/int8.nm +42 -0
  53. package/core/System/uint.nm +42 -0
  54. package/core/System/uint64.nm +42 -0
  55. package/core/System/uint8.nm +42 -0
  56. package/core/docs/System/Ansi.md +40 -0
  57. package/core/docs/System/Array.md +16 -0
  58. package/core/docs/System/BigInt.md +30 -0
  59. package/core/docs/System/Buffer.md +31 -0
  60. package/core/docs/System/Channel.md +10 -0
  61. package/core/docs/System/ClassBuffer.md +15 -0
  62. package/core/docs/System/Console.md +13 -0
  63. package/core/docs/System/Controls/Button.md +12 -0
  64. package/core/docs/System/Controls/CheckBox.md +15 -0
  65. package/core/docs/System/Controls/Container.md +82 -0
  66. package/core/docs/System/Controls/Control.md +5 -0
  67. package/core/docs/System/Controls/Geometry.md +26 -0
  68. package/core/docs/System/Controls/Layout.md +37 -0
  69. package/core/docs/System/Controls/LayoutParams.md +13 -0
  70. package/core/docs/System/Controls/Text.md +12 -0
  71. package/core/docs/System/Controls/TextBox.md +13 -0
  72. package/core/docs/System/Controls/Window.md +20 -0
  73. package/core/docs/System/Disposable.md +5 -0
  74. package/core/docs/System/Enumerable.md +5 -0
  75. package/core/docs/System/Graph.md +17 -0
  76. package/core/docs/System/Init.md +9 -0
  77. package/core/docs/System/LinkedList.md +16 -0
  78. package/core/docs/System/List.md +13 -0
  79. package/core/docs/System/Map.md +14 -0
  80. package/core/docs/System/Math.md +11 -0
  81. package/core/docs/System/Mutex.md +10 -0
  82. package/core/docs/System/Nursery.md +5 -0
  83. package/core/docs/System/Sendable.md +5 -0
  84. package/core/docs/System/Set.md +14 -0
  85. package/core/docs/System/Stream/Directory.md +12 -0
  86. package/core/docs/System/Stream/File.md +21 -0
  87. package/core/docs/System/String.md +14 -0
  88. package/core/docs/System/StringBuilder.md +12 -0
  89. package/core/docs/System/Stringable.md +5 -0
  90. package/core/docs/System/Task.md +15 -0
  91. package/core/docs/System/Text/Json.md +12 -0
  92. package/core/docs/System/Text/JsonTree.md +21 -0
  93. package/core/docs/System/Text/Regex.md +12 -0
  94. package/core/docs/System/Time.md +11 -0
  95. package/core/docs/System/Tree.md +18 -0
  96. package/core/docs/System/Viewable.md +5 -0
  97. package/core/docs/System/bool.md +9 -0
  98. package/core/docs/System/char.md +9 -0
  99. package/core/docs/System/float.md +9 -0
  100. package/core/docs/System/int.md +10 -0
  101. package/core/docs/System/int64.md +9 -0
  102. package/core/docs/System/int8.md +9 -0
  103. package/core/docs/System/uint.md +9 -0
  104. package/core/docs/System/uint64.md +9 -0
  105. package/core/docs/System/uint8.md +9 -0
  106. package/core/package.jsonc +4 -0
  107. package/dist/index.mjs +417 -5490
  108. package/package.json +33 -30
  109. package/src/args.ts +171 -0
  110. package/src/index.ts +53 -104
  111. package/src/init.ts +128 -0
  112. package/src/test.ts +6 -2
  113. package/test/fixtures/build/calc.test +0 -0
  114. package/test/fixtures/build/calc.test.c +0 -969
  115. package/test/fixtures/build/main.h +0 -170
  116. package/test/fixtures/calc.test.nm +0 -32
  117. package/tsconfig.json +0 -21
  118. package/vite.config.ts +0 -7
@@ -0,0 +1,887 @@
1
+ /**
2
+ * An arbitrary-precision integer
3
+ **/
4
+ pub struct BigInt {
5
+ var sign = 0
6
+ var len = 0
7
+ var digits = Buffer<int>()
8
+
9
+ pub func new = (ref self, int val, out BigInt) {
10
+ self.sign = 1
11
+ var int v = val
12
+ if v < 0 {
13
+ self.sign = -1
14
+ v = 0 - v
15
+ }
16
+ self.digits.grow_int(4)
17
+ self.digits.zero_int(self.digits.cap)
18
+ self.digits.store_int(0, v)
19
+ self.len = 1
20
+ return self
21
+ }
22
+
23
+ inline func get = (self, int i, out uint64) {
24
+ ```
25
+ #arch: c
26
+ return ((unsigned long long*)self->digits.data)[i];
27
+ ```
28
+ ```
29
+ #arch: aarch64
30
+ ldr x0, [x0, #32]
31
+ ldr x0, [x0, x1, lsl #3]
32
+ ```
33
+ }
34
+
35
+ inline func set = (ref self, int i, uint64 val) {
36
+ ```
37
+ #arch: c
38
+ ((unsigned long long*)self->digits.data)[i] = val;
39
+ ```
40
+ ```
41
+ #arch: aarch64
42
+ ldr x0, [x19, #32]
43
+ str x2, [x0, x1, lsl #3]
44
+ ```
45
+ }
46
+
47
+ // Raw data-pointer accessors. The limb loops below hoist `digits.data`
48
+ // into a local once (before the loop) and index through it via get_at /
49
+ // set_at, so each limb access is a single strided load/store instead of
50
+ // re-reading self->digits.data every iteration. ptr is held in a uint64.
51
+ inline func data_ptr = (self, out uint64) {
52
+ ```
53
+ #arch: c
54
+ return (unsigned long long)self->digits.data;
55
+ ```
56
+ ```
57
+ #arch: aarch64
58
+ ldr x0, [x0, #32]
59
+ ```
60
+ }
61
+
62
+ inline func get_at = (self, uint64 ptr, int i, out uint64) {
63
+ ```
64
+ #arch: c
65
+ return ((unsigned long long*)ptr)[i];
66
+ ```
67
+ ```
68
+ #arch: aarch64
69
+ ldr x0, [x1, x2, lsl #3]
70
+ ```
71
+ }
72
+
73
+ inline func set_at = (ref self, uint64 ptr, int i, uint64 val) {
74
+ ```
75
+ #arch: c
76
+ ((unsigned long long*)ptr)[i] = val;
77
+ ```
78
+ ```
79
+ #arch: aarch64
80
+ str x3, [x1, x2, lsl #3]
81
+ ```
82
+ }
83
+
84
+ func ensure = (ref self, int needed) {
85
+ self.digits.grow_int(needed)
86
+ }
87
+
88
+ func clear = (ref self, int len) {
89
+ self.digits.zero_int(len)
90
+ }
91
+
92
+ func copy_range_from = (ref self, BigInt src, int start, int count) {
93
+ self.ensure(count)
94
+ var i = 0
95
+ while i < count; i += 1 {
96
+ self.set(i, src.get(start + i))
97
+ }
98
+ self.len = count
99
+ while self.len > 1 {
100
+ if self.get(self.len - 1) != 0 {
101
+ break
102
+ }
103
+ self.len = self.len - 1
104
+ }
105
+ }
106
+
107
+ func add_at = (ref self, BigInt other, int shift) {
108
+ self.ensure(other.len + shift + 1)
109
+ var carry = 0
110
+ var i = 0
111
+ while i < other.len || carry != 0; i += 1 {
112
+ var uint64 a_val = 0
113
+ if i + shift < self.len {
114
+ a_val = self.get(i + shift)
115
+ }
116
+ var uint64 b_val = 0
117
+ if i < other.len {
118
+ b_val = other.get(i)
119
+ }
120
+ var uint64 sum = a_val + b_val
121
+ var c1 = 0
122
+ if sum < a_val {
123
+ c1 = 1
124
+ }
125
+ const uint64 sum2 = sum + carry
126
+ var c2 = 0
127
+ if sum2 < sum {
128
+ c2 = 1
129
+ }
130
+ self.set(i + shift, sum2)
131
+ carry = c1 + c2
132
+ }
133
+ if i + shift > self.len {
134
+ self.len = i + shift
135
+ }
136
+ }
137
+
138
+ func sub_at = (ref self, BigInt other, int shift) {
139
+ var borrow = 0
140
+ var i = 0
141
+ while i < other.len; i += 1 {
142
+ const uint64 a_val = self.get(i + shift)
143
+ const uint64 b_val = other.get(i)
144
+ const uint64 diff = a_val - borrow
145
+ var new_borrow = 0
146
+ if diff > a_val {
147
+ new_borrow = 1
148
+ }
149
+ const uint64 diff2 = diff - b_val
150
+ if diff2 > diff {
151
+ borrow = new_borrow + 1
152
+ } else {
153
+ borrow = new_borrow
154
+ }
155
+ self.set(i + shift, diff2)
156
+ }
157
+ while borrow != 0; i += 1 {
158
+ const uint64 a_val = self.get(i + shift)
159
+ const uint64 diff = a_val - borrow
160
+ if diff > a_val {
161
+ borrow = 1
162
+ } else {
163
+ borrow = 0
164
+ }
165
+ self.set(i + shift, diff)
166
+ }
167
+ while self.len > 1 {
168
+ if self.get(self.len - 1) != 0 {
169
+ break
170
+ }
171
+ self.len = self.len - 1
172
+ }
173
+ }
174
+
175
+ // (hi:lo) / d with the quotient truncated to 64 bits.
176
+ // Callers guarantee hi <= d (the running remainder is always < divisor,
177
+ // and Knuth-D q_hat estimation has u_hi <= v_top). When hi == d the true
178
+ // quotient is 2^64 + (lo/d), which saturates to UINT64_MAX (== B-1) — the
179
+ // value Knuth-D expects so its correction step brings q_hat back down.
180
+ // When hi < d the quotient fits in 64 bits and is exact.
181
+ //
182
+ // AArch64 has no 128/64 divide instruction, so this calls compiler-rt's
183
+ // ___udivti3 (linked via clang) instead of a 64-iteration bit loop — ~30x
184
+ // faster. The unsigned compare (b.hs) is required: hi/d can have their
185
+ // sign bit set.
186
+ inline func div128 = (self, uint64 hi, uint64 lo, uint64 d, out uint64) {
187
+ ```
188
+ #arch: c
189
+ if (hi >= d) return 18446744073709551615ULL;
190
+ unsigned __int128 n = ((unsigned __int128)hi << 64) | lo;
191
+ return (unsigned long long)(n / d);
192
+ ```
193
+ ```
194
+ #arch: aarch64
195
+ // x0=self(unused) x1=hi x2=lo x3=d -> x0 = quotient
196
+ // ___udivti3(a=x0:x1, b=x2:x3) -> x0:x1 ; we need a=(hi:lo), b=(d:0)
197
+ cmp x1, x3
198
+ b.hs 1f
199
+ mov x0, x2
200
+ mov x2, x3
201
+ mov x3, #0
202
+ str x30, [sp, #-16]!
203
+ bl ___udivti3
204
+ ldr x30, [sp], #16
205
+ b 2f
206
+ 1:
207
+ mov x0, #-1
208
+ 2:
209
+ ```
210
+ }
211
+
212
+ inline func mul_wide_hi = (self, uint64 a, uint64 b, out uint64) {
213
+ ```
214
+ #arch: c
215
+ unsigned __int128 product = (unsigned __int128)(unsigned long long)a * (unsigned long long)b;
216
+ return (unsigned long long)(product >> 64);
217
+ ```
218
+ ```
219
+ #arch: aarch64
220
+ umulh x0, x1, x2
221
+ ```
222
+ }
223
+
224
+ pub func cmp = (self, BigInt other, out int) {
225
+ if self.len != other.len {
226
+ if self.len > other.len {
227
+ return 1
228
+ }
229
+ return -1
230
+ }
231
+ const uint64 sp = self.data_ptr()
232
+ const uint64 op = other.data_ptr()
233
+ var int i = self.len - 1
234
+ while i >= 0; i -= 1 {
235
+ var uint64 a = self.get_at(sp, i)
236
+ var uint64 b = other.get_at(op, i)
237
+ if a != b {
238
+ if a > b {
239
+ return 1
240
+ }
241
+ return -1
242
+ }
243
+ }
244
+ return 0
245
+ }
246
+
247
+ pub func add_to = (ref self, BigInt a, BigInt b) {
248
+ if a.len == 1 && b.len == 1 {
249
+ var uint64 a_val = a.get(0)
250
+ var uint64 b_val = b.get(0)
251
+ const uint64 sum = a_val + b_val
252
+ var carry = 0
253
+ if sum < a_val {
254
+ carry = 1
255
+ }
256
+ self.ensure(2)
257
+ self.set(0, sum)
258
+ self.set(1, carry)
259
+ self.len = 1 + carry
260
+ return
261
+ }
262
+ const int a_len = a.len
263
+ const int b_len = b.len
264
+ var int max_len = a_len
265
+ if b_len > max_len {
266
+ max_len = b_len
267
+ }
268
+ self.ensure(max_len + 2)
269
+ const uint64 ap = a.data_ptr()
270
+ const uint64 bp = b.data_ptr()
271
+ const uint64 sp = self.data_ptr()
272
+ var carry = 0
273
+ var i = 0
274
+ var last_nonzero = 1
275
+ while i < max_len || carry != 0; i += 1 {
276
+ var uint64 a_val = 0
277
+ if i < a_len {
278
+ a_val = a.get_at(ap, i)
279
+ }
280
+ var uint64 b_val = 0
281
+ if i < b_len {
282
+ b_val = b.get_at(bp, i)
283
+ }
284
+ const uint64 sum = a_val + b_val
285
+ var c1 = 0
286
+ if sum < a_val {
287
+ c1 = 1
288
+ }
289
+ const uint64 sum2 = sum + carry
290
+ var c2 = 0
291
+ if sum2 < sum {
292
+ c2 = 1
293
+ }
294
+ self.set_at(sp, i, sum2)
295
+ if sum2 != 0 {
296
+ last_nonzero = i + 1
297
+ }
298
+ carry = c1 + c2
299
+ }
300
+ self.len = i
301
+ if last_nonzero < self.len {
302
+ self.len = last_nonzero
303
+ }
304
+ if self.len == 0 {
305
+ self.len = 1
306
+ }
307
+ }
308
+
309
+ pub func sub_to = (ref self, BigInt a, BigInt b) {
310
+ if a.len == 1 && b.len == 1 {
311
+ self.ensure(1)
312
+ self.set(0, a.get(0) - b.get(0))
313
+ self.len = 1
314
+ return
315
+ }
316
+ self.ensure(a.len)
317
+ const uint64 ap = a.data_ptr()
318
+ const uint64 bp = b.data_ptr()
319
+ const uint64 sp = self.data_ptr()
320
+ var borrow = 0
321
+ var i = 0
322
+ var last_nonzero = 1
323
+ while i < a.len; i += 1 {
324
+ const uint64 a_val = a.get_at(ap, i)
325
+ var uint64 b_val = 0
326
+ if i < b.len {
327
+ b_val = b.get_at(bp, i)
328
+ }
329
+ const uint64 diff = a_val - borrow
330
+ var new_borrow = 0
331
+ if diff > a_val {
332
+ new_borrow = 1
333
+ }
334
+ const uint64 diff2 = diff - b_val
335
+ if diff2 > diff {
336
+ borrow = new_borrow + 1
337
+ } else {
338
+ borrow = new_borrow
339
+ }
340
+ self.set_at(sp, i, diff2)
341
+ if diff2 != 0 {
342
+ last_nonzero = i + 1
343
+ }
344
+ }
345
+ self.len = a.len
346
+ if last_nonzero < self.len {
347
+ self.len = last_nonzero
348
+ }
349
+ if self.len == 0 {
350
+ self.len = 1
351
+ }
352
+ }
353
+
354
+ pub func mul_to = (ref self, BigInt a, BigInt b, ref BigInt scratch) {
355
+ if a.len == 1 || b.len == 1 {
356
+ var uint64 sv
357
+ var int other_len
358
+ if a.len == 1 {
359
+ sv = a.get(0)
360
+ other_len = b.len
361
+ } else {
362
+ sv = b.get(0)
363
+ other_len = a.len
364
+ }
365
+ self.ensure(other_len + 1)
366
+ const uint64 sp = self.data_ptr()
367
+ var uint64 carry = 0
368
+ var i = 0
369
+ var last_nonzero = 0
370
+ if a.len == 1 {
371
+ const uint64 bp = b.data_ptr()
372
+ while i < other_len || carry != 0; i += 1 {
373
+ var uint64 ov = 0
374
+ if i < other_len {
375
+ ov = b.get_at(bp, i)
376
+ }
377
+ const uint64 lo_prod = sv * ov
378
+ const uint64 hi_prod = self.mul_wide_hi(sv, ov)
379
+ const uint64 result = lo_prod + carry
380
+ var c1 = 0
381
+ if result < lo_prod {
382
+ c1 = 1
383
+ }
384
+ carry = hi_prod + c1
385
+ self.set_at(sp, i, result)
386
+ if result != 0 {
387
+ last_nonzero = i + 1
388
+ }
389
+ }
390
+ } else {
391
+ var uint64 ap = a.data_ptr()
392
+ while i < other_len || carry != 0; i += 1 {
393
+ var uint64 ov = 0
394
+ if i < other_len {
395
+ ov = a.get_at(ap, i)
396
+ }
397
+ const uint64 lo_prod = sv * ov
398
+ const uint64 hi_prod = self.mul_wide_hi(sv, ov)
399
+ const uint64 result = lo_prod + carry
400
+ var c1 = 0
401
+ if result < lo_prod {
402
+ c1 = 1
403
+ }
404
+ carry = hi_prod + c1
405
+ self.set_at(sp, i, result)
406
+ if result != 0 {
407
+ last_nonzero = i + 1
408
+ }
409
+ }
410
+ }
411
+ self.len = i
412
+ if last_nonzero < self.len {
413
+ self.len = last_nonzero
414
+ }
415
+ if self.len == 0 {
416
+ self.len = 1
417
+ }
418
+ return
419
+ }
420
+
421
+ // Multi-limb × multi-limb: Karatsuba for large operands, schoolbook for small
422
+ const int new_len = a.len + b.len
423
+ if a.len < 32 && b.len < 32 {
424
+ // Schoolbook for small operands
425
+ scratch.ensure(new_len)
426
+ scratch.clear(new_len)
427
+ scratch.len = new_len
428
+ const uint64 ap = a.data_ptr()
429
+ const uint64 bp = b.data_ptr()
430
+ const uint64 scratchp = scratch.data_ptr()
431
+ var i = 0
432
+ while i < a.len; i += 1 {
433
+ const uint64 ai = a.get_at(ap, i)
434
+ var uint64 carry = 0
435
+ var j = 0
436
+ while j < b.len || carry != 0; j += 1 {
437
+ var uint64 bj = 0
438
+ if j < b.len {
439
+ bj = b.get_at(bp, j)
440
+ }
441
+ const uint64 old = scratch.get_at(scratchp, j + i)
442
+ const uint64 lo_prod = ai * bj
443
+ const uint64 hi_prod = scratch.mul_wide_hi(ai, bj)
444
+ const uint64 cur = old + carry
445
+ var c1 = 0
446
+ if cur < old {
447
+ c1 = 1
448
+ }
449
+ const uint64 cur2 = cur + lo_prod
450
+ var c2 = 0
451
+ if cur2 < cur {
452
+ c2 = 1
453
+ }
454
+ carry = c1 + c2 + hi_prod as int
455
+ scratch.set_at(scratchp, j + i, cur2)
456
+ }
457
+ }
458
+ self.ensure(new_len)
459
+ const uint64 sp = self.data_ptr()
460
+ var last_nonzero = 1
461
+ var k = 0
462
+ while k < new_len; k += 1 {
463
+ const uint64 val = scratch.get_at(scratchp, k)
464
+ self.set_at(sp, k, val)
465
+ if val != 0 {
466
+ last_nonzero = k + 1
467
+ }
468
+ }
469
+ self.len = last_nonzero
470
+ return
471
+ }
472
+
473
+ // Karatsuba: split a = a1*B^m + a0, b = b1*B^m + b0
474
+ // result = z2*B^(2m) + z1*B^m + z0
475
+ // z0 = a0*b0, z2 = a1*b1, z1 = (a0+a1)*(b0+b1) - z0 - z2
476
+ var int m = a.len
477
+ if b.len > m {
478
+ m = b.len
479
+ }
480
+ m = m / 2
481
+
482
+ var int a0_len = m
483
+ if a0_len > a.len {
484
+ a0_len = a.len
485
+ }
486
+ var int b0_len = m
487
+ if b0_len > b.len {
488
+ b0_len = b.len
489
+ }
490
+ const int a1_len = a.len - a0_len
491
+ const int b1_len = b.len - b0_len
492
+
493
+ var a0 = BigInt()
494
+ var a1 = BigInt()
495
+ var b0 = BigInt()
496
+ var b1 = BigInt()
497
+ a0.copy_range_from(a, 0, a0_len)
498
+ b0.copy_range_from(b, 0, b0_len)
499
+ if a1_len > 0 {
500
+ a1.copy_range_from(a, m, a1_len)
501
+ }
502
+ if b1_len > 0 {
503
+ b1.copy_range_from(b, m, b1_len)
504
+ }
505
+
506
+ // z0 = a0 * b0
507
+ var z0 = BigInt()
508
+ var s0 = BigInt()
509
+ z0.mul_to(a0, b0, ref s0)
510
+
511
+ // z2 = a1 * b1 (only if both have high parts)
512
+ var z2 = BigInt()
513
+ var s2 = BigInt()
514
+ if a1_len > 0 && b1_len > 0 {
515
+ z2.mul_to(a1, b1, ref s2)
516
+ }
517
+
518
+ // z1 = (a0+a1)*(b0+b1) - z0 - z2
519
+ var aa = BigInt()
520
+ var bb = BigInt()
521
+ var z1 = BigInt()
522
+ var s1 = BigInt()
523
+ aa.add_to(a0, a1)
524
+ bb.add_to(b0, b1)
525
+ z1.mul_to(aa, bb, ref s1)
526
+ z1.sub_at(z0, 0)
527
+ z1.sub_at(z2, 0)
528
+
529
+ // Combine: self = z0 + z1 << m + z2 << (2*m)
530
+ self.ensure(new_len)
531
+ self.clear(new_len)
532
+ self.len = new_len
533
+ self.add_at(z0, 0)
534
+ self.add_at(z1, m)
535
+ self.add_at(z2, m + m)
536
+ while self.len > 1 {
537
+ if self.get(self.len - 1) != 0 {
538
+ break
539
+ }
540
+ self.len = self.len - 1
541
+ }
542
+
543
+ a0.digits.destroy()
544
+ a1.digits.destroy()
545
+ b0.digits.destroy()
546
+ b1.digits.destroy()
547
+ z0.digits.destroy()
548
+ z2.digits.destroy()
549
+ aa.digits.destroy()
550
+ bb.digits.destroy()
551
+ z1.digits.destroy()
552
+ s0.digits.destroy()
553
+ s1.digits.destroy()
554
+ s2.digits.destroy()
555
+ }
556
+ // self = quotient, a = dividend, b = divisor, remainder = remainder
557
+ // Uses remainder's internal buffer as working space
558
+ pub func div_to = (ref self, BigInt a, BigInt b, ref BigInt remainder) {
559
+ if b.len == 1 {
560
+ const uint64 divisor = b.get(0)
561
+ self.ensure(a.len)
562
+ self.len = a.len
563
+ var uint64 rem = 0
564
+ var last_nonzero = 0
565
+ var int i = a.len - 1
566
+ while i >= 0; i -= 1 {
567
+ var uint64 ai = a.get(i)
568
+ const uint64 q_val = self.div128(rem, ai, divisor)
569
+ const uint64 d_lo = divisor & 4294967295
570
+ const uint64 d_hi = divisor >> 32
571
+ const uint64 q_lo = q_val & 4294967295
572
+ const uint64 q_hi = q_val >> 32
573
+ const uint64 p_ll = q_lo * d_lo
574
+ const uint64 p_lh = q_lo * d_hi
575
+ const uint64 p_hl = q_hi * d_lo
576
+ //const uint64 p_hh = q_hi * d_hi
577
+ const uint64 p_mid = p_lh + p_hl
578
+ var p_mc = 0
579
+ if p_mid < p_lh {
580
+ p_mc = 1
581
+ }
582
+ const uint64 p_lo_val = p_ll + (p_mid << 32)
583
+ var p_lo_c = 0
584
+ if p_lo_val < p_ll {
585
+ p_lo_c = 1
586
+ }
587
+ //const uint64 p_hi_val = p_hh + (p_mid >> 32) + (p_mc as uint64 * 4294967296) + p_lo_c as uint64
588
+ const uint64 sub_lo = ai - p_lo_val
589
+ rem = sub_lo
590
+ self.set(i, q_val)
591
+ if q_val != 0 && last_nonzero == 0 {
592
+ last_nonzero = i + 1
593
+ }
594
+ }
595
+ if last_nonzero == 0 {
596
+ last_nonzero = 1
597
+ }
598
+ if last_nonzero < self.len {
599
+ self.len = last_nonzero
600
+ }
601
+ if self.len == 0 {
602
+ self.len = 1
603
+ }
604
+ remainder.len = 1
605
+ remainder.ensure(1)
606
+ remainder.set(0, rem)
607
+ return
608
+ }
609
+
610
+ // --- Knuth's Algorithm D for multi-limb division ---
611
+ // Uses remainder's digits buffer as working space:
612
+ // [0..n-1] = working divisor (normalized b)
613
+ // [n..n+a.len+1] = working dividend (normalized a)
614
+ const int n = b.len
615
+ const int m = a.len - n
616
+ if m < 0 {
617
+ self.ensure(1)
618
+ self.set(0, 0)
619
+ self.len = 1
620
+ remainder.ensure(a.len)
621
+ remainder.clear(remainder.digits.cap)
622
+ var ci = 0
623
+ while ci < a.len; ci += 1 {
624
+ remainder.set(ci, a.get(ci))
625
+ }
626
+ remainder.len = a.len
627
+ return
628
+ }
629
+
630
+ // D1. Normalize
631
+ const uint64 v_top = b.get(n - 1)
632
+ var shift = 0
633
+ var uint64 clz_mask = 9223372036854775808
634
+ while (clz_mask & v_top) == 0 {
635
+ shift += 1
636
+ clz_mask = clz_mask >> 1
637
+ if shift >= 64 {
638
+ break
639
+ }
640
+ }
641
+
642
+ // Ensure remainder buffer is big enough for working divisor + working dividend
643
+ const int working_size = 2 * n + a.len + 3
644
+ remainder.ensure(working_size)
645
+ remainder.clear(working_size)
646
+ const int wd_off = n
647
+
648
+ // Shift b left by shift into remainder[0..n-1]
649
+ var uint64 carry = 0
650
+ var si = 0
651
+ while si < n; si += 1 {
652
+ const uint64 b_val = b.get(si)
653
+ const uint64 shifted = (b_val << shift) | carry
654
+ remainder.digits.store_int(si, shifted as int)
655
+ if shift > 0 {
656
+ carry = b_val >> (64 - shift)
657
+ } else {
658
+ carry = 0
659
+ }
660
+ }
661
+
662
+ // Shift a left by shift into remainder[wd_off..wd_off+a.len]
663
+ carry = 0
664
+ si = 0
665
+ while si < a.len; si += 1 {
666
+ const uint64 a_val = a.get(si)
667
+ const uint64 shifted = (a_val << shift) | carry
668
+ remainder.digits.store_int(wd_off + si, shifted as int)
669
+ if shift > 0 {
670
+ carry = a_val >> (64 - shift)
671
+ } else {
672
+ carry = 0
673
+ }
674
+ }
675
+ remainder.digits.store_int(wd_off + si, carry as int)
676
+ const int u_len = a.len + 1
677
+
678
+ // D2. Main loop: for j = m down to 0
679
+ self.ensure(m + 2)
680
+ var int j = m
681
+ while j >= 0; j -= 1 {
682
+ // D3. Calculate q_hat
683
+ const uint64 u_hi = remainder.digits.load_int(wd_off + j + n) as uint64
684
+ const uint64 u_lo = remainder.digits.load_int(wd_off + j + n - 1) as uint64
685
+ const uint64 v_n1 = remainder.digits.load_int(n - 1) as uint64
686
+
687
+ var uint64 q_hat = self.div128(u_hi, u_lo, v_n1)
688
+
689
+ // q_hat correction: try q_hat, decrement if too large
690
+ if n >= 2 {
691
+ var try_count = 0
692
+ while try_count < 3 {
693
+ // compute q_hat * v and compare with u[j+n..j]
694
+ var uint64 hv_carry = 0
695
+ var pi = 0
696
+ while pi < n; pi += 1 {
697
+ const uint64 vv = remainder.digits.load_int(pi) as uint64
698
+ const uint64 lo_prod = q_hat * vv
699
+ const uint64 hi_prod = self.mul_wide_hi(q_hat, vv)
700
+ const uint64 p_lo = lo_prod + hv_carry
701
+ hv_carry = hi_prod
702
+ if p_lo < lo_prod {
703
+ hv_carry += 1
704
+ }
705
+ remainder.digits.store_int(wd_off + u_len + 1 + pi, p_lo as int)
706
+ }
707
+
708
+ // Compare hv_carry with u[j+n]
709
+ const uint64 u_at_jn = remainder.digits.load_int(wd_off + j + n) as uint64
710
+ if hv_carry > u_at_jn {
711
+ q_hat -= 1
712
+ try_count += 1
713
+ continue
714
+ }
715
+ if hv_carry < u_at_jn {
716
+ break
717
+ }
718
+
719
+ // hv_carry == u_at_jn, compare lower limbs
720
+ var int cmp_i = n - 1
721
+ var q_too_big = 0
722
+ while cmp_i >= 0 {
723
+ const uint64 prod_limb = remainder.digits.load_int(wd_off + u_len + 1 + cmp_i) as uint64
724
+ const uint64 u_limb = remainder.digits.load_int(wd_off + j + cmp_i) as uint64
725
+ if prod_limb > u_limb {
726
+ q_too_big = 1
727
+ break
728
+ }
729
+ if prod_limb < u_limb {
730
+ break
731
+ }
732
+ cmp_i -= 1
733
+ }
734
+ if q_too_big != 0 {
735
+ q_hat -= 1
736
+ try_count += 1
737
+ continue
738
+ }
739
+ break
740
+ }
741
+ }
742
+
743
+ // D4. Multiply and subtract: u[j+n..j] -= q_hat * v
744
+ // Step 1: Compute q_hat * v into scratch[0..n]
745
+ var uint64 mul_carry = 0
746
+ var mi = 0
747
+ while mi < n; mi += 1 {
748
+ const uint64 vv = remainder.digits.load_int(mi) as uint64
749
+ const uint64 lo_prod = q_hat * vv
750
+ const uint64 hi_prod = self.mul_wide_hi(q_hat, vv)
751
+ const uint64 prod = lo_prod + mul_carry
752
+ mul_carry = hi_prod
753
+ if prod < lo_prod {
754
+ mul_carry += 1
755
+ }
756
+ remainder.digits.store_int(wd_off + u_len + 1 + mi, prod as int)
757
+ }
758
+ remainder.digits.store_int(wd_off + u_len + 1 + n, mul_carry as int)
759
+
760
+ // Step 2: Subtract prod[0..n] from u[j..j+n]
761
+ var uint64 sub_borrow = 0
762
+ var si2 = 0
763
+ while si2 <= n; si2 += 1 {
764
+ const uint64 u_val = remainder.digits.load_int(wd_off + j + si2) as uint64
765
+ const uint64 p_val = remainder.digits.load_int(wd_off + u_len + 1 + si2) as uint64
766
+ const uint64 diff = u_val - p_val
767
+ var borrow1 = 0
768
+ if diff > u_val {
769
+ borrow1 = 1
770
+ }
771
+ const uint64 diff2 = diff - sub_borrow
772
+ var borrow2 = 0
773
+ if diff2 > diff {
774
+ borrow2 = 1
775
+ }
776
+ sub_borrow = (borrow1 + borrow2) as uint64
777
+ remainder.digits.store_int(wd_off + j + si2, diff2 as int)
778
+ }
779
+
780
+ // D5. Test remainder - if borrow was nonzero (negative result), add back
781
+ if sub_borrow != 0 {
782
+ q_hat -= 1
783
+ var uint64 add_carry = 0
784
+ var ai = 0
785
+ while ai < n; ai += 1 {
786
+ const uint64 v_add = remainder.digits.load_int(ai) as uint64
787
+ const uint64 u_add = remainder.digits.load_int(wd_off + j + ai) as uint64
788
+ const uint64 sum = u_add + v_add + add_carry
789
+ var new_carry = 0
790
+ switch {
791
+ case sum < u_add {
792
+ new_carry = 1
793
+ }
794
+ case sum == u_add {
795
+ new_carry = add_carry as int
796
+ }
797
+ }
798
+ remainder.digits.store_int(wd_off + j + ai, sum as int)
799
+ add_carry = new_carry as uint64
800
+ }
801
+ var carry_idx = 0
802
+ while add_carry != 0 {
803
+ const uint64 u_carry = remainder.digits.load_int(wd_off + j + n + carry_idx) as uint64
804
+ const uint64 new_u = u_carry + add_carry
805
+ remainder.digits.store_int(wd_off + j + n + carry_idx, new_u as int)
806
+ if new_u >= u_carry {
807
+ add_carry = 0
808
+ }
809
+ carry_idx += 1
810
+ }
811
+ }
812
+
813
+ // Store quotient digit
814
+ self.ensure(j + 1)
815
+ self.set(j, q_hat)
816
+ }
817
+ self.len = m + 1
818
+ while self.len > 1 {
819
+ if self.get(self.len - 1) != 0 {
820
+ break
821
+ }
822
+ self.len -= 1
823
+ }
824
+
825
+ // Extract remainder from working dividend (normalized at wd_off..wd_off+n-1)
826
+ // Shift right by 'shift' to un-normalize
827
+ remainder.ensure(n)
828
+ remainder.len = n
829
+ if shift > 0 {
830
+ var uint64 r_carry = 0
831
+ var int ri = n - 1
832
+ while ri >= 0; ri -= 1 {
833
+ const uint64 val = remainder.digits.load_int(wd_off + ri) as uint64
834
+ remainder.set(ri, ((val >> shift) | r_carry))
835
+ r_carry = val << (64 - shift)
836
+ }
837
+ } else {
838
+ var ri = 0
839
+ while ri < n; ri += 1 {
840
+ const uint64 val = remainder.digits.load_int(wd_off + ri) as uint64
841
+ remainder.set(ri, val)
842
+ }
843
+ }
844
+ while remainder.len > 1 {
845
+ if remainder.get(remainder.len - 1) != 0 {
846
+ break
847
+ }
848
+ remainder.len = remainder.len - 1
849
+ }
850
+ }
851
+
852
+ pub func to_digit = (self, out int) {
853
+ if self.len == 1 {
854
+ return self.get(0) as int
855
+ }
856
+ return -1
857
+ }
858
+
859
+ pub func copy_from = (ref self, BigInt other) {
860
+ self.ensure(other.len)
861
+ self.len = other.len
862
+ self.sign = other.sign
863
+ var i = 0
864
+ while i < other.len; i += 1 {
865
+ self.set(i, other.get(i))
866
+ }
867
+ }
868
+
869
+ pub func set_int = (ref self, int val) {
870
+ self.sign = 1
871
+ var int v = val
872
+ if v < 0 {
873
+ self.sign = -1
874
+ v = 0 - v
875
+ }
876
+ self.ensure(1)
877
+ self.digits.store_int(0, v)
878
+ self.len = 1
879
+ }
880
+
881
+ pub func set_u64 = (ref self, uint64 val) {
882
+ self.sign = 1
883
+ self.ensure(1)
884
+ self.set(0, val)
885
+ self.len = 1
886
+ }
887
+ }