Task: Montgomery reduction

C: #include <stdio.h>
#include <stdlib.h>

typedef unsigned long long ulong;

const int BASE = 2;

struct Montgomery {
    ulong m;
    ulong rrm;
    int n;
};

int bitLength(ulong v) {
    int result = 0;
    while (v > 0) {
        v >>= 1;
        result++;
    }
    return result;
}

ulong modPow(ulong b, ulong e, ulong n) {
    ulong result = 1;

    if (n == 1) {
        return 0;
    }

    b = b % n;
    while (e > 0) {
        if (e % 2 == 1) {
            result = (result * b) % n;
        }
        e >>= 1;
        b = (b * b) % n;
    }

    return result;
}

struct Montgomery makeMontgomery(ulong m) {
    struct Montgomery result;

    if (m == 0 || (m & 1) == 0) {
        fprintf(stderr, "m must be greater than zero and odd");
        exit(1);
    }

    result.m = m;
    result.n = bitLength(m);
    result.rrm = (1ULL << (result.n * 2)) % m;

    return result;
}

ulong reduce(struct Montgomery mont, ulong t) {
    ulong a = t;
    int i;

    for (i = 0; i < mont.n; i++) {
        if ((a & 1) == 1) {
            a += mont.m;
        }
        a = a >> 1;
    }

    if (a >= mont.m) {
        a -= mont.m;
    }
    return a;
}

void check(ulong x1, ulong x2, ulong m) {
    struct Montgomery mont = makeMontgomery(m);
    ulong t1 = x1 * mont.rrm;
    ulong t2 = x2 * mont.rrm;

    ulong r1 = reduce(mont, t1);
    ulong r2 = reduce(mont, t2);
    ulong r = 1ULL << mont.n;

    printf("b :  %d\n", BASE);
    printf("n :  %d\n", mont.n);
    printf("r :  %llu\n", r);
    printf("m :  %llu\n", mont.m);
    printf("t1:  %llu\n", t1);
    printf("t2:  %llu\n", t2);
    printf("r1:  %llu\n", r1);
    printf("r2:  %llu\n", r2);
    printf("\n");
    printf("Original x1       : %llu\n", x1);
    printf("Recovered from r1 : %llu\n", reduce(mont, r1));
    printf("Original x2       : %llu\n", x2);
    printf("Recovered from r2 : %llu\n", reduce(mont, r2));

    printf("\nMontgomery computation of x1 ^ x2 mod m :\n");
    ulong prod = reduce(mont, mont.rrm);
    ulong base = reduce(mont, x1 * mont.rrm);
    ulong exp = x2;
    while (bitLength(exp) > 0) {
        if ((exp & 1) == 1) {
            prod = reduce(mont, prod * base);
        }
        exp >>= 1;
        base = reduce(mont, base * base);
    }
    printf("%llu\n", reduce(mont, prod));
    printf("\nAlternate computation of x1 ^ x2 mod m :\n");
    printf("%llu\n", modPow(x1, x2, m));
}

int main() {
    check(41, 11, 1549);

    return 0;
}



C#: #include<iostream>
#include<conio.h>
using namespace std;
typedef unsigned long ulong;

int ith_digit_finder(long long n, long b, long i){
 
    while(i>0){
        n/=b;
        i--;
    }
    return (n%b);
}

long eeuclid(long m, long b, long *inverse){        
    
    long A1 = 1, A2 = 0, A3 = m,
         B1 = 0, B2 = 1, B3 = b,
         T1, T2, T3, Q;

         cout<<endl<<"eeuclid() started"<<endl;

        while(1){
            if(B3 == 0){
                *inverse = 0;
                return A3;      
            }

            if(B3 == 1){
                *inverse = B2; 
                return B3;      
            }

            Q = A3/B3;

            T1 = A1 - Q*B1;
            T2 = A2 - Q*B2;
            T3 = A3 - Q*B3;

            A1 = B1; A2 = B2; A3 = B3;
            B1 = T1; B2 = T2; B3 = T3;

       }
    cout<<endl<<"ending eeuclid() "<<endl;
}

long long mon_red(long m, long m_dash, long T, int n, long b = 2){

    long long A,ui, temp, Ai;       
    if( m_dash < 0 ) m_dash = m_dash + b;
    A = T;
    for(int i = 0; i<n; i++){
    
        Ai = ith_digit_finder(A, b, i);
        ui = ( ( Ai % b) * m_dash ) % b;
        temp  = ui*m*power(b, i);
        A = A + temp;
    }
    A = A/power(b, n);
    if(A >= m) A = A - m;
    return A;
}

int main(){
    long a, b, c, d=0, e, inverse = 0;
    cout<<"m >> ";
    cin >> a;
    cout<<"T >> ";
    cin>>b;
    cout<<"Radix b >> ";
    cin>>c;
    eeuclid(c, a, &d);      
    e = mon_red(a, -d, b, length_finder(a, c), c);
    cout<<"Montgomery domain representation = "<<e;
    return 0;
}