@@ -389,10 +389,6 @@ template `-=`*(a: var BigInt, b: BigInt) =
389
389
assert a == 3 .initBigInt
390
390
a = a - b
391
391
392
- func abs* (a: BigInt): BigInt =
393
- result = a
394
- result .isNegative = false
395
-
396
392
func unsignedMultiplication(a: var BigInt, b, c: BigInt) {.inline.} =
397
393
# always called with bl >= cl
398
394
let
@@ -450,6 +446,7 @@ func scalarMultiplication(a: var BigInt, b: uint32, c: BigInt) {.inline.} =
450
446
451
447
# forward declaration for use in `multiplication`
452
448
func unsignedKaratsubaMultiplication(a: var BigInt, b, c: BigInt) {.inline.}
449
+ func `shl` * (x: BigInt, y: Natural): BigInt
453
450
454
451
func multiplication(a: var BigInt, b, c: BigInt) =
455
452
# a = b * c
@@ -472,20 +469,31 @@ func multiplication(a: var BigInt, b, c: BigInt) =
472
469
unsignedMultiplication(a, b, c)
473
470
a.isNegative = b.isNegative xor c.isNegative
474
471
472
+ func `shr` * (x: BigInt, y: Natural): BigInt
475
473
func unsignedKaratsubaMultiplication(a: var BigInt, b, c: BigInt) {.inline.} =
476
474
let
477
475
bl = b.limbs.len
478
476
cl = c.limbs.len
479
477
let n = max(bl, cl)
480
478
if bl == 1 :
481
479
# base case : multiply the only limb with each limb of second term
482
- var a: BigInt
483
- unsignedMultiplication(a, c, b)
480
+ scalarMultiplication(a, b.limbs[0 ], c)
484
481
return
485
482
if cl == 1 :
486
- var a: BigInt
487
- unsignedMultiplication(a, b, c)
488
- return
483
+ scalarMultiplication(a, c.limbs[0 ], b)
484
+ return
485
+ if bl < karatsubaTreshold:
486
+ if cl <= bl:
487
+ unsignedMultiplication(a, b, c)
488
+ else :
489
+ unsignedMultiplication(a, c, b)
490
+ return
491
+ if cl < karatsubaTreshold:
492
+ if bl <= cl:
493
+ unsignedMultiplication(a, c, b)
494
+ else :
495
+ unsignedMultiplication(a, b, c)
496
+ return
489
497
let k = n shr 1 # should it be ceil(n/2) ?
490
498
var
491
499
low_b, high_b, low_c, high_c: BigInt
@@ -502,20 +510,18 @@ func unsignedKaratsubaMultiplication(a: var BigInt, b, c: BigInt) {.inline.} =
502
510
unsignedKaratsubaMultiplication(lowProduct, low_b, low_c)
503
511
unsignedKaratsubaMultiplication(highProduct, high_b, high_c)
504
512
A3 = low_b - high_b # Additive variant of Karatsuba
505
- A4 = low_c - high_c # would add them
506
- let sign = A3.isNegative xor A4.isNegative
513
+ A4 = high_c - low_c # would add them
507
514
if A4.limbs.len >= A3.limbs.len:
508
515
multiplication(A5, abs(A4), abs(A3))
509
516
else :
510
517
multiplication(A5, abs(A3), abs(A4))
511
- if sign:
512
- middleTerm = lowProduct + highProduct - A5
513
- else :
514
- middleTerm = lowProduct + highProduct + A5
515
- # result = lowProduct + middleTerm shr k + highProduct shr 2k
516
- a.limbs[0 .. k - 1 ] = lowProduct.limbs
517
- a.limbs[k .. 2 * k- 1 ] = middleTerm.limbs
518
- a.limbs[2 * k .. 3 * k- 1 ] = highProduct.limbs
518
+ middleTerm = lowProduct + highProduct + A5
519
+ a = lowProduct + (middleTerm shr k) + (highProduct shr (2 * k))
520
+ # We could affect directly some of the bits of the result with slicing
521
+ # a.limbs[0 .. k - 1] = lowProduct.limbs
522
+ # But the following instructions would not be correct due to sign handling
523
+ # a.limbs[k .. 2*k-1] = middleTerm.limbs
524
+ # a.limbs[2*k .. 3*k-1] = highProduct.limbs
519
525
520
526
521
527
func `*` * (a, b: BigInt): BigInt =
0 commit comments