#include <bits/stdc++.h>

#define SIZ 10000

int asmgcd(int a, int b)
{
    /* Compute Greatest Common Divisor using Euclid's Algorithm */
    int result ;
    __asm__ __volatile__ (
        "movl %1, %%eax;"
        "movl %2, %%ebx;"
        "CONTD: cmpl $0, %%ebx;"
        "je DONE;"
        "xorl %%edx, %%edx;"
        "idivl %%ebx;"
        "movl %%ebx, %%eax;"
        "movl %%edx, %%ebx;"
        "jmp CONTD;"
        "DONE: movl %%eax, %0;"
        : "=g" (result)  //outputs
        : "g" (a), "g" (b) //inputs
    );

    return result;
}

inline int mygcd1(register int a, register int b)
{
    while(b)
    {
        register int c = b;
        b = a % c;
        a = c;
    }
    return a;
}

inline int mygcd2(int a, int b)
{
    while(b)
    {
        register int c = b;
        b = a % c;
        a = c;
    }
    return a;
}

inline int mygcd3(int a, int b)
{
    while(b)
    {
        int c = b;
        b = a % c;
        a = c;
    }
    return a;
}

int recur_gcd(int a, int b)
{
    if(b == 0) return a;
    return recur_gcd(b, a % b);
}

int functest(int (*gcdfunc)(int, int))
{
    int i, j;
    time_t start, stop;

    int g = 0;
    start = clock();
    for(i = 1; i < SIZ; ++i)
    {
        for(j = 1; j <= i; ++j)
        {
            g += (gcdfunc(i, j) == 1);
        }
    }
    stop = clock();

    //printf("result = %d\n", g);
    printf("Time: %lf sec\n\n", (double)(stop - start) / CLOCKS_PER_SEC);
}

int main()
{
    puts("STD's gcd:");
    functest(std::__gcd);

    puts("ASM GCD:");
    functest(asmgcd);

    puts("parameter and variable both registers:");
    functest(mygcd1);

    puts("parameter normal, variable register:");
    functest(mygcd2);

    puts("parameter and variable both normal:");
    functest(mygcd3);

    puts("recursive gcd:");
    functest(recur_gcd);

    return 0;
}
