| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | #include <tommath.h>
 | 
					
						
							|  |  |  | #ifdef BN_MP_GCD_C
 | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  | /* LibTomMath, multiple-precision integer library -- Tom St Denis
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |  * LibTomMath is a library that provides multiple-precision | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |  * integer arithmetic as well as number theoretic functionality. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |  * The library was designed directly after the MPI library by | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |  * Michael Fromberger but has been written from scratch with | 
					
						
							|  |  |  |  * additional optimizations in place. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The library is free for all purposes without any express | 
					
						
							|  |  |  |  * guarantee it works. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-04-18 09:58:18 +00:00
										 |  |  |  * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
 | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  | /* Greatest Common Divisor using the binary method */ | 
					
						
							| 
									
										
										
										
											2003-12-24 18:59:22 +00:00
										 |  |  | int mp_gcd (mp_int * a, mp_int * b, mp_int * c) | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |   mp_int  u, v; | 
					
						
							|  |  |  |   int     k, u_lsb, v_lsb, res; | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* either zero than gcd is the largest */ | 
					
						
							| 
									
										
										
										
											2006-04-06 19:49:59 +00:00
										 |  |  |   if (mp_iszero (a) == MP_YES) { | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |     return mp_abs (b, c); | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2006-04-06 19:49:59 +00:00
										 |  |  |   if (mp_iszero (b) == MP_YES) { | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |     return mp_abs (a, c); | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* get copies of a and b we can modify */ | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |   if ((res = mp_init_copy (&u, a)) != MP_OKAY) { | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((res = mp_init_copy (&v, b)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |     goto LBL_U; | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* must be positive for the remainder of the algorithm */ | 
					
						
							|  |  |  |   u.sign = v.sign = MP_ZPOS; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |   /* B1.  Find the common power of two for u and v */ | 
					
						
							|  |  |  |   u_lsb = mp_cnt_lsb(&u); | 
					
						
							|  |  |  |   v_lsb = mp_cnt_lsb(&v); | 
					
						
							|  |  |  |   k     = MIN(u_lsb, v_lsb); | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |   if (k > 0) { | 
					
						
							|  |  |  |      /* divide the power of two out */ | 
					
						
							|  |  |  |      if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |         goto LBL_V; | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |      } | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |      if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |         goto LBL_V; | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |      } | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |   /* divide any remaining factors of two out */ | 
					
						
							|  |  |  |   if (u_lsb != k) { | 
					
						
							|  |  |  |      if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |         goto LBL_V; | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |      } | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |   if (v_lsb != k) { | 
					
						
							|  |  |  |      if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |         goto LBL_V; | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |      } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |   while (mp_iszero(&v) == 0) { | 
					
						
							|  |  |  |      /* make sure v is the largest */ | 
					
						
							|  |  |  |      if (mp_cmp_mag(&u, &v) == MP_GT) { | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |         /* swap u and v to make sure v is >= u */ | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |         mp_exch(&u, &v); | 
					
						
							|  |  |  |      } | 
					
						
							|  |  |  |       | 
					
						
							|  |  |  |      /* subtract smallest from largest */ | 
					
						
							|  |  |  |      if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |         goto LBL_V; | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |      } | 
					
						
							|  |  |  |       | 
					
						
							|  |  |  |      /* Divide out all factors of two */ | 
					
						
							|  |  |  |      if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |         goto LBL_V; | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |      }  | 
					
						
							|  |  |  |   }  | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* multiply by 2**k which we divided out at the beginning */ | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |   if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |      goto LBL_V; | 
					
						
							| 
									
										
										
										
											2003-07-02 15:39:39 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   c->sign = MP_ZPOS; | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |   res = MP_OKAY; | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  | LBL_V:mp_clear (&u); | 
					
						
							|  |  |  | LBL_U:mp_clear (&v); | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |   return res; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-08-01 16:37:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* $Source$ */ | 
					
						
							|  |  |  | /* $Revision$ */ | 
					
						
							|  |  |  | /* $Date$ */ |