Task: Tonelli-Shanks algorithm

C: #include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

uint64_t modpow(uint64_t a, uint64_t b, uint64_t n) {
    uint64_t x = 1, y = a;
    while (b > 0) {
        if (b % 2 == 1) {
            x = (x * y) % n; 
        }
        y = (y * y) % n; 
        b /= 2;
    }
    return x % n;
}

struct Solution {
    uint64_t root1, root2;
    bool exists;
};

struct Solution makeSolution(uint64_t root1, uint64_t root2, bool exists) {
    struct Solution sol;
    sol.root1 = root1;
    sol.root2 = root2;
    sol.exists = exists;
    return sol;
}

struct Solution ts(uint64_t n, uint64_t p) {
    uint64_t q = p - 1;
    uint64_t ss = 0;
    uint64_t z = 2;
    uint64_t c, r, t, m;

    if (modpow(n, (p - 1) / 2, p) != 1) {
        return makeSolution(0, 0, false);
    }

    while ((q & 1) == 0) {
        ss += 1;
        q >>= 1;
    }

    if (ss == 1) {
        uint64_t r1 = modpow(n, (p + 1) / 4, p);
        return makeSolution(r1, p - r1, true);
    }

    while (modpow(z, (p - 1) / 2, p) != p - 1) {
        z++;
    }

    c = modpow(z, q, p);
    r = modpow(n, (q + 1) / 2, p);
    t = modpow(n, q, p);
    m = ss;

    while (true) {
        uint64_t i = 0, zz = t;
        uint64_t b = c, e;
        if (t == 1) {
            return makeSolution(r, p - r, true);
        }
        while (zz != 1 && i < (m - 1)) {
            zz = zz * zz % p;
            i++;
        }
        e = m - i - 1;
        while (e > 0) {
            b = b * b % p;
            e--;
        }
        r = r * b % p;
        c = b * b % p;
        t = t * c % p;
        m = i;
    }
}

void test(uint64_t n, uint64_t p) {
    struct Solution sol = ts(n, p);
    printf("n = %llu\n", n);
    printf("p = %llu\n", p);
    if (sol.exists) {
        printf("root1 = %llu\n", sol.root1);
        printf("root2 = %llu\n", sol.root2);
    } else {
        printf("No solution exists\n");
    }
    printf("\n");
}

int main() {
    test(10, 13);
    test(56, 101);
    test(1030, 10009);
    test(1032, 10009);
    test(44402, 100049);

    return 0;
}








VB: Imports System.Numerics

Module Module1

    Class Solution
        ReadOnly root1 As BigInteger
        ReadOnly root2 As BigInteger
        ReadOnly exists As Boolean

        Sub New(r1 As BigInteger, r2 As BigInteger, e As Boolean)
            root1 = r1
            root2 = r2
            exists = e
        End Sub

        Public Function GetRoot1() As BigInteger
            Return root1
        End Function

        Public Function GetRoot2() As BigInteger
            Return root2
        End Function

        Public Function GetExists() As Boolean
            Return exists
        End Function
    End Class

    Function Ts(n As BigInteger, p As BigInteger) As Solution
        If BigInteger.ModPow(n, (p - 1) / 2, p) <> 1 Then
            Return New Solution(0, 0, False)
        End If

        Dim q As BigInteger = p - 1
        Dim ss = BigInteger.Zero
        While (q Mod 2) = 0
            ss += 1
            q >>= 1
        End While

        If ss = 1 Then
            Dim r1 = BigInteger.ModPow(n, (p + 1) / 4, p)
            Return New Solution(r1, p - r1, True)
        End If

        Dim z As BigInteger = 2
        While BigInteger.ModPow(z, (p - 1) / 2, p) <> p - 1
            z += 1
        End While
        Dim c = BigInteger.ModPow(z, q, p)
        Dim r = BigInteger.ModPow(n, (q + 1) / 2, p)
        Dim t = BigInteger.ModPow(n, q, p)
        Dim m = ss

        Do
            If t = 1 Then
                Return New Solution(r, p - r, True)
            End If
            Dim i = BigInteger.Zero
            Dim zz = t
            While zz <> 1 AndAlso i < (m - 1)
                zz = zz * zz Mod p
                i += 1
            End While
            Dim b = c
            Dim e = m - i - 1
            While e > 0
                b = b * b Mod p
                e = e - 1
            End While
            r = r * b Mod p
            c = b * b Mod p
            t = t * c Mod p
            m = i
        Loop
    End Function

    Sub Main()
        Dim pairs = New List(Of Tuple(Of Long, Long)) From {
            New Tuple(Of Long, Long)(10, 13),
            New Tuple(Of Long, Long)(56, 101),
            New Tuple(Of Long, Long)(1030, 10009),
            New Tuple(Of Long, Long)(1032, 10009),
            New Tuple(Of Long, Long)(44402, 100049),
            New Tuple(Of Long, Long)(665820697, 1000000009),
            New Tuple(Of Long, Long)(881398088036, 1000000000039)
        }

        For Each pair In pairs
            Dim sol = Ts(pair.Item1, pair.Item2)
            Console.WriteLine("n = {0}", pair.Item1)
            Console.WriteLine("p = {0}", pair.Item2)
            If sol.GetExists() Then
                Console.WriteLine("root1 = {0}", sol.GetRoot1())
                Console.WriteLine("root2 = {0}", sol.GetRoot2())
            Else
                Console.WriteLine("No solution exists")
            End If
            Console.WriteLine()
        Next

        Dim bn = BigInteger.Parse("41660815127637347468140745042827704103445750172002")
        Dim bp = BigInteger.Pow(10, 50) + 577
        Dim bsol = Ts(bn, bp)
        Console.WriteLine("n = {0}", bn)
        Console.WriteLine("p = {0}", bp)
        If bsol.GetExists() Then
            Console.WriteLine("root1 = {0}", bsol.GetRoot1())
            Console.WriteLine("root2 = {0}", bsol.GetRoot2())
        Else
            Console.WriteLine("No solution exists")
        End If
    End Sub

End Module