/*-------------------------------------------------------------------------*/
/* GNU Prolog                                                              */
/*                                                                         */
/* Part  : development tool                                                */
/* File  : euclide.c                                                       */
/* Descr.: compute inverse                                                 */
/* Author: Daniel Diaz                                                     */
/*                                                                         */
/* Copyright (C) 1999,2000 Daniel Diaz                                     */
/*                                                                         */
/* GNU Prolog is free software; you can redistribute it and/or modify it   */
/* under the terms of the GNU General Public License as published by the   */
/* Free Software Foundation; either version 2, or any later version.       */
/*                                                                         */
/* GNU Prolog is distributed in the hope that it will be useful, but       */
/* WITHOUT ANY WARRANTY; without even the implied warranty of              */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU        */
/* General Public License for more details.                                */
/*                                                                         */
/* You should have received a copy of the GNU General Public License along */
/* with this program; if not, write to the Free Software Foundation, Inc.  */
/* 59 Temple Place - Suite 330, Boston, MA 02111, USA.                     */
/*-------------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>


/*-------------------------------------------------------------------------*/
/* This program takes 2 numbers N1 and N2 (relatively prime) and computes  */
/* N3 s.t. N1*N3 % N2 = 1.                                                 */
/* It uses the Euclide algorithm, by successive divisions of n1 by n2 until*/
/* n2==0 maintaining u1 v1 and u2 v2 s.t., at each step, we have           */
/*                                                                         */
/*    n1=u1*N1 + v1*N2                                                     */
/*    n2=u2*N1 + v2*N2                                                     */
/*                                                                         */
/* At the end, n2=0, n1 is the gdb of N1 and N2 and u1 is the wanted nb.   */
/*                                                                         */
/* This program is used to compute the constant INV_RADIX_MOD_MAX_ATOM  in */
/* atom.c. Indeed, it is the result of euclide RADIX MAX_ATOM, ie. actually*/
/* RADIX=67 and MAX_ATOM=65536 thus INV_RADIX_MOD_MAX_ATOM=19563.          */
/* If MAX_ATOM is changed, INV_RADIX_MOD_MAX_ATOM must be changed too.     */
/*-------------------------------------------------------------------------*/

/*-------------------------------------------------------------------------*/
/* EUCLIDE                                                                 */
/*                                                                         */
/*-------------------------------------------------------------------------*/
unsigned Euclide(unsigned N1,unsigned N2)

{
 unsigned q,r;
 int u2,v2;
 int u1,v1;
 int t;
 unsigned n1=N1;
 unsigned n2=N2;
                                        /* v1 and v2 are not used actually */
 u1=1; v1=0;
 u2=0; v2=1;


 while(n2)
    {
     q=n1 / n2;                                                /* gcd part */
     r=n1 % n2;
     n1=n2;
     n2=r;

     t =u1 - q*u2;                                /* maintaining u1 and u2 */
     u1=u2;
     u2=t;

     t =v1 - q*v2;                                /* maintaining v1 and v2 */
     v1=v2;
     v2=t;
    }

 if (u1<0)
     u1+=N2;

 return u1;
}




/*-------------------------------------------------------------------------*/
/* MAIN                                                                    */
/*                                                                         */
/*-------------------------------------------------------------------------*/
int main(int argc,char *argv[])

{
 unsigned n1;
 unsigned n2;
 unsigned inv_n1_mod_n2;

 if (argc!=3)
    {
     printf("Usage: %s nb_to_invert modulo\n",argv[0]);
     printf("       nb_to_invert and modulo must be relatively prime\n");
     return 1;
    }

 n1=atoi(argv[1]);
 n2=atoi(argv[2]);

 inv_n1_mod_n2=Euclide(n1,n2);

 printf("Res: %-10u i.e. (1/%u) %% %u = %u\n",
        inv_n1_mod_n2,n1,n2,inv_n1_mod_n2);
 printf("     %-10s i.e. (%u*%u) %% %u = 1\n","",n1,inv_n1_mod_n2,n2);

 if ((unsigned) ((n1*inv_n1_mod_n2) % n2) != 1)
     printf("\n*** CHECK ERROR %u instead of 1\n",(n1*inv_n1_mod_n2) % n2);

 return 0;
}



 
