#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "gmp.h"
mpz_t e;
void find_e(mpz_t x, char * test){
    mpz_t a, d,t;
    mpz_init (e);
    mpz_set_str (e,test, 10);
    mpz_init (t);
    mpz_init (a);
    mpz_init (d);
    mpz_gcdext (t, d, a, e,  x);
    while ( mpz_cmp_ui(t,1) != 0) {
        mpz_add_ui(e,e,2);
        mpz_gcdext (t, d, a, e,  x);
    }
    return ;
}
int main (int argc, char* argv[]){
    clock_t start, end;
    double elapsed;
    mpz_t a, t,p,q,pminus1,qminus1,d1,d,n,pm1qm1;
    mpz_t test, etest,back ;
    start = clock();
    printf("\nn=");
    mpz_init (p);
    mpz_init (q);
    mpz_init (n);
    mpz_set_str (p,"32416183339", 10);
    mpz_set_str (q,"4222234763", 10);
    mpz_mul(n,p,q);
    mpz_out_str (stdout, 10, n);
    mpz_init (pminus1);
    mpz_init (qminus1);
    mpz_init (pm1qm1);
    mpz_set_str (pminus1,"32416183338", 10);
    mpz_set_str (qminus1,"4222234762", 10);
    mpz_mul(pm1qm1,pminus1,qminus1);
    printf("\n(p-1)(q-1)=");  
    mpz_out_str (stdout, 10, pm1qm1);
    mpz_init (t);
    mpz_init (a);
    mpz_init (d1);
    printf("\nthe e probe=%s",argv[1]);
    find_e( pm1qm1,argv[1]);
    printf("\ne=");
    mpz_out_str (stdout, 10, e);
    mpz_gcdext (t, d1, a, e,  pm1qm1);
    printf("\nd1=");
    mpz_out_str (stdout, 10, d1);
    mpz_init (d);
    mpz_mod (d, d1,  pm1qm1);
    printf("\nd=");
    mpz_out_str (stdout, 10, d);
    mpz_init (test);mpz_init (etest);mpz_init(back);
    mpz_set_str (test,argv[2], 10);
    mpz_powm (etest,test,e,n);
    printf("\nargv[2] encoded=");
    mpz_out_str (stdout, 10, etest);
    mpz_powm (back,etest,d,n);
    printf("\nargv[2]=");
    mpz_out_str (stdout, 10, back);
    end = clock();
    elapsed=((double) (end - start)) / CLOCKS_PER_SEC;
    printf("\nelapsed time = ");
    printf(" %f seconds \n", elapsed);
    return 0;

}