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.

Reply via email to