This is no longer Nim's problem, but just for fun, (short of importing
intrinsics)
{.passc:"-march=native".}
import times, math
proc leibniz0(terms: int): float =
var res = 0.0
for n in 0..terms:
res += pow(-1,float(n))/(2*float(n)+1)
4*res
proc leibniz1(terms: int): float =
var res = 0.0
for n in 0..terms:
if (n and 1) == 0: res += 1/(2*float(n)+1)
else: res += -1/(2*float(n)+1)
4*res
proc leibniz2[N:static[int]](terms: int): float =
const
L = 1 shl N
L2 = L shl 1
T = 10
var t: array[L*T, float]
let r = (terms shr N) div T
if (terms mod (L*T)) != 0: quit 1
var res = 1/float(2*terms+1)
for n in 0..<r:
for j in 0..<T:
let jl = j*L
let nl = float(n)*float(L2)*float(T)+float(2*jl)
for i in 0..<L: t[jl+i] += 1/(nl+float(2*i+1))
for j in 1..<T:
for i in 0..<L:
t[i] += t[j*L+i]
for n in 0..<L shr 1: res += t[2*n]-t[2*n+1]
4*res
{.emit:"""
typedef int vi __attribute__ ((vector_size(16),may_alias));
typedef double vd __attribute__ ((vector_size(32),may_alias));
""".}
type
vi {.importc.} = object
vd {.importc.} = object
proc `+=`(x:ptr vd,y:float) =
{.emit:"*`x` += `y`;".}
proc `+=`(x:ptr vd,y:ptr vd) =
{.emit:"*`x` += *`y`;".}
proc inv(y:ptr vd) =
{.emit:"*`y` = 1.0 / *`y`;".}
proc leibniz3(terms: int): float =
const
L = 4
L2 = 2*L
var
t: array[L,float]
z: array[L,float]
let
tt = cast[ptr vd](addr t)
zz = cast[ptr vd](addr z)
let r = terms div L
if (terms mod L) != 0: quit 1
var res = 1/float(2*terms+1)
for n in 0..<r:
let nl = float(n*L2)
for i in 0..<L:
z[i] = float(2*i+1)
zz += nl
inv zz
tt += zz
for n in 0..<L shr 1: res += t[2*n]-t[2*n+1]
4*res
template r(f:untyped) =
const N = 1_000_000_000
let t = cpuTime()
let p = f N
let d = (cpuTime() - t)
echo asttostr(f), " ", p, " Elapsed time: ", d
r leibniz0
r leibniz1
r leibniz2[1]
r leibniz2[2]
r leibniz2[3]
r leibniz2[4]
r leibniz2[5]
r leibniz2[6]
r leibniz2[7]
r leibniz2[8]
r leibniz3
Results completely depend on your C compiler and your CPU. Note that I've
changed the number to be one billion.