Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Pi Digits at any position
#1
here's my translation of pi1.c from https://bellard.org/pi/pi1.c
it prints 9 digits of Pi starting at position n
Code: (Select All)
_Title "pi1_c"

$Console:Only
_Dest _Console
Option _Explicit

Dim As Double t
Dim As Long i, n
t = Timer(.0001)
n = -8
pi1 1
pi1 10
pi1 32
pi1 100 - 9
pi1 1000 - 9
Print
Print "                                      Pi = 3."
For i = 1 To 111
    n = n + 9
    pi1 n
Next i

t = Timer(.0001) - t
Print "runtime in seconds = "; t
'Print "press return to end"
'Sleep

Function inv_mod& (x As Long, y As Long)
    Dim As Long q, u, v, a, c, t
    u = x
    v = y
    c = 1
    a = 0
    Do
        q = v \ u
        t = c
        c = a - (q * c)
        a = t
        t = u
        u = v - (q * u)
        v = t
    Loop While u <> 0
    a = a Mod y
    If a < 0 Then
        a = y + a
    End If
    inv_mod = a
End Function

Function inv_mod2& (u As Long, v As Long)
    Dim As Long u1, u3, v1, v3, t1, t3
    u1 = 1
    u3 = u
    v1 = v
    v3 = v
    If (u And 1) <> 0 Then
        t1 = 0
        t3 = -v
        GoTo Y4
    Else
        t1 = 1
        t3 = u
    End If
    Do
        Do
            If (t1 And 1) = 0 Then
                t1 = _ShR(t1, 1)
                t3 = _ShR(t3, 1)
            Else
                t1 = _ShR((t1 + v), 1)
                t3 = _ShR(t3, 1)
            End If
            Y4:
        Loop While (t3 And 1) = 0
        If t3 >= 0 Then
            u1 = t1
            u3 = t3
        Else
            v1 = v - t1
            v3 = -t3
        End If
        t1 = u1 - v1
        t3 = u3 - v3
        If t1 < 0 Then
            t1 = t1 + v
        End If
    Loop While t3 <> 0
    inv_mod2 = u1
End Function

Function pow_mod& (a_in As Long, b_in As Long, m_in As Long)
    Dim As _Integer64 a, b, m, r, aa
    a = a_in
    b = b_in
    m = m_in
    r = 1
    aa = a
    While 1
        If b And 1 Then
            r = (r * aa) Mod m
        End If
        b = _ShR(b, 1)
        If b = 0 Then Exit While
        aa = (aa * aa) Mod m
    Wend
    pow_mod = r
End Function

Function is_prime& (n As Long)
    Dim As Long r, i
    If (n Mod 2) = 0 Then
        is_prime = 0
        Exit Function
    End If
    r = Int(Sqr(CDbl(n)))
    i = 3
    While i <= r
        If (n Mod i) = 0 Then
            is_prime = 0
            Exit Function
        End If
        i = i + 2
    Wend
    is_prime = 1
End Function

Function next_prime& (n As Long)
    Do
        n = n + 1
    Loop While is_prime(n) = 0
    next_prime = n
End Function

Sub fmod (f_mod As Double, num As Double, denom As Double)
    Dim As Double q, fm 'make copy in case the destination and source are the same
    fm = num / denom
    q = Fix(fm)
    fm = fm - q
    fm = fm * denom
    f_mod = fm
End Sub

Sub pi1 (n As Long)
    Dim As _Integer64 av, a, vmax, N2, num, den, k
    Dim As _Integer64 kq1, kq2, kq3, kq4, t, v
    Dim As _Integer64 s, i, t1
    Dim As Double sum
    Dim As String sn
    N2 = Int(((n + 20#) * Log(10#)) / Log(13.5#))
    sum = 0
    a = 2
    While a <= (3 * N2)
        vmax = Int(Log(3# * N2) / Log(CDbl(a)))
        If a = 2 Then
            vmax = vmax + (N2 - n)
            If (vmax <= 0) Then
                GoTo Continue_While
            End If
        End If
        av = 1
        i = 0
        While i < vmax
            av = av * a
            i = i + 1
        Wend
        s = 0
        den = 1
        kq1 = 0
        kq2 = -1
        kq3 = -3
        kq4 = -2
        If a = 2 Then
            num = 1
            v = -n
        Else
            num = pow_mod(2, n, av)
            v = 0
        End If
        k = 1
        While k <= N2
            t = 2 * k
            kq1 = kq1 + 2
            If kq1 >= a Then
                Do
                    kq1 = kq1 - a
                Loop While kq1 >= a
                If kq1 = 0 Then
                    Do
                        t = t \ a
                        v = v - 1
                    Loop While (t Mod a) = 0
                End If
            End If
            num = (num * t) Mod av
            t = (2 * k) - 1
            kq2 = kq2 + 2
            If kq2 >= a Then
                Do
                    kq2 = kq2 - a
                Loop While kq2 >= a
                If kq2 = 0 Then
                    Do
                        t = t \ a
                        v = v - 1
                    Loop While (t Mod a) = 0
                End If
            End If
            num = (num * t) Mod av
            t = 3 * ((3 * k) - 1)
            kq3 = kq3 + 9
            If kq3 >= a Then
                Do
                    kq3 = kq3 - a
                Loop While kq3 >= a
                If kq3 = 0 Then
                    Do
                        t = t \ a
                        v = v + 1
                    Loop While (t Mod a) = 0
                End If
            End If
            den = (den * t) Mod av
            t = (3 * k) - 2
            kq4 = kq4 + 3
            If kq4 >= a Then
                Do
                    kq4 = kq4 - a
                Loop While kq4 >= a
                If kq4 = 0 Then
                    Do
                        t = t \ a
                        v = v + 1
                    Loop While (t Mod a) = 0
                End If
            End If
            If a <> 2 Then
                t = t * 2
            Else
                v = v + 1
            End If
            den = (den * t) Mod av
            If v > 0 Then
                If a <> 2 Then
                    t = inv_mod2(den, av)
                Else
                    t = inv_mod(den, av)
                End If
                t = (t * num) Mod av
                i = v
                While i < vmax
                    t = (t * a) Mod av
                    i = i + 1
                Wend
                t1 = (25 * k) - 3
                t = (t * t1) Mod av
                s = s + t
                If s >= av Then
                    s = s - av
                End If
            End If
            k = k + 1
        Wend
        t = pow_mod(5, n - 1, av)
        s = (s * t) Mod av
        fmod sum, sum + (CDbl(s) / CDbl(av)), 1#
        Continue_While:
        a = next_prime(a)
    Wend
    sn = _Trim$(Str$(Int(sum * 1000000000)))
    While Len(sn) < 9
        sn = "0" + sn
    Wend
    Print Using "Decimal digits of pi at position ########"; n;: Print ":  "; sn
End Sub
Reply
#2
Spot on! +2. It only took 8.3 odd seconds on my Flintstone500.

Pete Big Grin
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  "9,999 digits of PHI with strings" Benchmark Sanmayce 6 1,567 12-30-2024, 04:50 PM
Last Post: vince

Forum Jump:


Users browsing this thread: 1 Guest(s)