Guest User

Untitled

a guest
Jul 20th, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // gcd128.c
  2. // read and caclulate the GCD of two 128-bit unsigned integers
  3. //      (<=38 decimal digits)
  4. //Uses a C structure of an array of 4 ints. (assumes int is 32 bits long)
  5. //
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9.  
  10. typedef struct {
  11.     unsigned int i[4];
  12.     } int128;
  13.    
  14. void ODD128 ( int128 *n);
  15. int GC2int128 ( int128 *n, int128 *p);
  16. void GCD2ODD128( int128 *n, int128 *p);
  17. int128 * ptrmax128 ( int128 *x, int128 *y );
  18. int128 * ptrmin128 ( int128 *x, int128 *y );
  19. void atoi128( int128 *n, char *s);
  20. void i128toa (char *s, int128 *n);
  21.  
  22. int main(int argc, char *args[])
  23. {
  24.     int128 *P, *Q;
  25.     int  R;
  26.     char Pstr[40], Qstr[40];
  27.  
  28.     P = (int128 * ) malloc( sizeof( int128 ) );
  29.     Q = (int128 * ) malloc( sizeof( int128 ) );
  30.    
  31.     printf ("Enter two large integers (up to 38 digits in decimal\n");
  32.    
  33.     scanf("%s %s", Pstr, Qstr);
  34.     atoi128( P, Pstr);
  35.     atoi128( Q, Qstr);
  36.     i128toa(Pstr,P);
  37.     i128toa(Qstr,Q);
  38.     printf(" The GCD of \n  %s  and\n  %s \n is calculated as follows:\n", Pstr, Qstr);
  39.  
  40.     R = GC2int128(P, Q);
  41.     printf(" The greatest power of 2 dividing both numbers is 2^%d\n", R);
  42.    
  43.     ODD128(P);
  44.     ODD128(Q);
  45.     i128toa(Pstr, P);
  46.     i128toa(Qstr, Q);
  47.     printf(" The remaining odd part of P is %s\n", Pstr);
  48.     printf(" The remaining odd part of Q is %s\n", Qstr);
  49.    
  50.     GCD2ODD128(P,Q);
  51.     i128toa( Pstr, P);
  52.     printf(" The GCD of these odd parts is %s \n", Pstr);
  53.     printf(" The GCD of the original pair is 2^%d * %s \n", R, Pstr);
  54.  
  55.     return 0;
  56. }
  57. // GC2int128: repeatedly divides two int128's by 2 if BOTH are even
  58. //  until at least one is odd.
  59.  
  60. int GC2int128 ( int128 *n, int128 *p)
  61. {   int e=0;
  62.     while ( !(n->i[0]&1) &&  !(p->i[0]&1)  ) {
  63.         //n->i[0]>>=1;
  64.         //p->i[0]>>=1;
  65.         //e++; 
  66.         _asm{
  67.             push esi
  68.             push edi
  69.             mov esi, n
  70.             mov edi, p
  71.             again: 
  72.                 test [esi], 1
  73.                 jnz done
  74.                 test [edi], 1
  75.                 jnz done
  76.                 shr DWORD PTR 12[esi], 1
  77.                 ror DWORD PTR 8[esi], 1
  78.                 ror DWORD PTR 4[esi], 1
  79.                 ror DWORD PTR 0[esi], 1
  80.  
  81.                 shr DWORD PTR 12[edi], 1
  82.                 ror DWORD PTR 8[edi], 1
  83.                 ror DWORD PTR 4[edi], 1
  84.                 ror DWORD PTR 0[edi], 1
  85.                
  86.                 inc e
  87.                 jmp again
  88.                
  89.             done:
  90.                 pop edi
  91.                 pop esi
  92.  
  93.         }
  94.  
  95.     }
  96.     return (e);
  97. }
  98. // ODD128: repeatedly divides an int128 by 2 until it is odd.
  99. void ODD128 ( int128 *n)
  100. {
  101.     while( !(n->i[0]&1) ) n->i[0]>>=1;
  102.     return;
  103. }
  104. //GCD2DOO128: repeatedly subtracts the smaller odd int128 from the larger one
  105. //  and calls ODD128 to make them both odd. Stops when they are equal.
  106. void GCD2ODD128( int128 *n, int128 *p)
  107. {
  108.     int128 *lg, *sm;
  109.     while (n->i[0] != p->i[0])
  110.     {
  111.         lg =  ptrmax128(n,p);
  112.         sm = ptrmin128(n,p);   
  113.          lg->i[0]  -= sm->i[0];                  
  114.          p = lg;
  115.          n = sm;
  116.          ODD128 (p);
  117.         }      
  118.     return;
  119. }
  120. //ptrmax128: given two pointers to int128's, returns the pointer to the larger int128.
  121. int128 *ptrmax128(int128 *x, int128 *y )
  122. {
  123.     return (x->i[0]) >=( y->i[0]) ? x: y;
  124. }  
  125.  
  126. //ptrmin128: given two pointers to int128's, returns the pointer to the smaller int128.
  127. int128 *ptrmin128 (int128 *x, int128 *y )
  128. {
  129.     return  (x->i[0] )<= ( y->i[0] )? x: y;
  130. }  
  131. //atoi128: converts a numeric string to int128.
  132. void atoi128( int128 *n, char *s)
  133. {
  134.     n->i[0] = atoi(s);
  135.     n->i[1] = 0;
  136.     n->i[2] = 0;
  137.     n->i[3] = 0;
  138.     return;
  139. }  
  140. // itoa128: converts a 128-bit integer to a string
  141. void i128toa (char *s, int128 * n)
  142. {
  143.     sprintf(s,"%u", n->i[0]);
  144.     return;
  145. }
Add Comment
Please, Sign In to add comment