@@ -389,10 +389,6 @@ template `-=`*(a: var BigInt, b: BigInt) =
389389 assert a == 3 .initBigInt
390390 a = a - b
391391
392- func abs * (a: BigInt ): BigInt =
393- result = a
394- result .isNegative = false
395-
396392func unsignedMultiplication (a: var BigInt , b, c: BigInt ) {.inline .} =
397393 # always called with bl >= cl
398394 let
@@ -450,6 +446,7 @@ func scalarMultiplication(a: var BigInt, b: uint32, c: BigInt) {.inline.} =
450446
451447# forward declaration for use in `multiplication`
452448func unsignedKaratsubaMultiplication (a: var BigInt , b, c: BigInt ) {.inline .}
449+ func `shl` * (x: BigInt , y: Natural ): BigInt
453450
454451func multiplication (a: var BigInt , b, c: BigInt ) =
455452 # a = b * c
@@ -472,20 +469,31 @@ func multiplication(a: var BigInt, b, c: BigInt) =
472469 unsignedMultiplication (a, b, c)
473470 a.isNegative = b.isNegative xor c.isNegative
474471
472+ func `shr` * (x: BigInt , y: Natural ): BigInt
475473func unsignedKaratsubaMultiplication (a: var BigInt , b, c: BigInt ) {.inline .} =
476474 let
477475 bl = b.limbs.len
478476 cl = c.limbs.len
479477 let n = max (bl, cl)
480478 if bl == 1 :
481479 # 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)
484481 return
485482 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
489497 let k = n shr 1 # should it be ceil(n/2) ?
490498 var
491499 low_b, high_b, low_c, high_c: BigInt
@@ -502,20 +510,18 @@ func unsignedKaratsubaMultiplication(a: var BigInt, b, c: BigInt) {.inline.} =
502510 unsignedKaratsubaMultiplication (lowProduct, low_b, low_c)
503511 unsignedKaratsubaMultiplication (highProduct, high_b, high_c)
504512 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
507514 if A4 .limbs.len >= A3 .limbs.len:
508515 multiplication (A5 , abs (A4 ), abs (A3 ))
509516 else :
510517 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
519525
520526
521527func `*` * (a, b: BigInt ): BigInt =
0 commit comments