Hello! So I decided to start trying to implement MTProto protocol (Telegram) in Nim, did the most basic things so I can get a reply from the server for the first time.
To continue I need to decompose a number `pq` into two prime cofactors `p` and `q`, such as `p` < `q`. So basically I need to find the largest prime cofactor of a number and then divide the number by that cofactor to get the second one. The Python version I found runs really fast in under 100ms: from random import randint from math import gcd def brent(N): if N % 2 == 0: return 2 # y, c, m = randint(1, N - 1), randint(1, N - 1), randint(1, N - 1) y = 398563423414958448 c = 259203014236224986 m = 359097073186387306 g, r, q = 1, 1, 1 while g == 1: x = y for i in range(r): y = ((y * y) % N + c) % N k = 0 while k < r and g == 1: ys = y for i in range(min(m, r - k)): y = ((y * y) % N + c) % N q = q * (abs(x - y)) % N g = gcd(q, N) k = k + m r *= 2 if g == N: while True: ys = ((ys * ys) % N + c) % N g = gcd(abs(x - ys), N) if g > 1: break return g def factors(n): a = brent(n) b = n // a return (a, b) if a < b else (b, a) print(factors(1243804461473944423)) Run I tried my hand at porting it to Nim but I guess I failed: import random, math randomize() proc brent*(n: uint64): uint64 = if n mod 2 == 0: return 2 var # y = rand(1'u64 ..< n - 1) y = 398563423414958448'u64 c = 259203014236224986'u64 m = 359097073186387306'u64 g, r, q = 1'u64 x, k, ys = 0'u64 while g == 1: x = y for i in 0 ..< r: y = ((y * y) mod n + c) mod n k = 0'u64 while k < r and g == 1: ys = y for i in 0 ..< min(m, r - k): y = ((y * y) mod n + c) mod n q = q * uint64(abs(int64(x - y))) mod n g = gcd(q, n) k = k + m r *= 2 if g == n: while true: ys = ((ys * ys) mod n + c) mod n g = gcd(uint64(abs(int64(x - ys))), n) if g > 1: break result = g proc factors(n: uint64): (uint64, uint64) = let a = brent(n) let b = n div a if a < b: (a, b) else: (b, a) echo factors(1243804461473944423'u64) Run As far as I can see one of the issues if that there's an overflow when two big uint64's are multiplied. So can someone recommend a good way to port this algorithm, or maybe I can use some other algorithm which won't use such big numbers for multiplication? (I also tried porting [https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm](https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm) and succeeded, but it's quite slow)