| 
									
										
										
										
											2018-05-02 21:43:17 +02:00
										 |  |  | #include "tommath_private.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-14 11:26:07 +01:00
										 |  |  | #ifdef BN_MP_N_ROOT_EX_C
 | 
					
						
							|  |  |  | /* LibTomMath, multiple-precision integer library -- Tom St Denis
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * LibTomMath is a library that provides multiple-precision | 
					
						
							|  |  |  |  * integer arithmetic as well as number theoretic functionality. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The library was designed directly after the MPI library by | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* find the n'th root of an integer
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Result found such that (c)**b <= a and (c+1)**b > a | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This algorithm uses Newton's approximation | 
					
						
							|  |  |  |  * x[i+1] = x[i] - f(x[i])/f'(x[i]) | 
					
						
							|  |  |  |  * which will find the root in log(N) time where | 
					
						
							|  |  |  |  * each step involves a fair bit.  This is not meant to | 
					
						
							|  |  |  |  * find huge roots [square and cube, etc]. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-09-20 16:59:43 +02:00
										 |  |  | int mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) | 
					
						
							| 
									
										
										
										
											2014-02-14 11:26:07 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-20 16:59:43 +02:00
										 |  |  |    mp_int  t1, t2, t3, a_; | 
					
						
							|  |  |  |    int     res; | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |    /* input must be positive if b is even */ | 
					
						
							| 
									
										
										
										
											2017-10-15 19:57:12 +02:00
										 |  |  |    if (((b & 1u) == 0u) && (a->sign == MP_NEG)) { | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  |       return MP_VAL; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    if ((res = mp_init(&t1)) != MP_OKAY) { | 
					
						
							|  |  |  |       return res; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    if ((res = mp_init(&t2)) != MP_OKAY) { | 
					
						
							|  |  |  |       goto LBL_T1; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    if ((res = mp_init(&t3)) != MP_OKAY) { | 
					
						
							|  |  |  |       goto LBL_T2; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* if a is negative fudge the sign but keep track */ | 
					
						
							| 
									
										
										
										
											2017-09-20 16:59:43 +02:00
										 |  |  |    a_ = *a; | 
					
						
							|  |  |  |    a_.sign = MP_ZPOS; | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |    /* t2 = 2 */ | 
					
						
							| 
									
										
										
										
											2017-10-15 16:11:09 +02:00
										 |  |  |    mp_set(&t2, 2uL); | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |    do { | 
					
						
							|  |  |  |       /* t1 = t2 */ | 
					
						
							|  |  |  |       if ((res = mp_copy(&t2, &t1)) != MP_OKAY) { | 
					
						
							|  |  |  |          goto LBL_T3; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* t3 = t1**(b-1) */ | 
					
						
							| 
									
										
										
										
											2017-10-15 19:57:12 +02:00
										 |  |  |       if ((res = mp_expt_d_ex(&t1, b - 1u, &t3, fast)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  |          goto LBL_T3; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* numerator */ | 
					
						
							|  |  |  |       /* t2 = t1**b */ | 
					
						
							|  |  |  |       if ((res = mp_mul(&t3, &t1, &t2)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2014-02-14 11:26:07 +01:00
										 |  |  |          goto LBL_T3; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  |       /* t2 = t1**b - a */ | 
					
						
							| 
									
										
										
										
											2017-09-20 16:59:43 +02:00
										 |  |  |       if ((res = mp_sub(&t2, &a_, &t2)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  |          goto LBL_T3; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* denominator */ | 
					
						
							|  |  |  |       /* t3 = t1**(b-1) * b  */ | 
					
						
							|  |  |  |       if ((res = mp_mul_d(&t3, b, &t3)) != MP_OKAY) { | 
					
						
							|  |  |  |          goto LBL_T3; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* t3 = (t1**b - a)/(b * t1**(b-1)) */ | 
					
						
							|  |  |  |       if ((res = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) { | 
					
						
							|  |  |  |          goto LBL_T3; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ((res = mp_sub(&t1, &t3, &t2)) != MP_OKAY) { | 
					
						
							|  |  |  |          goto LBL_T3; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |    }  while (mp_cmp(&t1, &t2) != MP_EQ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* result can be off by a few so check */ | 
					
						
							|  |  |  |    for (;;) { | 
					
						
							|  |  |  |       if ((res = mp_expt_d_ex(&t1, b, &t2, fast)) != MP_OKAY) { | 
					
						
							|  |  |  |          goto LBL_T3; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-20 16:59:43 +02:00
										 |  |  |       if (mp_cmp(&t2, &a_) == MP_GT) { | 
					
						
							| 
									
										
										
										
											2017-10-15 16:11:09 +02:00
										 |  |  |          if ((res = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  |             goto LBL_T3; | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |          break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* set the result */ | 
					
						
							|  |  |  |    mp_exch(&t1, c); | 
					
						
							| 
									
										
										
										
											2014-02-14 11:26:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  |    /* set the sign of the result */ | 
					
						
							| 
									
										
										
										
											2017-09-20 16:59:43 +02:00
										 |  |  |    c->sign = a->sign; | 
					
						
							| 
									
										
										
										
											2014-02-14 11:26:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  |    res = MP_OKAY; | 
					
						
							| 
									
										
										
										
											2014-02-14 11:26:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-28 22:34:46 +02:00
										 |  |  | LBL_T3: | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  |    mp_clear(&t3); | 
					
						
							| 
									
										
										
										
											2017-08-28 22:34:46 +02:00
										 |  |  | LBL_T2: | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  |    mp_clear(&t2); | 
					
						
							| 
									
										
										
										
											2017-08-28 22:34:46 +02:00
										 |  |  | LBL_T1: | 
					
						
							| 
									
										
										
										
											2017-08-30 20:23:46 +02:00
										 |  |  |    mp_clear(&t1); | 
					
						
							|  |  |  |    return res; | 
					
						
							| 
									
										
										
										
											2014-02-14 11:26:07 +01:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-28 16:27:26 +02:00
										 |  |  | /* ref:         $Format:%D$ */ | 
					
						
							|  |  |  | /* git commit:  $Format:%H$ */ | 
					
						
							|  |  |  | /* commit time: $Format:%ai$ */ |