I started learning Nim yesterday and decided to code a little test to make a performance comparison with Rust. The code was fairly easy to write and works for values up to 10^9. However, I need to test it with at least 10^12, which gives incorrect values because of an overflow, even while using uint.
I've been trying different conversions for most variables but I can't seem to avoid the overflow. Of course, any suggestions to make the code easier to read are more than welcome!
import math
import sequtils
import unsigned
proc sum_min_pfactor(N : uint) : uint =
proc f(n : uint) : uint =
return n*(n+1) div 2 - 1
var
v = int(math.sqrt(float(N)))
used = newSeqWith(v+1,false)
s_sum,s_cnt,l_cnt,l_sum = newSeq[uint](v+1)
ret = 0.uint
for i in -1..v-1:
s_cnt[i+1] = i.uint
for i in 0..v:
s_sum[i] = f(i.uint)
for i in 1..v:
l_cnt[i] = N div i.uint - 1
l_sum[i] = f(N div i.uint)
for p in 2..v:
if s_cnt[p] == s_cnt[p-1]:
continue
var p_cnt = s_cnt[p - 1]
var p_sum = s_sum[p - 1]
var q = p * p
ret += p.uint * (l_cnt[p] - p_cnt)
l_cnt[1] -= l_cnt[p] - p_cnt
l_sum[1] -= (l_sum[p] - p_sum) * p.uint
var interval = (p and 1) + 1
var finish = min(v,N.int div q)
for i in countup(p+interval,finish,interval):
if used[i]:
continue
var d = i * p
if d <= v:
l_cnt[i] -= l_cnt[d] - p_cnt
l_sum[i] -= (l_sum[d] - p_sum) * p.uint
else:
var t = N.int div d
l_cnt[i] -= s_cnt[t] - p_cnt
l_sum[i] -= (s_sum[t] - p_sum) * p.uint
if q <= v:
for i in countup(q,finish-1,p*interval):
used[i] = true
for i in countdown(v,q-1):
var t = i div p
s_cnt[i] -= s_cnt[t] - p_cnt
s_sum[i] -= (s_sum[t] - p_sum) * p.uint
return l_sum[1] + ret
echo(sum_min_pfactor(uint(math.pow(10,2))))