added libtommath-0.35
This commit is contained in:
		
							parent
							
								
									3d0fcaab0a
								
							
						
					
					
						commit
						fdfa2f4f50
					
				
							
								
								
									
										2
									
								
								bn.tex
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								bn.tex
									
									
									
									
									
								
							| @ -49,7 +49,7 @@ | |||||||
| \begin{document} | \begin{document} | ||||||
| \frontmatter | \frontmatter | ||||||
| \pagestyle{empty} | \pagestyle{empty} | ||||||
| \title{LibTomMath User Manual \\ v0.34} | \title{LibTomMath User Manual \\ v0.35} | ||||||
| \author{Tom St Denis \\ tomstdenis@iahu.ca} | \author{Tom St Denis \\ tomstdenis@iahu.ca} | ||||||
| \maketitle | \maketitle | ||||||
| This text, the library and the accompanying textbook are all hereby placed in the public domain.  This book has been  | This text, the library and the accompanying textbook are all hereby placed in the public domain.  This book has been  | ||||||
|  | |||||||
| @ -42,7 +42,7 @@ int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* we need y = |a| */ |   /* we need y = |a| */ | ||||||
|   if ((res = mp_abs (a, &y)) != MP_OKAY) { |   if ((res = mp_mod (a, b, &y)) != MP_OKAY) { | ||||||
|     goto LBL_ERR; |     goto LBL_ERR; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -62,7 +62,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | |||||||
|       tmpx = a->dp + tx; |       tmpx = a->dp + tx; | ||||||
|       tmpy = b->dp + ty; |       tmpy = b->dp + ty; | ||||||
| 
 | 
 | ||||||
|       /* this is the number of times the loop will iterrate, essentially its 
 |       /* this is the number of times the loop will iterrate, essentially 
 | ||||||
|          while (tx++ < a->used && ty-- >= 0) { ... } |          while (tx++ < a->used && ty-- >= 0) { ... } | ||||||
|        */ |        */ | ||||||
|       iy = MIN(a->used-tx, ty+1); |       iy = MIN(a->used-tx, ty+1); | ||||||
| @ -80,16 +80,16 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* store final carry */ |   /* store final carry */ | ||||||
|   W[ix] = _W & MP_MASK; |   W[ix] = (mp_digit)(_W & MP_MASK); | ||||||
| 
 | 
 | ||||||
|   /* setup dest */ |   /* setup dest */ | ||||||
|   olduse  = c->used; |   olduse  = c->used; | ||||||
|   c->used = digs; |   c->used = pa; | ||||||
| 
 | 
 | ||||||
|   { |   { | ||||||
|     register mp_digit *tmpc; |     register mp_digit *tmpc; | ||||||
|     tmpc = c->dp; |     tmpc = c->dp; | ||||||
|     for (ix = 0; ix < digs; ix++) { |     for (ix = 0; ix < pa+1; ix++) { | ||||||
|       /* now extract the previous digit [below the carry] */ |       /* now extract the previous digit [below the carry] */ | ||||||
|       *tmpc++ = W[ix]; |       *tmpc++ = W[ix]; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -71,7 +71,7 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | |||||||
|   } |   } | ||||||
|    |    | ||||||
|   /* store final carry */ |   /* store final carry */ | ||||||
|   W[ix] = _W & MP_MASK; |   W[ix] = (mp_digit)(_W & MP_MASK); | ||||||
| 
 | 
 | ||||||
|   /* setup dest */ |   /* setup dest */ | ||||||
|   olduse  = c->used; |   olduse  = c->used; | ||||||
|  | |||||||
| @ -15,33 +15,14 @@ | |||||||
|  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 |  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /* fast squaring
 |  | ||||||
|  * |  | ||||||
|  * This is the comba method where the columns of the product |  | ||||||
|  * are computed first then the carries are computed.  This |  | ||||||
|  * has the effect of making a very simple inner loop that |  | ||||||
|  * is executed the most |  | ||||||
|  * |  | ||||||
|  * W2 represents the outer products and W the inner. |  | ||||||
|  * |  | ||||||
|  * A further optimizations is made because the inner |  | ||||||
|  * products are of the form "A * B * 2".  The *2 part does |  | ||||||
|  * not need to be computed until the end which is good |  | ||||||
|  * because 64-bit shifts are slow! |  | ||||||
|  * |  | ||||||
|  * Based on Algorithm 14.16 on pp.597 of HAC. |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
| /* the jist of squaring...
 | /* the jist of squaring...
 | ||||||
| 
 |  * you do like mult except the offset of the tmpx [one that  | ||||||
| you do like mult except the offset of the tmpx [one that starts closer to zero] |  * starts closer to zero] can't equal the offset of tmpy.   | ||||||
| can't equal the offset of tmpy.  So basically you set up iy like before then you min it with |  * So basically you set up iy like before then you min it with | ||||||
| (ty-tx) so that it never happens.  You double all those you add in the inner loop |  * (ty-tx) so that it never happens.  You double all those  | ||||||
|  |  * you add in the inner loop | ||||||
| 
 | 
 | ||||||
| After that loop you do the squares and add them in. | After that loop you do the squares and add them in. | ||||||
| 
 |  | ||||||
| Remove W2 and don't memset W |  | ||||||
| 
 |  | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| int fast_s_mp_sqr (mp_int * a, mp_int * b) | int fast_s_mp_sqr (mp_int * a, mp_int * b) | ||||||
| @ -76,7 +57,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) | |||||||
|       tmpx = a->dp + tx; |       tmpx = a->dp + tx; | ||||||
|       tmpy = a->dp + ty; |       tmpy = a->dp + ty; | ||||||
| 
 | 
 | ||||||
|       /* this is the number of times the loop will iterrate, essentially its 
 |       /* this is the number of times the loop will iterrate, essentially
 | ||||||
|          while (tx++ < a->used && ty-- >= 0) { ... } |          while (tx++ < a->used && ty-- >= 0) { ... } | ||||||
|        */ |        */ | ||||||
|       iy = MIN(a->used-tx, ty+1); |       iy = MIN(a->used-tx, ty+1); | ||||||
| @ -101,7 +82,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) | |||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       /* store it */ |       /* store it */ | ||||||
|       W[ix] = _W & MP_MASK; |       W[ix] = (mp_digit)(_W & MP_MASK); | ||||||
| 
 | 
 | ||||||
|       /* make next carry */ |       /* make next carry */ | ||||||
|       W1 = _W >> ((mp_word)DIGIT_BIT); |       W1 = _W >> ((mp_word)DIGIT_BIT); | ||||||
|  | |||||||
| @ -59,6 +59,13 @@ int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) | |||||||
|        if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; } |        if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; } | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  |    /* make sure U3 >= 0 */ | ||||||
|  |    if (u3.sign == MP_NEG) { | ||||||
|  |       mp_neg(&u1, &u1); | ||||||
|  |       mp_neg(&u2, &u2); | ||||||
|  |       mp_neg(&u3, &u3); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    /* copy result out */ |    /* copy result out */ | ||||||
|    if (U1 != NULL) { mp_exch(U1, &u1); } |    if (U1 != NULL) { mp_exch(U1, &u1); } | ||||||
|    if (U2 != NULL) { mp_exch(U2, &u2); } |    if (U2 != NULL) { mp_exch(U2, &u2); } | ||||||
|  | |||||||
| @ -33,8 +33,8 @@ int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* x = a, y = b */ |   /* x = a, y = b */ | ||||||
|   if ((res = mp_copy (a, &x)) != MP_OKAY) { |   if ((res = mp_mod(a, b, &x)) != MP_OKAY) { | ||||||
|     goto LBL_ERR; |       goto LBL_ERR; | ||||||
|   } |   } | ||||||
|   if ((res = mp_copy (b, &y)) != MP_OKAY) { |   if ((res = mp_copy (b, &y)) != MP_OKAY) { | ||||||
|     goto LBL_ERR; |     goto LBL_ERR; | ||||||
|  | |||||||
| @ -28,7 +28,6 @@ int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) | |||||||
|   /* how many bits of last digit does b use */ |   /* how many bits of last digit does b use */ | ||||||
|   bits = mp_count_bits (b) % DIGIT_BIT; |   bits = mp_count_bits (b) % DIGIT_BIT; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|   if (b->used > 1) { |   if (b->used > 1) { | ||||||
|      if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { |      if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { | ||||||
|         return res; |         return res; | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								bn_mp_neg.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								bn_mp_neg.c
									
									
									
									
									
								
							| @ -19,12 +19,18 @@ | |||||||
| int mp_neg (mp_int * a, mp_int * b) | int mp_neg (mp_int * a, mp_int * b) | ||||||
| { | { | ||||||
|   int     res; |   int     res; | ||||||
|   if ((res = mp_copy (a, b)) != MP_OKAY) { |   if (a != b) { | ||||||
|     return res; |      if ((res = mp_copy (a, b)) != MP_OKAY) { | ||||||
|  |         return res; | ||||||
|  |      } | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   if (mp_iszero(b) != MP_YES) { |   if (mp_iszero(b) != MP_YES) { | ||||||
|      b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; |      b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; | ||||||
|  |   } else { | ||||||
|  |      b->sign = MP_ZPOS; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   return MP_OKAY; |   return MP_OKAY; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -35,22 +35,29 @@ int mp_radix_size (mp_int * a, int radix, int *size) | |||||||
|     return MP_VAL; |     return MP_VAL; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* init a copy of the input */ |   if (mp_iszero(a) == MP_YES) { | ||||||
|   if ((res = mp_init_copy (&t, a)) != MP_OKAY) { |      *size = 2; | ||||||
|     return res; |     return MP_OKAY; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* digs is the digit count */ |   /* digs is the digit count */ | ||||||
|   digs = 0; |   digs = 0; | ||||||
| 
 | 
 | ||||||
|   /* if it's negative add one for the sign */ |   /* if it's negative add one for the sign */ | ||||||
|   if (t.sign == MP_NEG) { |   if (a->sign == MP_NEG) { | ||||||
|     ++digs; |     ++digs; | ||||||
|     t.sign = MP_ZPOS; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   /* init a copy of the input */ | ||||||
|  |   if ((res = mp_init_copy (&t, a)) != MP_OKAY) { | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /* force temp to positive */ | ||||||
|  |   t.sign = MP_ZPOS;  | ||||||
|  | 
 | ||||||
|   /* fetch out all of the digits */ |   /* fetch out all of the digits */ | ||||||
|   while (mp_iszero (&t) == 0) { |   while (mp_iszero (&t) == MP_NO) { | ||||||
|     if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { |     if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { | ||||||
|       mp_clear (&t); |       mp_clear (&t); | ||||||
|       return res; |       return res; | ||||||
|  | |||||||
| @ -29,14 +29,14 @@ mp_rand (mp_int * a, int digits) | |||||||
| 
 | 
 | ||||||
|   /* first place a random non-zero digit */ |   /* first place a random non-zero digit */ | ||||||
|   do { |   do { | ||||||
|     d = ((mp_digit) abs (rand ())); |     d = ((mp_digit) abs (rand ())) & MP_MASK; | ||||||
|   } while (d == 0); |   } while (d == 0); | ||||||
| 
 | 
 | ||||||
|   if ((res = mp_add_d (a, d, a)) != MP_OKAY) { |   if ((res = mp_add_d (a, d, a)) != MP_OKAY) { | ||||||
|     return res; |     return res; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   while (digits-- > 0) { |   while (--digits > 0) { | ||||||
|     if ((res = mp_lshd (a, 1)) != MP_OKAY) { |     if ((res = mp_lshd (a, 1)) != MP_OKAY) { | ||||||
|       return res; |       return res; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -39,11 +39,11 @@ int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) | |||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
| #ifdef BN_S_MP_MUL_HIGH_DIGS_C | #ifdef BN_S_MP_MUL_HIGH_DIGS_C | ||||||
|     if ((res = s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) { |     if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { | ||||||
|       goto CLEANUP; |       goto CLEANUP; | ||||||
|     } |     } | ||||||
| #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) | #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) | ||||||
|     if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) { |     if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { | ||||||
|       goto CLEANUP; |       goto CLEANUP; | ||||||
|     } |     } | ||||||
| #else  | #else  | ||||||
|  | |||||||
| @ -17,9 +17,10 @@ | |||||||
| 
 | 
 | ||||||
| /* multiplication using the Toom-Cook 3-way algorithm 
 | /* multiplication using the Toom-Cook 3-way algorithm 
 | ||||||
|  * |  * | ||||||
|  * Much more complicated than Karatsuba but has a lower asymptotic running time of  |  * Much more complicated than Karatsuba but has a lower  | ||||||
|  * O(N**1.464).  This algorithm is only particularly useful on VERY large |  * asymptotic running time of O(N**1.464).  This algorithm is  | ||||||
|  * inputs (we're talking 1000s of digits here...). |  * only particularly useful on VERY large inputs  | ||||||
|  |  * (we're talking 1000s of digits here...). | ||||||
| */ | */ | ||||||
| int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) | int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) | ||||||
| { | { | ||||||
|  | |||||||
| @ -37,7 +37,7 @@ mp_xor (mp_int * a, mp_int * b, mp_int * c) | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   for (ix = 0; ix < px; ix++) { |   for (ix = 0; ix < px; ix++) { | ||||||
| 
 |      t.dp[ix] ^= x->dp[ix]; | ||||||
|   } |   } | ||||||
|   mp_clamp (&t); |   mp_clamp (&t); | ||||||
|   mp_exch (c, &t); |   mp_exch (c, &t); | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								bn_mp_zero.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								bn_mp_zero.c
									
									
									
									
									
								
							| @ -16,11 +16,17 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /* set to zero */ | /* set to zero */ | ||||||
| void | void mp_zero (mp_int * a) | ||||||
| mp_zero (mp_int * a) |  | ||||||
| { | { | ||||||
|  |   int       n; | ||||||
|  |   mp_digit *tmp; | ||||||
|  | 
 | ||||||
|   a->sign = MP_ZPOS; |   a->sign = MP_ZPOS; | ||||||
|   a->used = 0; |   a->used = 0; | ||||||
|   memset (a->dp, 0, sizeof (mp_digit) * a->alloc); | 
 | ||||||
|  |   tmp = a->dp; | ||||||
|  |   for (n = 0; n < a->alloc; n++) { | ||||||
|  |      *tmp++ = 0; | ||||||
|  |   } | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -19,8 +19,7 @@ | |||||||
|  * HAC pp. 595, Algorithm 14.12  Modified so you can control how  |  * HAC pp. 595, Algorithm 14.12  Modified so you can control how  | ||||||
|  * many digits of output are created. |  * many digits of output are created. | ||||||
|  */ |  */ | ||||||
| int | int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | ||||||
| s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) |  | ||||||
| { | { | ||||||
|   mp_int  t; |   mp_int  t; | ||||||
|   int     res, pa, pb, ix, iy; |   int     res, pa, pb, ix, iy; | ||||||
|  | |||||||
| @ -16,8 +16,7 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ | /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ | ||||||
| int | int s_mp_sqr (mp_int * a, mp_int * b) | ||||||
| s_mp_sqr (mp_int * a, mp_int * b) |  | ||||||
| { | { | ||||||
|   mp_int  t; |   mp_int  t; | ||||||
|   int     res, ix, iy, pa; |   int     res, ix, iy, pa; | ||||||
|  | |||||||
							
								
								
									
										887
									
								
								callgraph.txt
									
									
									
									
									
								
							
							
						
						
									
										887
									
								
								callgraph.txt
									
									
									
									
									
								
							| @ -907,7 +907,64 @@ BN_MP_EXPTMOD_C | |||||||
| |   |   |   +--->BN_MP_CLEAR_C | |   |   |   +--->BN_MP_CLEAR_C | ||||||
| |   |   +--->BN_MP_COPY_C | |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   +--->BN_MP_GROW_C | |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   +--->BN_MP_ABS_C | |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   +--->BN_MP_SET_C | ||||||
|  | |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_DIV_2D_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_MOD_2D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   +--->BN_MP_INIT_COPY_C | ||||||
|  | |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   +--->BN_MP_SET_C | |   |   +--->BN_MP_SET_C | ||||||
| |   |   |   +--->BN_MP_ZERO_C | |   |   |   +--->BN_MP_ZERO_C | ||||||
| |   |   +--->BN_MP_DIV_2_C | |   |   +--->BN_MP_DIV_2_C | ||||||
| @ -938,6 +995,66 @@ BN_MP_EXPTMOD_C | |||||||
| |   +--->BN_MP_INVMOD_SLOW_C | |   +--->BN_MP_INVMOD_SLOW_C | ||||||
| |   |   +--->BN_MP_INIT_MULTI_C | |   |   +--->BN_MP_INIT_MULTI_C | ||||||
| |   |   |   +--->BN_MP_CLEAR_C | |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   +--->BN_MP_COPY_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   +--->BN_MP_SET_C | ||||||
|  | |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_DIV_2D_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_MOD_2D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   +--->BN_MP_INIT_COPY_C | ||||||
|  | |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   +--->BN_MP_COPY_C | |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   +--->BN_MP_GROW_C | |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   +--->BN_MP_SET_C | |   |   +--->BN_MP_SET_C | ||||||
| @ -1874,7 +1991,64 @@ BN_MP_PRIME_FERMAT_C | |||||||
| |   |   |   |   +--->BN_MP_CLEAR_C | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
| |   |   |   +--->BN_MP_COPY_C | |   |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   +--->BN_MP_ABS_C | |   |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_SET_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_DIV_2D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_MOD_2D_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_INIT_COPY_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   |   +--->BN_MP_SET_C | |   |   |   +--->BN_MP_SET_C | ||||||
| |   |   |   |   +--->BN_MP_ZERO_C | |   |   |   |   +--->BN_MP_ZERO_C | ||||||
| |   |   |   +--->BN_MP_DIV_2_C | |   |   |   +--->BN_MP_DIV_2_C | ||||||
| @ -1904,6 +2078,66 @@ BN_MP_PRIME_FERMAT_C | |||||||
| |   |   +--->BN_MP_INVMOD_SLOW_C | |   |   +--->BN_MP_INVMOD_SLOW_C | ||||||
| |   |   |   +--->BN_MP_INIT_MULTI_C | |   |   |   +--->BN_MP_INIT_MULTI_C | ||||||
| |   |   |   |   +--->BN_MP_CLEAR_C | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_COPY_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_SET_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_DIV_2D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_MOD_2D_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_INIT_COPY_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   |   +--->BN_MP_COPY_C | |   |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   +--->BN_MP_SET_C | |   |   |   +--->BN_MP_SET_C | ||||||
| @ -3111,7 +3345,65 @@ BN_MP_INVMOD_C | |||||||
| |   |   +--->BN_MP_CLEAR_C | |   |   +--->BN_MP_CLEAR_C | ||||||
| |   +--->BN_MP_COPY_C | |   +--->BN_MP_COPY_C | ||||||
| |   |   +--->BN_MP_GROW_C | |   |   +--->BN_MP_GROW_C | ||||||
| |   +--->BN_MP_ABS_C | |   +--->BN_MP_MOD_C | ||||||
|  | |   |   +--->BN_MP_INIT_C | ||||||
|  | |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   +--->BN_MP_SET_C | ||||||
|  | |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_DIV_2D_C | ||||||
|  | |   |   |   |   +--->BN_MP_MOD_2D_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   +--->BN_MP_INIT_COPY_C | ||||||
|  | |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_EXCH_C | ||||||
| |   +--->BN_MP_SET_C | |   +--->BN_MP_SET_C | ||||||
| |   |   +--->BN_MP_ZERO_C | |   |   +--->BN_MP_ZERO_C | ||||||
| |   +--->BN_MP_DIV_2_C | |   +--->BN_MP_DIV_2_C | ||||||
| @ -3143,6 +3435,67 @@ BN_MP_INVMOD_C | |||||||
| |   +--->BN_MP_INIT_MULTI_C | |   +--->BN_MP_INIT_MULTI_C | ||||||
| |   |   +--->BN_MP_INIT_C | |   |   +--->BN_MP_INIT_C | ||||||
| |   |   +--->BN_MP_CLEAR_C | |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   +--->BN_MP_MOD_C | ||||||
|  | |   |   +--->BN_MP_INIT_C | ||||||
|  | |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   +--->BN_MP_COPY_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   +--->BN_MP_SET_C | ||||||
|  | |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_DIV_2D_C | ||||||
|  | |   |   |   |   +--->BN_MP_MOD_2D_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   +--->BN_MP_INIT_COPY_C | ||||||
|  | |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_EXCH_C | ||||||
| |   +--->BN_MP_COPY_C | |   +--->BN_MP_COPY_C | ||||||
| |   |   +--->BN_MP_GROW_C | |   |   +--->BN_MP_GROW_C | ||||||
| |   +--->BN_MP_SET_C | |   +--->BN_MP_SET_C | ||||||
| @ -3195,7 +3548,65 @@ BN_FAST_MP_INVMOD_C | |||||||
| |   +--->BN_MP_CLEAR_C | |   +--->BN_MP_CLEAR_C | ||||||
| +--->BN_MP_COPY_C | +--->BN_MP_COPY_C | ||||||
| |   +--->BN_MP_GROW_C | |   +--->BN_MP_GROW_C | ||||||
| +--->BN_MP_ABS_C | +--->BN_MP_MOD_C | ||||||
|  | |   +--->BN_MP_INIT_C | ||||||
|  | |   +--->BN_MP_DIV_C | ||||||
|  | |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   +--->BN_MP_SET_C | ||||||
|  | |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_DIV_2D_C | ||||||
|  | |   |   |   +--->BN_MP_MOD_2D_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   +--->BN_MP_INIT_COPY_C | ||||||
|  | |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   +--->BN_MP_CLEAR_C | ||||||
|  | |   +--->BN_MP_ADD_C | ||||||
|  | |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   +--->BN_MP_EXCH_C | ||||||
| +--->BN_MP_SET_C | +--->BN_MP_SET_C | ||||||
| |   +--->BN_MP_ZERO_C | |   +--->BN_MP_ZERO_C | ||||||
| +--->BN_MP_DIV_2_C | +--->BN_MP_DIV_2_C | ||||||
| @ -3683,7 +4094,55 @@ BN_MP_PRIME_RANDOM_EX_C | |||||||
| |   |   |   |   |   |   +--->BN_MP_CLEAR_C | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
| |   |   |   |   |   +--->BN_MP_COPY_C | |   |   |   |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   |   |   +--->BN_MP_ABS_C | |   |   |   |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   |   |   |   +--->BN_MP_DIV_2_C | |   |   |   |   |   +--->BN_MP_DIV_2_C | ||||||
| |   |   |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   |   |   |   +--->BN_MP_CLAMP_C | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
| @ -3711,6 +4170,57 @@ BN_MP_PRIME_RANDOM_EX_C | |||||||
| |   |   |   |   +--->BN_MP_INVMOD_SLOW_C | |   |   |   |   +--->BN_MP_INVMOD_SLOW_C | ||||||
| |   |   |   |   |   +--->BN_MP_INIT_MULTI_C | |   |   |   |   |   +--->BN_MP_INIT_MULTI_C | ||||||
| |   |   |   |   |   |   +--->BN_MP_CLEAR_C | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_COPY_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   |   |   |   +--->BN_MP_COPY_C | |   |   |   |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   |   |   +--->BN_MP_DIV_2_C | |   |   |   |   |   +--->BN_MP_DIV_2_C | ||||||
| @ -5057,7 +5567,55 @@ BN_MP_PRIME_IS_PRIME_C | |||||||
| |   |   |   |   |   +--->BN_MP_CLEAR_C | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
| |   |   |   |   +--->BN_MP_COPY_C | |   |   |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   |   +--->BN_MP_ABS_C | |   |   |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   |   |   +--->BN_MP_DIV_2_C | |   |   |   |   +--->BN_MP_DIV_2_C | ||||||
| |   |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   |   |   +--->BN_MP_CLAMP_C | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
| @ -5085,6 +5643,57 @@ BN_MP_PRIME_IS_PRIME_C | |||||||
| |   |   |   +--->BN_MP_INVMOD_SLOW_C | |   |   |   +--->BN_MP_INVMOD_SLOW_C | ||||||
| |   |   |   |   +--->BN_MP_INIT_MULTI_C | |   |   |   |   +--->BN_MP_INIT_MULTI_C | ||||||
| |   |   |   |   |   +--->BN_MP_CLEAR_C | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_COPY_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   |   |   +--->BN_MP_COPY_C | |   |   |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   |   +--->BN_MP_DIV_2_C | |   |   |   |   +--->BN_MP_DIV_2_C | ||||||
| @ -6894,7 +7503,55 @@ BN_MP_PRIME_NEXT_PRIME_C | |||||||
| |   |   |   |   |   +--->BN_MP_CLEAR_C | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
| |   |   |   |   +--->BN_MP_COPY_C | |   |   |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   |   +--->BN_MP_ABS_C | |   |   |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   |   |   +--->BN_MP_DIV_2_C | |   |   |   |   +--->BN_MP_DIV_2_C | ||||||
| |   |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   |   |   +--->BN_MP_CLAMP_C | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
| @ -6922,6 +7579,57 @@ BN_MP_PRIME_NEXT_PRIME_C | |||||||
| |   |   |   +--->BN_MP_INVMOD_SLOW_C | |   |   |   +--->BN_MP_INVMOD_SLOW_C | ||||||
| |   |   |   |   +--->BN_MP_INIT_MULTI_C | |   |   |   |   +--->BN_MP_INIT_MULTI_C | ||||||
| |   |   |   |   |   +--->BN_MP_CLEAR_C | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_COPY_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   |   |   +--->BN_MP_COPY_C | |   |   |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   |   +--->BN_MP_DIV_2_C | |   |   |   |   +--->BN_MP_DIV_2_C | ||||||
| @ -7898,6 +8606,67 @@ BN_MP_INVMOD_SLOW_C | |||||||
| +--->BN_MP_INIT_MULTI_C | +--->BN_MP_INIT_MULTI_C | ||||||
| |   +--->BN_MP_INIT_C | |   +--->BN_MP_INIT_C | ||||||
| |   +--->BN_MP_CLEAR_C | |   +--->BN_MP_CLEAR_C | ||||||
|  | +--->BN_MP_MOD_C | ||||||
|  | |   +--->BN_MP_INIT_C | ||||||
|  | |   +--->BN_MP_DIV_C | ||||||
|  | |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   +--->BN_MP_COPY_C | ||||||
|  | |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   +--->BN_MP_SET_C | ||||||
|  | |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_DIV_2D_C | ||||||
|  | |   |   |   +--->BN_MP_MOD_2D_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   +--->BN_MP_INIT_COPY_C | ||||||
|  | |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   +--->BN_MP_CLEAR_C | ||||||
|  | |   +--->BN_MP_ADD_C | ||||||
|  | |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   +--->BN_MP_EXCH_C | ||||||
| +--->BN_MP_COPY_C | +--->BN_MP_COPY_C | ||||||
| |   +--->BN_MP_GROW_C | |   +--->BN_MP_GROW_C | ||||||
| +--->BN_MP_SET_C | +--->BN_MP_SET_C | ||||||
| @ -9817,6 +10586,7 @@ BN_MP_EXTEUCLID_C | |||||||
| |   +--->BN_S_MP_SUB_C | |   +--->BN_S_MP_SUB_C | ||||||
| |   |   +--->BN_MP_GROW_C | |   |   +--->BN_MP_GROW_C | ||||||
| |   |   +--->BN_MP_CLAMP_C | |   |   +--->BN_MP_CLAMP_C | ||||||
|  | +--->BN_MP_NEG_C | ||||||
| +--->BN_MP_EXCH_C | +--->BN_MP_EXCH_C | ||||||
| +--->BN_MP_CLEAR_MULTI_C | +--->BN_MP_CLEAR_MULTI_C | ||||||
| |   +--->BN_MP_CLEAR_C | |   +--->BN_MP_CLEAR_C | ||||||
| @ -10024,7 +10794,56 @@ BN_MP_PRIME_MILLER_RABIN_C | |||||||
| |   |   |   |   +--->BN_MP_CLEAR_C | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
| |   |   |   +--->BN_MP_COPY_C | |   |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   +--->BN_MP_ABS_C | |   |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_SET_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   |   +--->BN_MP_SET_C | |   |   |   +--->BN_MP_SET_C | ||||||
| |   |   |   |   +--->BN_MP_ZERO_C | |   |   |   |   +--->BN_MP_ZERO_C | ||||||
| |   |   |   +--->BN_MP_DIV_2_C | |   |   |   +--->BN_MP_DIV_2_C | ||||||
| @ -10054,6 +10873,58 @@ BN_MP_PRIME_MILLER_RABIN_C | |||||||
| |   |   +--->BN_MP_INVMOD_SLOW_C | |   |   +--->BN_MP_INVMOD_SLOW_C | ||||||
| |   |   |   +--->BN_MP_INIT_MULTI_C | |   |   |   +--->BN_MP_INIT_MULTI_C | ||||||
| |   |   |   |   +--->BN_MP_CLEAR_C | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   +--->BN_MP_MOD_C | ||||||
|  | |   |   |   |   +--->BN_MP_DIV_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_COPY_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ZERO_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_SET_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_COUNT_BITS_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ABS_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_MUL_2D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_EXCH_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_INIT_SIZE_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_LSHD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_RSHD_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_MUL_D_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_CLEAR_C | ||||||
|  | |   |   |   |   +--->BN_MP_ADD_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_ADD_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   |   +--->BN_MP_CMP_MAG_C | ||||||
|  | |   |   |   |   |   +--->BN_S_MP_SUB_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_GROW_C | ||||||
|  | |   |   |   |   |   |   +--->BN_MP_CLAMP_C | ||||||
|  | |   |   |   |   +--->BN_MP_EXCH_C | ||||||
| |   |   |   +--->BN_MP_COPY_C | |   |   |   +--->BN_MP_COPY_C | ||||||
| |   |   |   |   +--->BN_MP_GROW_C | |   |   |   |   +--->BN_MP_GROW_C | ||||||
| |   |   |   +--->BN_MP_SET_C | |   |   |   +--->BN_MP_SET_C | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								changes.txt
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								changes.txt
									
									
									
									
									
								
							| @ -1,3 +1,14 @@ | |||||||
|  | March 12th, 2005 | ||||||
|  | v0.35  -- Stupid XOR function missing line again... oops. | ||||||
|  |        -- Fixed bug in invmod not handling negative inputs correctly [Wolfgang Ehrhardt] | ||||||
|  |        -- Made exteuclid always give positive u3 output...[ Wolfgang Ehrhardt ] | ||||||
|  |        -- [Wolfgang Ehrhardt] Suggested a fix for mp_reduce() which avoided underruns.  ;-) | ||||||
|  |        -- mp_rand() would emit one too many digits and it was possible to get a 0 out of it ... oops | ||||||
|  |        -- Added montgomery to the testing to make sure it handles 1..10 digit moduli correctly | ||||||
|  |        -- Fixed bug in comba that would lead to possible erroneous outputs when "pa < digs"  | ||||||
|  |        -- Fixed bug in mp_toradix_size for "0" [Kevin Kenny] | ||||||
|  |        -- Updated chapters 1-5 of the textbook ;-) It now talks about the new comba code! | ||||||
|  | 
 | ||||||
| February 12th, 2005 | February 12th, 2005 | ||||||
| v0.34  -- Fixed two more small errors in mp_prime_random_ex() | v0.34  -- Fixed two more small errors in mp_prime_random_ex() | ||||||
|        -- Fixed overflow in mp_mul_d() [Kevin Kenny] |        -- Fixed overflow in mp_mul_d() [Kevin Kenny] | ||||||
|  | |||||||
							
								
								
									
										41
									
								
								demo/demo.c
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								demo/demo.c
									
									
									
									
									
								
							| @ -56,6 +56,7 @@ int main(void) | |||||||
|       gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n, t; |       gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n, t; | ||||||
|    unsigned rr; |    unsigned rr; | ||||||
|    int i, n, err, cnt, ix, old_kara_m, old_kara_s; |    int i, n, err, cnt, ix, old_kara_m, old_kara_s; | ||||||
|  |    mp_digit mp; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|    mp_init(&a); |    mp_init(&a); | ||||||
| @ -68,6 +69,40 @@ int main(void) | |||||||
|    srand(time(NULL)); |    srand(time(NULL)); | ||||||
| 
 | 
 | ||||||
| #if 0 | #if 0 | ||||||
|  |    // test montgomery 
 | ||||||
|  |    printf("Testing montgomery...\n"); | ||||||
|  |    for (i = 1; i < 10; i++) { | ||||||
|  |       printf("Testing digit size: %d\n", i); | ||||||
|  |       for (n = 0; n < 1000; n++) { | ||||||
|  |          mp_rand(&a, i); | ||||||
|  |          a.dp[0] |= 1; | ||||||
|  | 
 | ||||||
|  |          // let's see if R is right
 | ||||||
|  |          mp_montgomery_calc_normalization(&b, &a); | ||||||
|  |          mp_montgomery_setup(&a, &mp); | ||||||
|  | 
 | ||||||
|  |          // now test a random reduction 
 | ||||||
|  |          for (ix = 0; ix < 100; ix++) { | ||||||
|  |              mp_rand(&c, 1 + abs(rand()) % (2*i)); | ||||||
|  |              mp_copy(&c, &d); | ||||||
|  |              mp_copy(&c, &e); | ||||||
|  | 
 | ||||||
|  |              mp_mod(&d, &a, &d); | ||||||
|  |              mp_montgomery_reduce(&c, &a, mp); | ||||||
|  |              mp_mulmod(&c, &b, &a, &c); | ||||||
|  | 
 | ||||||
|  |              if (mp_cmp(&c, &d) != MP_EQ) {  | ||||||
|  | printf("d = e mod a, c = e MOD a\n"); | ||||||
|  | mp_todecimal(&a, buf); printf("a = %s\n", buf); | ||||||
|  | mp_todecimal(&e, buf); printf("e = %s\n", buf); | ||||||
|  | mp_todecimal(&d, buf); printf("d = %s\n", buf); | ||||||
|  | mp_todecimal(&c, buf); printf("c = %s\n", buf); | ||||||
|  | printf("compare no compare!\n"); exit(EXIT_FAILURE); } | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |    printf("done\n"); | ||||||
|  | 
 | ||||||
|    // test mp_get_int
 |    // test mp_get_int
 | ||||||
|    printf("Testing: mp_get_int\n"); |    printf("Testing: mp_get_int\n"); | ||||||
|    for (i = 0; i < 1000; ++i) { |    for (i = 0; i < 1000; ++i) { | ||||||
| @ -139,7 +174,7 @@ int main(void) | |||||||
|    printf("\n\n"); |    printf("\n\n"); | ||||||
| 
 | 
 | ||||||
|    /* test for size */ |    /* test for size */ | ||||||
|    for (ix = 10; ix < 256; ix++) { |    for (ix = 10; ix < 128; ix++) { | ||||||
|       printf("Testing (not safe-prime): %9d bits    \r", ix); |       printf("Testing (not safe-prime): %9d bits    \r", ix); | ||||||
|       fflush(stdout); |       fflush(stdout); | ||||||
|       err = |       err = | ||||||
| @ -156,7 +191,7 @@ int main(void) | |||||||
|       } |       } | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    for (ix = 16; ix < 256; ix++) { |    for (ix = 16; ix < 128; ix++) { | ||||||
|       printf("Testing (   safe-prime): %9d bits    \r", ix); |       printf("Testing (   safe-prime): %9d bits    \r", ix); | ||||||
|       fflush(stdout); |       fflush(stdout); | ||||||
|       err = |       err = | ||||||
| @ -235,7 +270,7 @@ int main(void) | |||||||
| 	 mp_rand(&b, (cnt / DIGIT_BIT + 1) * 2); | 	 mp_rand(&b, (cnt / DIGIT_BIT + 1) * 2); | ||||||
| 	 mp_copy(&c, &b); | 	 mp_copy(&c, &b); | ||||||
| 	 mp_mod(&c, &a, &c); | 	 mp_mod(&c, &a, &c); | ||||||
| 	 mp_reduce_2k(&b, &a, 1); | 	 mp_reduce_2k(&b, &a, 2); | ||||||
| 	 if (mp_cmp(&c, &b)) { | 	 if (mp_cmp(&c, &b)) { | ||||||
| 	    printf("FAILED\n"); | 	    printf("FAILED\n"); | ||||||
| 	    exit(0); | 	    exit(0); | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								makefile
									
									
									
									
									
								
							| @ -3,7 +3,7 @@ | |||||||
| #Tom St Denis
 | #Tom St Denis
 | ||||||
| 
 | 
 | ||||||
| #version of library 
 | #version of library 
 | ||||||
| VERSION=0.34 | VERSION=0.35 | ||||||
| 
 | 
 | ||||||
| CFLAGS  +=  -I./ -Wall -W -Wshadow -Wsign-compare | CFLAGS  +=  -I./ -Wall -W -Wshadow -Wsign-compare | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| #Makefile for GCC | #Makefile for GCC | ||||||
| # | # | ||||||
| #Tom St Denis | #Tom St Denis | ||||||
| VERSION=0:34 | VERSION=0:35 | ||||||
| 
 | 
 | ||||||
| CC = libtool --mode=compile gcc | CC = libtool --mode=compile gcc | ||||||
| CFLAGS  +=  -I./ -Wall -W -Wshadow -Wsign-compare | CFLAGS  +=  -I./ -Wall -W -Wshadow -Wsign-compare | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								poster.pdf
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								poster.pdf
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										121
									
								
								pre_gen/mpi.c
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								pre_gen/mpi.c
									
									
									
									
									
								
							| @ -90,7 +90,7 @@ int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* we need y = |a| */ |   /* we need y = |a| */ | ||||||
|   if ((res = mp_abs (a, &y)) != MP_OKAY) { |   if ((res = mp_mod (a, b, &y)) != MP_OKAY) { | ||||||
|     goto LBL_ERR; |     goto LBL_ERR; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -430,7 +430,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | |||||||
|       tmpx = a->dp + tx; |       tmpx = a->dp + tx; | ||||||
|       tmpy = b->dp + ty; |       tmpy = b->dp + ty; | ||||||
| 
 | 
 | ||||||
|       /* this is the number of times the loop will iterrate, essentially its 
 |       /* this is the number of times the loop will iterrate, essentially 
 | ||||||
|          while (tx++ < a->used && ty-- >= 0) { ... } |          while (tx++ < a->used && ty-- >= 0) { ... } | ||||||
|        */ |        */ | ||||||
|       iy = MIN(a->used-tx, ty+1); |       iy = MIN(a->used-tx, ty+1); | ||||||
| @ -448,16 +448,16 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* store final carry */ |   /* store final carry */ | ||||||
|   W[ix] = _W & MP_MASK; |   W[ix] = (mp_digit)(_W & MP_MASK); | ||||||
| 
 | 
 | ||||||
|   /* setup dest */ |   /* setup dest */ | ||||||
|   olduse  = c->used; |   olduse  = c->used; | ||||||
|   c->used = digs; |   c->used = pa; | ||||||
| 
 | 
 | ||||||
|   { |   { | ||||||
|     register mp_digit *tmpc; |     register mp_digit *tmpc; | ||||||
|     tmpc = c->dp; |     tmpc = c->dp; | ||||||
|     for (ix = 0; ix < digs; ix++) { |     for (ix = 0; ix < pa+1; ix++) { | ||||||
|       /* now extract the previous digit [below the carry] */ |       /* now extract the previous digit [below the carry] */ | ||||||
|       *tmpc++ = W[ix]; |       *tmpc++ = W[ix]; | ||||||
|     } |     } | ||||||
| @ -548,7 +548,7 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | |||||||
|   } |   } | ||||||
|    |    | ||||||
|   /* store final carry */ |   /* store final carry */ | ||||||
|   W[ix] = _W & MP_MASK; |   W[ix] = (mp_digit)(_W & MP_MASK); | ||||||
| 
 | 
 | ||||||
|   /* setup dest */ |   /* setup dest */ | ||||||
|   olduse  = c->used; |   olduse  = c->used; | ||||||
| @ -593,33 +593,14 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | |||||||
|  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 |  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
 | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /* fast squaring
 |  | ||||||
|  * |  | ||||||
|  * This is the comba method where the columns of the product |  | ||||||
|  * are computed first then the carries are computed.  This |  | ||||||
|  * has the effect of making a very simple inner loop that |  | ||||||
|  * is executed the most |  | ||||||
|  * |  | ||||||
|  * W2 represents the outer products and W the inner. |  | ||||||
|  * |  | ||||||
|  * A further optimizations is made because the inner |  | ||||||
|  * products are of the form "A * B * 2".  The *2 part does |  | ||||||
|  * not need to be computed until the end which is good |  | ||||||
|  * because 64-bit shifts are slow! |  | ||||||
|  * |  | ||||||
|  * Based on Algorithm 14.16 on pp.597 of HAC. |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
| /* the jist of squaring...
 | /* the jist of squaring...
 | ||||||
| 
 |  * you do like mult except the offset of the tmpx [one that  | ||||||
| you do like mult except the offset of the tmpx [one that starts closer to zero] |  * starts closer to zero] can't equal the offset of tmpy.   | ||||||
| can't equal the offset of tmpy.  So basically you set up iy like before then you min it with |  * So basically you set up iy like before then you min it with | ||||||
| (ty-tx) so that it never happens.  You double all those you add in the inner loop |  * (ty-tx) so that it never happens.  You double all those  | ||||||
|  |  * you add in the inner loop | ||||||
| 
 | 
 | ||||||
| After that loop you do the squares and add them in. | After that loop you do the squares and add them in. | ||||||
| 
 |  | ||||||
| Remove W2 and don't memset W |  | ||||||
| 
 |  | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| int fast_s_mp_sqr (mp_int * a, mp_int * b) | int fast_s_mp_sqr (mp_int * a, mp_int * b) | ||||||
| @ -654,7 +635,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) | |||||||
|       tmpx = a->dp + tx; |       tmpx = a->dp + tx; | ||||||
|       tmpy = a->dp + ty; |       tmpy = a->dp + ty; | ||||||
| 
 | 
 | ||||||
|       /* this is the number of times the loop will iterrate, essentially its 
 |       /* this is the number of times the loop will iterrate, essentially
 | ||||||
|          while (tx++ < a->used && ty-- >= 0) { ... } |          while (tx++ < a->used && ty-- >= 0) { ... } | ||||||
|        */ |        */ | ||||||
|       iy = MIN(a->used-tx, ty+1); |       iy = MIN(a->used-tx, ty+1); | ||||||
| @ -679,7 +660,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) | |||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       /* store it */ |       /* store it */ | ||||||
|       W[ix] = _W & MP_MASK; |       W[ix] = (mp_digit)(_W & MP_MASK); | ||||||
| 
 | 
 | ||||||
|       /* make next carry */ |       /* make next carry */ | ||||||
|       W1 = _W >> ((mp_word)DIGIT_BIT); |       W1 = _W >> ((mp_word)DIGIT_BIT); | ||||||
| @ -2890,6 +2871,13 @@ int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) | |||||||
|        if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; } |        if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; } | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|  |    /* make sure U3 >= 0 */ | ||||||
|  |    if (u3.sign == MP_NEG) { | ||||||
|  |       mp_neg(&u1, &u1); | ||||||
|  |       mp_neg(&u2, &u2); | ||||||
|  |       mp_neg(&u3, &u3); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    /* copy result out */ |    /* copy result out */ | ||||||
|    if (U1 != NULL) { mp_exch(U1, &u1); } |    if (U1 != NULL) { mp_exch(U1, &u1); } | ||||||
|    if (U2 != NULL) { mp_exch(U2, &u2); } |    if (U2 != NULL) { mp_exch(U2, &u2); } | ||||||
| @ -3564,8 +3552,8 @@ int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* x = a, y = b */ |   /* x = a, y = b */ | ||||||
|   if ((res = mp_copy (a, &x)) != MP_OKAY) { |   if ((res = mp_mod(a, b, &x)) != MP_OKAY) { | ||||||
|     goto LBL_ERR; |       goto LBL_ERR; | ||||||
|   } |   } | ||||||
|   if ((res = mp_copy (b, &y)) != MP_OKAY) { |   if ((res = mp_copy (b, &y)) != MP_OKAY) { | ||||||
|     goto LBL_ERR; |     goto LBL_ERR; | ||||||
| @ -4493,7 +4481,6 @@ int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) | |||||||
|   /* how many bits of last digit does b use */ |   /* how many bits of last digit does b use */ | ||||||
|   bits = mp_count_bits (b) % DIGIT_BIT; |   bits = mp_count_bits (b) % DIGIT_BIT; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|   if (b->used > 1) { |   if (b->used > 1) { | ||||||
|      if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { |      if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { | ||||||
|         return res; |         return res; | ||||||
| @ -5206,12 +5193,18 @@ LBL_T1:mp_clear (&t1); | |||||||
| int mp_neg (mp_int * a, mp_int * b) | int mp_neg (mp_int * a, mp_int * b) | ||||||
| { | { | ||||||
|   int     res; |   int     res; | ||||||
|   if ((res = mp_copy (a, b)) != MP_OKAY) { |   if (a != b) { | ||||||
|     return res; |      if ((res = mp_copy (a, b)) != MP_OKAY) { | ||||||
|  |         return res; | ||||||
|  |      } | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   if (mp_iszero(b) != MP_YES) { |   if (mp_iszero(b) != MP_YES) { | ||||||
|      b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; |      b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; | ||||||
|  |   } else { | ||||||
|  |      b->sign = MP_ZPOS; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|   return MP_OKAY; |   return MP_OKAY; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @ -5953,22 +5946,29 @@ int mp_radix_size (mp_int * a, int radix, int *size) | |||||||
|     return MP_VAL; |     return MP_VAL; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* init a copy of the input */ |   if (mp_iszero(a) == MP_YES) { | ||||||
|   if ((res = mp_init_copy (&t, a)) != MP_OKAY) { |      *size = 2; | ||||||
|     return res; |     return MP_OKAY; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* digs is the digit count */ |   /* digs is the digit count */ | ||||||
|   digs = 0; |   digs = 0; | ||||||
| 
 | 
 | ||||||
|   /* if it's negative add one for the sign */ |   /* if it's negative add one for the sign */ | ||||||
|   if (t.sign == MP_NEG) { |   if (a->sign == MP_NEG) { | ||||||
|     ++digs; |     ++digs; | ||||||
|     t.sign = MP_ZPOS; |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   /* init a copy of the input */ | ||||||
|  |   if ((res = mp_init_copy (&t, a)) != MP_OKAY) { | ||||||
|  |     return res; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /* force temp to positive */ | ||||||
|  |   t.sign = MP_ZPOS;  | ||||||
|  | 
 | ||||||
|   /* fetch out all of the digits */ |   /* fetch out all of the digits */ | ||||||
|   while (mp_iszero (&t) == 0) { |   while (mp_iszero (&t) == MP_NO) { | ||||||
|     if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { |     if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { | ||||||
|       mp_clear (&t); |       mp_clear (&t); | ||||||
|       return res; |       return res; | ||||||
| @ -6042,14 +6042,14 @@ mp_rand (mp_int * a, int digits) | |||||||
| 
 | 
 | ||||||
|   /* first place a random non-zero digit */ |   /* first place a random non-zero digit */ | ||||||
|   do { |   do { | ||||||
|     d = ((mp_digit) abs (rand ())); |     d = ((mp_digit) abs (rand ())) & MP_MASK; | ||||||
|   } while (d == 0); |   } while (d == 0); | ||||||
| 
 | 
 | ||||||
|   if ((res = mp_add_d (a, d, a)) != MP_OKAY) { |   if ((res = mp_add_d (a, d, a)) != MP_OKAY) { | ||||||
|     return res; |     return res; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   while (digits-- > 0) { |   while (--digits > 0) { | ||||||
|     if ((res = mp_lshd (a, 1)) != MP_OKAY) { |     if ((res = mp_lshd (a, 1)) != MP_OKAY) { | ||||||
|       return res; |       return res; | ||||||
|     } |     } | ||||||
| @ -6287,11 +6287,11 @@ int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) | |||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
| #ifdef BN_S_MP_MUL_HIGH_DIGS_C | #ifdef BN_S_MP_MUL_HIGH_DIGS_C | ||||||
|     if ((res = s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) { |     if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { | ||||||
|       goto CLEANUP; |       goto CLEANUP; | ||||||
|     } |     } | ||||||
| #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) | #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) | ||||||
|     if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) { |     if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { | ||||||
|       goto CLEANUP; |       goto CLEANUP; | ||||||
|     } |     } | ||||||
| #else  | #else  | ||||||
| @ -7433,9 +7433,10 @@ int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen) | |||||||
| 
 | 
 | ||||||
| /* multiplication using the Toom-Cook 3-way algorithm 
 | /* multiplication using the Toom-Cook 3-way algorithm 
 | ||||||
|  * |  * | ||||||
|  * Much more complicated than Karatsuba but has a lower asymptotic running time of  |  * Much more complicated than Karatsuba but has a lower  | ||||||
|  * O(N**1.464).  This algorithm is only particularly useful on VERY large |  * asymptotic running time of O(N**1.464).  This algorithm is  | ||||||
|  * inputs (we're talking 1000s of digits here...). |  * only particularly useful on VERY large inputs  | ||||||
|  |  * (we're talking 1000s of digits here...). | ||||||
| */ | */ | ||||||
| int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) | int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) | ||||||
| { | { | ||||||
| @ -8154,7 +8155,7 @@ mp_xor (mp_int * a, mp_int * b, mp_int * c) | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   for (ix = 0; ix < px; ix++) { |   for (ix = 0; ix < px; ix++) { | ||||||
| 
 |      t.dp[ix] ^= x->dp[ix]; | ||||||
|   } |   } | ||||||
|   mp_clamp (&t); |   mp_clamp (&t); | ||||||
|   mp_exch (c, &t); |   mp_exch (c, &t); | ||||||
| @ -8184,12 +8185,18 @@ mp_xor (mp_int * a, mp_int * b, mp_int * c) | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /* set to zero */ | /* set to zero */ | ||||||
| void | void mp_zero (mp_int * a) | ||||||
| mp_zero (mp_int * a) |  | ||||||
| { | { | ||||||
|  |   int       n; | ||||||
|  |   mp_digit *tmp; | ||||||
|  | 
 | ||||||
|   a->sign = MP_ZPOS; |   a->sign = MP_ZPOS; | ||||||
|   a->used = 0; |   a->used = 0; | ||||||
|   memset (a->dp, 0, sizeof (mp_digit) * a->alloc); | 
 | ||||||
|  |   tmp = a->dp; | ||||||
|  |   for (n = 0; n < a->alloc; n++) { | ||||||
|  |      *tmp++ = 0; | ||||||
|  |   } | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| @ -8679,8 +8686,7 @@ LBL_M: | |||||||
|  * HAC pp. 595, Algorithm 14.12  Modified so you can control how  |  * HAC pp. 595, Algorithm 14.12  Modified so you can control how  | ||||||
|  * many digits of output are created. |  * many digits of output are created. | ||||||
|  */ |  */ | ||||||
| int | int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | ||||||
| s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) |  | ||||||
| { | { | ||||||
|   mp_int  t; |   mp_int  t; | ||||||
|   int     res, pa, pb, ix, iy; |   int     res, pa, pb, ix, iy; | ||||||
| @ -8848,8 +8854,7 @@ s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ | /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ | ||||||
| int | int s_mp_sqr (mp_int * a, mp_int * b) | ||||||
| s_mp_sqr (mp_int * a, mp_int * b) |  | ||||||
| { | { | ||||||
|   mp_int  t; |   mp_int  t; | ||||||
|   int     res, ix, iy, pa; |   int     res, ix, iy, pa; | ||||||
|  | |||||||
							
								
								
									
										35
									
								
								tombc/grammar.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								tombc/grammar.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | program       := program statement | statement | empty | ||||||
|  | statement     := { statement }                                                                              |  | ||||||
|  |                  identifier = numexpression;                                                                |  | ||||||
|  |                  identifier[numexpression] = numexpression;                                                 | | ||||||
|  |                  function(expressionlist);                                                                  |  | ||||||
|  |                  for (identifer = numexpression; numexpression; identifier = numexpression) { statement }   | | ||||||
|  |                  while (numexpression) { statement }                                                        |  | ||||||
|  |                  if (numexpresion) { statement } elif                                                       |  | ||||||
|  |                  break;                                                                                     |  | ||||||
|  |                  continue;                                                                                   | ||||||
|  |                   | ||||||
|  | elif          := else statement | empty | ||||||
|  | function      := abs | countbits | exptmod | jacobi | print | isprime | nextprime | issquare | readinteger | exit | ||||||
|  | expressionlist := expressionlist, expression | expression | ||||||
|  | 
 | ||||||
|  | // LR(1) !!!? | ||||||
|  | expression    := string | numexpression | ||||||
|  | numexpression := cmpexpr && cmpexpr | cmpexpr \|\| cmpexpr | cmpexpr | ||||||
|  | cmpexpr       := boolexpr  < boolexpr | boolexpr  > boolexpr | boolexpr == boolexpr |  | ||||||
|  |                  boolexpr <= boolexpr | boolexpr >= boolexpr | boolexpr | ||||||
|  | boolexpr      := shiftexpr & shiftexpr | shiftexpr ^ shiftexpr | shiftexpr \| shiftexpr | shiftexpr | ||||||
|  | shiftexpr     := addsubexpr << addsubexpr | addsubexpr >> addsubexpr | addsubexpr | ||||||
|  | addsubexpr    := mulexpr + mulexpr | mulexpr - mulexpr | mulexpr | ||||||
|  | mulexpr       := expr * expr       | expr / expr | expr % expr | expr | ||||||
|  | expr          := -nexpr | nexpr  | ||||||
|  | nexpr         := integer | identifier | ( numexpression ) | identifier[numexpression]  | ||||||
|  | 
 | ||||||
|  | identifier    := identifer digits | identifier alpha | alpha | ||||||
|  | alpha         := a ... z | A ... Z | ||||||
|  | integer       := hexnumber | digits  | ||||||
|  | hexnumber     := 0xhexdigits | ||||||
|  | hexdigits     := hexdigits hexdigit | hexdigit | ||||||
|  | hexdigit      := 0 ... 9 | a ... f | A ... F | ||||||
|  | digits        := digits digit | digit  | ||||||
|  | digit         := 0 ... 9 | ||||||
							
								
								
									
										
											BIN
										
									
								
								tommath.pdf
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tommath.pdf
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										491
									
								
								tommath.src
									
									
									
									
									
								
							
							
						
						
									
										491
									
								
								tommath.src
									
									
									
									
									
								
							| @ -49,7 +49,7 @@ | |||||||
| \begin{document} | \begin{document} | ||||||
| \frontmatter | \frontmatter | ||||||
| \pagestyle{empty} | \pagestyle{empty} | ||||||
| \title{Implementing Multiple Precision Arithmetic \\ ~ \\ Draft Edition } | \title{Multi--Precision Math} | ||||||
| \author{\mbox{ | \author{\mbox{ | ||||||
| %\begin{small} | %\begin{small} | ||||||
| \begin{tabular}{c} | \begin{tabular}{c} | ||||||
| @ -66,7 +66,7 @@ QUALCOMM Australia \\ | |||||||
| } | } | ||||||
| } | } | ||||||
| \maketitle | \maketitle | ||||||
| This text has been placed in the public domain.  This text corresponds to the v0.34 release of the  | This text has been placed in the public domain.  This text corresponds to the v0.35 release of the  | ||||||
| LibTomMath project. | LibTomMath project. | ||||||
| 
 | 
 | ||||||
| \begin{alltt} | \begin{alltt} | ||||||
| @ -85,66 +85,32 @@ This text is formatted to the international B5 paper size of 176mm wide by 250mm | |||||||
| 
 | 
 | ||||||
| \tableofcontents | \tableofcontents | ||||||
| \listoffigures | \listoffigures | ||||||
| \chapter*{Prefaces to the Draft Edition} | \chapter*{Prefaces} | ||||||
| I started this text in April 2003 to complement my LibTomMath library.  That is, explain how to implement the functions | When I tell people about my LibTom projects and that I release them as public domain they are often puzzled.   | ||||||
| contained in LibTomMath.  The goal is to have a textbook that any Computer Science student can use when implementing their | They ask why I did it and especially why I continue to work on them for free.  The best I can explain it is ``Because I can.''   | ||||||
| own multiple precision arithmetic.  The plan I wanted to follow was flesh out all the | Which seems odd and perhaps too terse for adult conversation. I often qualify it with ``I am able, I am willing.'' which  | ||||||
| ideas and concepts I had floating around in my head and then work on it afterwards refining a little bit at a time.  Chance | perhaps explains it better.  I am the first to admit there is not anything that special with what I have done.  Perhaps | ||||||
| would have it that I ended up with my summer off from Algonquin College and I was given four months solid to work on the | others can see that too and then we would have a society to be proud of.  My LibTom projects are what I am doing to give  | ||||||
| text.   | back to society in the form of tools and knowledge that can help others in their endeavours. | ||||||
| 
 | 
 | ||||||
| Choosing to not waste any time I dove right into the project even before my spring semester was finished.  I wrote a bit | I started writing this book because it was the most logical task to further my goal of open academia.  The LibTomMath source | ||||||
| off and on at first.  The moment my exams were finished I jumped into long 12 to 16 hour days.  The result after only | code itself was written to be easy to follow and learn from.  There are times, however, where pure C source code does not | ||||||
| a couple of months was a ten chapter, three hundred page draft that I quickly had distributed to anyone who wanted | explain the algorithms properly.  Hence this book.  The book literally starts with the foundation of the library and works | ||||||
| to read it.  I had Jean-Luc Cooke print copies for me and I brought them to Crypto'03 in Santa Barbara.  So far I have | itself outwards to the more complicated algorithms.  The use of both pseudo--code and verbatim source code provides a duality | ||||||
| managed to grab a certain level of attention having people from around the world ask me for copies of the text was certain | of ``theory'' and ``practice'' that the computer science students of the world shall appreciate.  I never deviate too far | ||||||
| rewarding. | from relatively straightforward algebra and I hope that this book can be a valuable learning asset. | ||||||
| 
 | 
 | ||||||
| Now we are past December 2003.  By this time I had pictured that I would have at least finished my second draft of the text.   | This book and indeed much of the LibTom projects would not exist in their current form if it was not for a plethora | ||||||
| Currently I am far off from this goal.  I've done partial re-writes of chapters one, two and three but they are not even | of kind people donating their time, resources and kind words to help support my work.  Writing a text of significant | ||||||
| finished yet.  I haven't given up on the project, only had some setbacks.  First O'Reilly declined to publish the text then | length (along with the source code) is a tiresome and lengthy process.  Currently the LibTom project is four years old, | ||||||
| Addison-Wesley and Greg is tried another which I don't know the name of.  However, at this point I want to focus my energy | comprises of literally thousands of users and over 100,000 lines of source code, TeX and other material.  People like Mads and Greg  | ||||||
| onto finishing the book not securing a contract. | were there at the beginning to encourage me to work well.  It is amazing how timely validation from others can boost morale to  | ||||||
|  | continue the project. Definitely my parents were there for me by providing room and board during the many months of work in 2003.   | ||||||
| 
 | 
 | ||||||
| So why am I writing this text?  It seems like a lot of work right?  Most certainly it is a lot of work writing a textbook.   | To my many friends whom I have met through the years I thank you for the good times and the words of encouragement.  I hope I | ||||||
| Even the simplest introductory material has to be lined with references and figures.  A lot of the text has to be re-written | honour your kind gestures with this project. | ||||||
| from point form to prose form to ensure an easier read.  Why am I doing all this work for free then?  Simple. My philosophy |  | ||||||
| is quite simply ``Open Source.  Open Academia.  Open Minds'' which means that to achieve a goal of open minds, that is, |  | ||||||
| people willing to accept new ideas and explore the unknown you have to make available material they can access freely  |  | ||||||
| without hinderance.   |  | ||||||
| 
 | 
 | ||||||
| I've been writing free software since I was about sixteen but only recently have I hit upon software that people have come | Open Source.  Open Academia.  Open Minds. | ||||||
| to depend upon.  I started LibTomCrypt in December 2001 and now several major companies use it as integral portions of their |  | ||||||
| software.  Several educational institutions use it as a matter of course and many freelance developers use it as |  | ||||||
| part of their projects.  To further my contributions I started the LibTomMath project in December 2002 aimed at providing |  | ||||||
| multiple precision arithmetic routines that students could learn from.  That is write routines that are not only easy |  | ||||||
| to understand and follow but provide quite impressive performance considering they are all in standard portable ISO C.   |  | ||||||
| 
 |  | ||||||
| The second leg of my philosophy is ``Open Academia'' which is where this textbook comes in.  In the end, when all is |  | ||||||
| said and done the text will be useable by educational institutions as a reference on multiple precision arithmetic.   |  | ||||||
| 
 |  | ||||||
| At this time I feel I should share a little information about myself.  The most common question I was asked at  |  | ||||||
| Crypto'03, perhaps just out of professional courtesy, was which school I either taught at or attended.  The unfortunate |  | ||||||
| truth is that I neither teach at or attend a school of academic reputation.  I'm currently at Algonquin College which  |  | ||||||
| is what I'd like to call ``somewhat academic but mostly vocational'' college.  In otherwords, job training. |  | ||||||
| 
 |  | ||||||
| I'm a 21 year old computer science student mostly self-taught in the areas I am aware of (which includes a half-dozen |  | ||||||
| computer science fields, a few fields of mathematics and some English).  I look forward to teaching someday but I am |  | ||||||
| still far off from that goal.   |  | ||||||
| 
 |  | ||||||
| Now it would be improper for me to not introduce the rest of the texts co-authors.  While they are only contributing  |  | ||||||
| corrections and editorial feedback their support has been tremendously helpful in presenting the concepts laid out |  | ||||||
| in the text so far.  Greg has always been there for me.  He has tracked my LibTom projects since their inception and even |  | ||||||
| sent cheques to help pay tuition from time to time.  His background has provided a wonderful source to bounce ideas off |  | ||||||
| of and improve the quality of my writing.  Mads is another fellow who has just ``been there''.  I don't even recall what |  | ||||||
| his interest in the LibTom projects is but I'm definitely glad he has been around.  His ability to catch logical errors |  | ||||||
| in my written English have saved me on several occasions to say the least. |  | ||||||
| 
 |  | ||||||
| What to expect next?  Well this is still a rough draft.  I've only had the chance to update a few chapters.  However, I've |  | ||||||
| been getting the feeling that people are starting to use my text and I owe them some updated material.  My current tenative |  | ||||||
| plan is to edit one chapter every two weeks starting January 4th.  It seems insane but my lower course load at college |  | ||||||
| should provide ample time.  By Crypto'04 I plan to have a 2nd draft of the text polished and ready to hand out to as many |  | ||||||
| people who will take it. |  | ||||||
| 
 | 
 | ||||||
| \begin{flushright} Tom St Denis \end{flushright} | \begin{flushright} Tom St Denis \end{flushright} | ||||||
| 
 | 
 | ||||||
| @ -937,7 +903,7 @@ assumed to contain undefined values they are initially set to zero. | |||||||
| 
 | 
 | ||||||
| EXAM,bn_mp_grow.c | EXAM,bn_mp_grow.c | ||||||
| 
 | 
 | ||||||
| A quick optimization is to first determine if a memory re-allocation is required at all.  The if statement (line @23,if@) checks | A quick optimization is to first determine if a memory re-allocation is required at all.  The if statement (line @24,alloc@) checks | ||||||
| if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count.  If the count is not larger than \textbf{alloc} | if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count.  If the count is not larger than \textbf{alloc} | ||||||
| the function skips the re-allocation part thus saving time. | the function skips the re-allocation part thus saving time. | ||||||
| 
 | 
 | ||||||
| @ -1310,7 +1276,7 @@ After the function is completed, all of the digits are zeroed, the \textbf{used} | |||||||
| With the mp\_int representation of an integer, calculating the absolute value is trivial.  The mp\_abs algorithm will compute | With the mp\_int representation of an integer, calculating the absolute value is trivial.  The mp\_abs algorithm will compute | ||||||
| the absolute value of an mp\_int. | the absolute value of an mp\_int. | ||||||
| 
 | 
 | ||||||
| \newpage\begin{figure}[here] | \begin{figure}[here] | ||||||
| \begin{center} | \begin{center} | ||||||
| \begin{tabular}{l} | \begin{tabular}{l} | ||||||
| \hline Algorithm \textbf{mp\_abs}. \\ | \hline Algorithm \textbf{mp\_abs}. \\ | ||||||
| @ -1335,6 +1301,9 @@ logic to handle it. | |||||||
| 
 | 
 | ||||||
| EXAM,bn_mp_abs.c | EXAM,bn_mp_abs.c | ||||||
| 
 | 
 | ||||||
|  | This fairly trivial algorithm first eliminates non--required duplications (line @27,a != b@) and then sets the | ||||||
|  | \textbf{sign} flag to \textbf{MP\_ZPOS}. | ||||||
|  | 
 | ||||||
| \subsection{Integer Negation} | \subsection{Integer Negation} | ||||||
| With the mp\_int representation of an integer, calculating the negation is also trivial.  The mp\_neg algorithm will compute | With the mp\_int representation of an integer, calculating the negation is also trivial.  The mp\_neg algorithm will compute | ||||||
| the negative of an mp\_int input. | the negative of an mp\_int input. | ||||||
| @ -1368,11 +1337,15 @@ zero as negative. | |||||||
| 
 | 
 | ||||||
| EXAM,bn_mp_neg.c | EXAM,bn_mp_neg.c | ||||||
| 
 | 
 | ||||||
|  | Like mp\_abs() this function avoids non--required duplications (line @21,a != b@) and then sets the sign.  We | ||||||
|  | have to make sure that only non--zero values get a \textbf{sign} of \textbf{MP\_NEG}.  If the mp\_int is zero | ||||||
|  | than the \textbf{sign} is hard--coded to \textbf{MP\_ZPOS}. | ||||||
|  | 
 | ||||||
| \section{Small Constants} | \section{Small Constants} | ||||||
| \subsection{Setting Small Constants} | \subsection{Setting Small Constants} | ||||||
| Often a mp\_int must be set to a relatively small value such as $1$ or $2$.  For these cases the mp\_set algorithm is useful. | Often a mp\_int must be set to a relatively small value such as $1$ or $2$.  For these cases the mp\_set algorithm is useful. | ||||||
| 
 | 
 | ||||||
| \begin{figure}[here] | \newpage\begin{figure}[here] | ||||||
| \begin{center} | \begin{center} | ||||||
| \begin{tabular}{l} | \begin{tabular}{l} | ||||||
| \hline Algorithm \textbf{mp\_set}. \\ | \hline Algorithm \textbf{mp\_set}. \\ | ||||||
| @ -1397,11 +1370,14 @@ single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adj | |||||||
| 
 | 
 | ||||||
| EXAM,bn_mp_set.c | EXAM,bn_mp_set.c | ||||||
| 
 | 
 | ||||||
| Line @21,mp_zero@ calls mp\_zero() to clear the mp\_int and reset the sign.  Line @22,MP_MASK@ copies the digit  | First we zero (line @21,mp_zero@) the mp\_int to make sure that the other members are initialized for a  | ||||||
| into the least significant location.  Note the usage of a new constant \textbf{MP\_MASK}.  This constant is used to quickly | small positive constant.  mp\_zero() ensures that the \textbf{sign} is positive and the \textbf{used} count | ||||||
| reduce an integer modulo $\beta$.  Since $\beta$ is of the form $2^k$ for any suitable $k$ it suffices to perform a binary AND with  | is zero.  Next we set the digit and reduce it modulo $\beta$ (line @22,MP_MASK@).  After this step we have to  | ||||||
| $MP\_MASK = 2^k - 1$ to perform the reduction.  Finally line @23,a->used@ will set the \textbf{used} member with respect to the  | check if the resulting digit is zero or not.  If it is not then we set the \textbf{used} count to one, otherwise | ||||||
| digit actually set. This function will always make the integer positive. | to zero. | ||||||
|  | 
 | ||||||
|  | We can quickly reduce modulo $\beta$ since it is of the form $2^k$ and a quick binary AND operation with  | ||||||
|  | $2^k - 1$ will perform the same operation. | ||||||
| 
 | 
 | ||||||
| One important limitation of this function is that it will only set one digit.  The size of a digit is not fixed, meaning source that uses  | One important limitation of this function is that it will only set one digit.  The size of a digit is not fixed, meaning source that uses  | ||||||
| this function should take that into account.  Only trivially small constants can be set using this function. | this function should take that into account.  Only trivially small constants can be set using this function. | ||||||
| @ -1503,10 +1479,12 @@ the zero'th digit.  If after all of the digits have been compared, no difference | |||||||
| 
 | 
 | ||||||
| EXAM,bn_mp_cmp_mag.c | EXAM,bn_mp_cmp_mag.c | ||||||
| 
 | 
 | ||||||
| The two if statements on lines @24,if@ and @28,if@ compare the number of digits in the two inputs.  These two are performed before all of the digits | The two if statements (lines @24,if@ and @28,if@) compare the number of digits in the two inputs.  These two are  | ||||||
| are compared since it is a very cheap test to perform and can potentially save considerable time.  The implementation given is also not valid  | performed before all of the digits are compared since it is a very cheap test to perform and can potentially save  | ||||||
| without those two statements.  $b.alloc$ may be smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the  | considerable time.  The implementation given is also not valid without those two statements.  $b.alloc$ may be  | ||||||
| array of digits. | smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the array of digits. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| \subsection{Signed Comparisons} | \subsection{Signed Comparisons} | ||||||
| Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}).  Based on an unsigned magnitude  | Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}).  Based on an unsigned magnitude  | ||||||
| @ -1539,9 +1517,9 @@ $\vert a \vert < \vert b \vert$.  Step number four will compare the two when the | |||||||
| 
 | 
 | ||||||
| EXAM,bn_mp_cmp.c | EXAM,bn_mp_cmp.c | ||||||
| 
 | 
 | ||||||
| The two if statements on lines @22,if@ and @26,if@ perform the initial sign comparison.  If the signs are not the equal then which ever | The two if statements (lines @22,if@ and @26,if@) perform the initial sign comparison.  If the signs are not the equal then which ever | ||||||
| has the positive sign is larger.   At line @30,if@, the inputs are compared based on magnitudes.  If the signs were both negative then  | has the positive sign is larger.   The inputs are compared (line @30,if@) based on magnitudes.  If the signs were both  | ||||||
| the unsigned comparison is performed in the opposite direction (\textit{line @31,mp_cmp_mag@}).  Otherwise, the signs are assumed to  | negative then the unsigned comparison is performed in the opposite direction (line @31,mp_cmp_mag@).  Otherwise, the signs are assumed to  | ||||||
| be both positive and a forward direction unsigned comparison is performed. | be both positive and a forward direction unsigned comparison is performed. | ||||||
| 
 | 
 | ||||||
| \section*{Exercises} | \section*{Exercises} | ||||||
| @ -1664,19 +1642,21 @@ The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are | |||||||
| 
 | 
 | ||||||
| EXAM,bn_s_mp_add.c | EXAM,bn_s_mp_add.c | ||||||
| 
 | 
 | ||||||
| Lines @27,if@ to @35,}@ perform the initial sorting of the inputs and determine the $min$ and $max$ variables.  Note that $x$ is a pointer to a  | We first sort (lines @27,if@ to @35,}@) the inputs based on magnitude and determine the $min$ and $max$ variables. | ||||||
| mp\_int assigned to the largest input, in effect it is a local alias.  Lines @37,init@ to @42,}@ ensure that the destination is grown to  | Note that $x$ is a pointer to an mp\_int assigned to the largest input, in effect it is a local alias.  Next we | ||||||
| accomodate the result of the addition.  | grow the destination (@37,init@ to @42,}@) ensure that it can accomodate the result of the addition.  | ||||||
| 
 | 
 | ||||||
| Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style.  The three aliases that are on  | Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style.  The three aliases that are on  | ||||||
| lines @56,tmpa@, @59,tmpb@ and @62,tmpc@ represent the two inputs and destination variables respectively.  These aliases are used to ensure the | lines @56,tmpa@, @59,tmpb@ and @62,tmpc@ represent the two inputs and destination variables respectively.  These aliases are used to ensure the | ||||||
| compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int. | compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int. | ||||||
| 
 | 
 | ||||||
| The initial carry $u$ is cleared on line @65,u = 0@, note that $u$ is of type mp\_digit which ensures type compatibility within the  | The initial carry $u$ will be cleared (line @65,u = 0@), note that $u$ is of type mp\_digit which ensures type  | ||||||
| implementation.  The initial addition loop begins on line @66,for@ and ends on line @75,}@.  Similarly the conditional addition loop | compatibility within the implementation.  The initial addition (line @66,for@ to @75,}@) adds digits from | ||||||
| begins on line @81,for@ and ends on line @90,}@.  The addition is finished with the final carry being stored in $tmpc$ on line @94,tmpc++@.   | both inputs until the smallest input runs out of digits.  Similarly the conditional addition loop | ||||||
| Note the ``++'' operator on the same line.  After line @94,tmpc++@ $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$.  This is useful | (line @81,for@ to @90,}@) adds the remaining digits from the larger of the two inputs.  The addition is finished  | ||||||
| for the next loop on lines @97,for@ to @99,}@ which set any old upper digits to zero. | with the final carry being stored in $tmpc$ (line @94,tmpc++@).  Note the ``++'' operator within the same expression. | ||||||
|  | After line @94,tmpc++@, $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$.  This is useful | ||||||
|  | for the next loop (line @97,for@ to @99,}@) which set any old upper digits to zero. | ||||||
| 
 | 
 | ||||||
| \subsection{Low Level Subtraction} | \subsection{Low Level Subtraction} | ||||||
| The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm.  The principle difference is that the | The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm.  The principle difference is that the | ||||||
| @ -1692,7 +1672,7 @@ this algorithm we will assume that the variable $\gamma$ represents the number o | |||||||
| mp\_digit (\textit{this implies $2^{\gamma} > \beta$}).   | mp\_digit (\textit{this implies $2^{\gamma} > \beta$}).   | ||||||
| 
 | 
 | ||||||
| For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$.  In ISO C an ``unsigned long'' | For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$.  In ISO C an ``unsigned long'' | ||||||
| data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma = 32$. | data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma \ge 32$. | ||||||
| 
 | 
 | ||||||
| \newpage\begin{figure}[!here] | \newpage\begin{figure}[!here] | ||||||
| \begin{center} | \begin{center} | ||||||
| @ -1759,20 +1739,23 @@ If $b$ has a smaller magnitude than $a$ then step 9 will force the carry and cop | |||||||
| 
 | 
 | ||||||
| EXAM,bn_s_mp_sub.c | EXAM,bn_s_mp_sub.c | ||||||
| 
 | 
 | ||||||
| Line @24,min@ and @25,max@ perform the initial hardcoded sorting of the inputs.  In reality the $min$ and $max$ variables are only aliases and are only  | Like low level addition we ``sort'' the inputs.  Except in this case the sorting is hardcoded  | ||||||
| used to make the source code easier to read.  Again the pointer alias optimization is used within this algorithm.  Lines @42,tmpa@, @43,tmpb@ and @44,tmpc@ initialize the aliases for  | (lines @24,min@ and @25,max@).  In reality the $min$ and $max$ variables are only aliases and are only  | ||||||
| $a$, $b$ and $c$ respectively. | used to make the source code easier to read.  Again the pointer alias optimization is used  | ||||||
|  | within this algorithm.  The aliases $tmpa$, $tmpb$ and $tmpc$ are initialized | ||||||
|  | (lines @42,tmpa@, @43,tmpb@ and @44,tmpc@) for $a$, $b$ and $c$ respectively. | ||||||
| 
 | 
 | ||||||
| The first subtraction loop occurs on lines @47,u = 0@ through @61,}@.  The theory behind the subtraction loop is exactly the same as that for | The first subtraction loop (lines @47,u = 0@ through @61,}@) subtract digits from both inputs until the smaller of | ||||||
| the addition loop.  As remarked earlier there is an implementation reason for using the ``awkward'' method of extracting the carry  | the two inputs has been exhausted.  As remarked earlier there is an implementation reason for using the ``awkward''  | ||||||
| (\textit{see line @57, >>@}).  The traditional method for extracting the carry would be to shift by $lg(\beta)$ positions and logically AND  | method of extracting the carry (line @57, >>@).  The traditional method for extracting the carry would be to shift  | ||||||
| the least significant bit.  The AND operation is required because all of the bits above the $\lg(\beta)$'th bit will be set to one after a carry | by $lg(\beta)$ positions and logically AND the least significant bit.  The AND operation is required because all of  | ||||||
| occurs from subtraction.  This carry extraction requires two relatively cheap operations to extract the carry.  The other method is to simply  | the bits above the $\lg(\beta)$'th bit will be set to one after a carry occurs from subtraction.  This carry  | ||||||
| shift the most significant bit to the least significant bit thus extracting the carry with a single cheap operation.  This optimization only works on | extraction requires two relatively cheap operations to extract the carry.  The other method is to simply shift the  | ||||||
| twos compliment machines which is a safe assumption to make. | most significant bit to the least significant bit thus extracting the carry with a single cheap operation.  This  | ||||||
|  | optimization only works on twos compliment machines which is a safe assumption to make. | ||||||
| 
 | 
 | ||||||
| If $a$ has a larger magnitude than $b$ an additional loop (\textit{see lines @64,for@ through @73,}@}) is required to propagate the carry through | If $a$ has a larger magnitude than $b$ an additional loop (lines @64,for@ through @73,}@) is required to propagate  | ||||||
| $a$ and copy the result to $c$.   | the carry through $a$ and copy the result to $c$.   | ||||||
| 
 | 
 | ||||||
| \subsection{High Level Addition} | \subsection{High Level Addition} | ||||||
| Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be | Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be | ||||||
| @ -2098,10 +2081,11 @@ FIGU,sliding_window,Sliding Window Movement | |||||||
| 
 | 
 | ||||||
| EXAM,bn_mp_lshd.c | EXAM,bn_mp_lshd.c | ||||||
| 
 | 
 | ||||||
| The if statement on line @24,if@ ensures that the $b$ variable is greater than zero.  The \textbf{used} count is incremented by $b$ before | The if statement (line @24,if@) ensures that the $b$ variable is greater than zero since we do not interpret negative | ||||||
| the copy loop begins.  This elminates the need for an additional variable in the for loop.  The variable $top$ on line @42,top@ is an alias | shift counts properly.  The \textbf{used} count is incremented by $b$ before the copy loop begins.  This elminates  | ||||||
| for the leading digit while $bottom$ on line @45,bottom@ is an alias for the trailing edge.  The aliases form a window of exactly $b$ digits | the need for an additional variable in the for loop.  The variable $top$ (line @42,top@) is an alias | ||||||
| over the input.   | for the leading digit while $bottom$ (line @45,bottom@) is an alias for the trailing edge.  The aliases form a  | ||||||
|  | window of exactly $b$ digits over the input.   | ||||||
| 
 | 
 | ||||||
| \subsection{Division by $x$} | \subsection{Division by $x$} | ||||||
| 
 | 
 | ||||||
| @ -2151,9 +2135,9 @@ Once the window copy is complete the upper digits must be zeroed and the \textbf | |||||||
| 
 | 
 | ||||||
| EXAM,bn_mp_rshd.c | EXAM,bn_mp_rshd.c | ||||||
| 
 | 
 | ||||||
| The only noteworthy element of this routine is the lack of a return type.   | The only noteworthy element of this routine is the lack of a return type since it cannot fail.  Like mp\_lshd() we | ||||||
| 
 | form a sliding window except we copy in the other direction.  After the window (line @59,for (;@) we then zero | ||||||
| -- Will update later to give it a return type...Tom | the upper digits of the input to make sure the result is correct. | ||||||
| 
 | 
 | ||||||
| \section{Powers of Two} | \section{Powers of Two} | ||||||
| 
 | 
 | ||||||
| @ -2214,7 +2198,15 @@ complete.  It is possible to optimize this algorithm down to a $O(n)$ algorithm | |||||||
| 
 | 
 | ||||||
| EXAM,bn_mp_mul_2d.c | EXAM,bn_mp_mul_2d.c | ||||||
| 
 | 
 | ||||||
| Notes to be revised when code is updated. -- Tom | The shifting is performed in--place which means the first step (line @24,a != c@) is to copy the input to the  | ||||||
|  | destination.  We avoid calling mp\_copy() by making sure the mp\_ints are different.  The destination then | ||||||
|  | has to be grown (line @31,grow@) to accomodate the result. | ||||||
|  | 
 | ||||||
|  | If the shift count $b$ is larger than $lg(\beta)$ then a call to mp\_lshd() is used to handle all of the multiples  | ||||||
|  | of $lg(\beta)$.  Leaving only a remaining shift of $lg(\beta) - 1$ or fewer bits left.  Inside the actual shift  | ||||||
|  | loop (lines @45,if@ to @76,}@) we make use of pre--computed values $shift$ and $mask$.   These are used to | ||||||
|  | extract the carry bit(s) to pass into the next iteration of the loop.  The $r$ and $rr$ variables form a  | ||||||
|  | chain between consecutive iterations to propagate the carry.   | ||||||
| 
 | 
 | ||||||
| \subsection{Division by Power of Two} | \subsection{Division by Power of Two} | ||||||
| 
 | 
 | ||||||
| @ -2263,7 +2255,8 @@ ignored by passing \textbf{NULL} as the pointer to the mp\_int variable.    The | |||||||
| result of the remainder operation until the end.  This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before | result of the remainder operation until the end.  This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before | ||||||
| the quotient is obtained. | the quotient is obtained. | ||||||
| 
 | 
 | ||||||
| The remainder of the source code is essentially the same as the source code for mp\_mul\_2d.  (-- Fix this paragraph up later, Tom). | The remainder of the source code is essentially the same as the source code for mp\_mul\_2d.  The only significant difference is | ||||||
|  | the direction of the shifts. | ||||||
| 
 | 
 | ||||||
| \subsection{Remainder of Division by Power of Two} | \subsection{Remainder of Division by Power of Two} | ||||||
| 
 | 
 | ||||||
| @ -2306,7 +2299,13 @@ is copied to $b$, leading digits are removed and the remaining leading digit is | |||||||
| 
 | 
 | ||||||
| EXAM,bn_mp_mod_2d.c | EXAM,bn_mp_mod_2d.c | ||||||
| 
 | 
 | ||||||
| -- Add comments later, Tom. | We first avoid cases of $b \le 0$ by simply mp\_zero()'ing the destination in such cases.  Next if $2^b$ is larger | ||||||
|  | than the input we just mp\_copy() the input and return right away.  After this point we know we must actually | ||||||
|  | perform some work to produce the remainder. | ||||||
|  | 
 | ||||||
|  | Recalling that reducing modulo $2^k$ and a binary ``and'' with $2^k - 1$ are numerically equivalent we can quickly reduce  | ||||||
|  | the number.  First we zero any digits above the last digit in $2^b$ (line @41,for@).  Next we reduce the  | ||||||
|  | leading digit of both (line @45,&=@) and then mp\_clamp(). | ||||||
| 
 | 
 | ||||||
| \section*{Exercises} | \section*{Exercises} | ||||||
| \begin{tabular}{cl} | \begin{tabular}{cl} | ||||||
| @ -2464,33 +2463,46 @@ exceed the precision requested. | |||||||
| 
 | 
 | ||||||
| EXAM,bn_s_mp_mul_digs.c | EXAM,bn_s_mp_mul_digs.c | ||||||
| 
 | 
 | ||||||
| Lines @31,if@ to @35,}@ determine if the Comba method can be used first.  The conditions for using the Comba routine are that min$(a.used, b.used) < \delta$ and | First we determine (line @30,if@) if the Comba method can be used first since it's faster.  The conditions for  | ||||||
| the number of digits of output is less than \textbf{MP\_WARRAY}.  This new constant is used to control  | sing the Comba routine are that min$(a.used, b.used) < \delta$ and the number of digits of output is less than  | ||||||
| the stack usage in the Comba routines.  By default it is set to $\delta$ but can be reduced when memory is at a premium. | \textbf{MP\_WARRAY}.  This new constant is used to control the stack usage in the Comba routines.  By default it is  | ||||||
|  | set to $\delta$ but can be reduced when memory is at a premium. | ||||||
| 
 | 
 | ||||||
| Of particular importance is the calculation of the $ix+iy$'th column on lines @64,mp_word@, @65,mp_word@ and @66,mp_word@.  Note how all of the | If we cannot use the Comba method we proceed to setup the baseline routine.  We allocate the the destination mp\_int | ||||||
| variables are cast to the type \textbf{mp\_word}, which is also the type of variable $\hat r$.  That is to ensure that double precision operations  | $t$ (line @36,init@) to the exact size of the output to avoid further re--allocations.  At this point we now  | ||||||
| are used instead of single precision.  The multiplication on line @65,) * (@ makes use of a specific GCC optimizer behaviour.  On the outset it looks like  | begin the $O(n^2)$ loop. | ||||||
| the compiler will have to use a double precision multiplication to produce the result required.  Such an operation would be horribly slow on most  | 
 | ||||||
| processors and drag this to a crawl.  However, GCC is smart enough to realize that double wide output single precision multipliers can be used.  For  | This implementation of multiplication has the caveat that it can be trimmed to only produce a variable number of | ||||||
| example, the instruction ``MUL'' on the x86 processor can multiply two 32-bit values and produce a 64-bit result.   | digits as output.  In each iteration of the outer loop the $pb$ variable is set (line @48,MIN@) to the maximum  | ||||||
|  | number of inner loop iterations.   | ||||||
|  | 
 | ||||||
|  | Inside the inner loop we calculate $\hat r$ as the mp\_word product of the two mp\_digits and the addition of the | ||||||
|  | carry from the previous iteration.  A particularly important observation is that most modern optimizing  | ||||||
|  | C compilers (GCC for instance) can recognize that a $N \times N \rightarrow 2N$ multiplication is all that  | ||||||
|  | is required for the product.  In x86 terms for example, this means using the MUL instruction. | ||||||
|  | 
 | ||||||
|  | Each digit of the product is stored in turn (line @68,tmpt@) and the carry propagated (line @71,>>@) to the  | ||||||
|  | next iteration. | ||||||
| 
 | 
 | ||||||
| \subsection{Faster Multiplication by the ``Comba'' Method} | \subsection{Faster Multiplication by the ``Comba'' Method} | ||||||
| MARK,COMBA | MARK,COMBA | ||||||
| 
 | 
 | ||||||
| One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be computed and propagated upwards.  This | One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be  | ||||||
| makes the nested loop very sequential and hard to unroll and implement in parallel.  The ``Comba'' \cite{COMBA} method is named after little known  | computed and propagated upwards.  This makes the nested loop very sequential and hard to unroll and implement  | ||||||
| (\textit{in cryptographic venues}) Paul G. Comba who described a method of implementing fast multipliers that do not require nested  | in parallel.  The ``Comba'' \cite{COMBA} method is named after little known (\textit{in cryptographic venues}) Paul G.  | ||||||
| carry fixup operations.  As an interesting aside it seems that Paul Barrett describes a similar technique in | Comba who described a method of implementing fast multipliers that do not require nested carry fixup operations.  As an  | ||||||
| his 1986 paper \cite{BARRETT} written five years before. | interesting aside it seems that Paul Barrett describes a similar technique in his 1986 paper \cite{BARRETT} written  | ||||||
|  | five years before. | ||||||
| 
 | 
 | ||||||
| At the heart of the Comba technique is once again the long-hand algorithm.  Except in this case a slight twist is placed on how | At the heart of the Comba technique is once again the long-hand algorithm.  Except in this case a slight  | ||||||
| the columns of the result are produced.  In the standard long-hand algorithm rows of products are produced then added together to form the  | twist is placed on how the columns of the result are produced.  In the standard long-hand algorithm rows of products  | ||||||
| final result.  In the baseline algorithm the columns are added together after each iteration to get the result instantaneously.   | are produced then added together to form the final result.  In the baseline algorithm the columns are added together  | ||||||
|  | after each iteration to get the result instantaneously.   | ||||||
| 
 | 
 | ||||||
| In the Comba algorithm the columns of the result are produced entirely independently of each other.  That is at the $O(n^2)$ level a  | In the Comba algorithm the columns of the result are produced entirely independently of each other.  That is at  | ||||||
| simple multiplication and addition step is performed.  The carries of the columns are propagated after the nested loop to reduce the amount | the $O(n^2)$ level a simple multiplication and addition step is performed.  The carries of the columns are propagated  | ||||||
| of work requiored. Succintly the first step of the algorithm is to compute the product vector $\vec x$ as follows.  | after the nested loop to reduce the amount of work requiored. Succintly the first step of the algorithm is to compute  | ||||||
|  | the product vector $\vec x$ as follows.  | ||||||
| 
 | 
 | ||||||
| \begin{equation} | \begin{equation} | ||||||
| \vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace | \vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace | ||||||
| @ -2584,38 +2596,32 @@ $256$ digits would allow for numbers in the range of $0 \le x < 2^{7168}$ which, | |||||||
| \textbf{Input}.   mp\_int $a$, mp\_int $b$ and an integer $digs$ \\ | \textbf{Input}.   mp\_int $a$, mp\_int $b$ and an integer $digs$ \\ | ||||||
| \textbf{Output}.  $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\ | \textbf{Output}.  $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\ | ||||||
| \hline \\ | \hline \\ | ||||||
| Place an array of \textbf{MP\_WARRAY} double precision digits named $\hat W$ on the stack. \\ | Place an array of \textbf{MP\_WARRAY} single precision digits named $W$ on the stack. \\ | ||||||
| 1.  If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\ | 1.  If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\ | ||||||
| 2.  If step 1 failed return(\textit{MP\_MEM}).\\ | 2.  If step 1 failed return(\textit{MP\_MEM}).\\ | ||||||
| \\ | \\ | ||||||
| Zero the temporary array $\hat W$. \\ | 3.  $pa \leftarrow \mbox{MIN}(digs, a.used + b.used)$ \\ | ||||||
| 3.  for $n$ from $0$ to $digs - 1$ do \\ |  | ||||||
| \hspace{3mm}3.1  $\hat W_n \leftarrow 0$ \\ |  | ||||||
| \\ | \\ | ||||||
| Compute the columns. \\ | 4.  $\_ \hat W \leftarrow 0$ \\ | ||||||
| 4.  for $ix$ from $0$ to $a.used - 1$ do \\ | 5.  for $ix$ from 0 to $pa - 1$ do \\ | ||||||
| \hspace{3mm}4.1  $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\ | \hspace{3mm}5.1  $ty \leftarrow \mbox{MIN}(b.used - 1, ix)$ \\ | ||||||
| \hspace{3mm}4.2  If $pb < 1$ then goto step 5. \\ | \hspace{3mm}5.2  $tx \leftarrow ix - ty$ \\ | ||||||
| \hspace{3mm}4.3  for $iy$ from $0$ to $pb - 1$ do \\ | \hspace{3mm}5.3  $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\ | ||||||
| \hspace{6mm}4.3.1  $\hat W_{ix+iy} \leftarrow \hat W_{ix+iy} + a_{ix}b_{iy}$ \\ | \hspace{3mm}5.4  for $iz$ from 0 to $iy - 1$ do \\ | ||||||
|  | \hspace{6mm}5.4.1  $\_ \hat W \leftarrow \_ \hat W + a_{tx+iy}b_{ty-iy}$ \\ | ||||||
|  | \hspace{3mm}5.5  $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$\\ | ||||||
|  | \hspace{3mm}5.6  $\_ \hat W \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\ | ||||||
|  | 6.  $W_{pa} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\ | ||||||
| \\ | \\ | ||||||
| Propagate the carries upwards. \\ | 7.  $oldused \leftarrow c.used$ \\ | ||||||
| 5.  $oldused \leftarrow c.used$ \\ | 8.  $c.used \leftarrow digs$ \\ | ||||||
| 6.  $c.used \leftarrow digs$ \\ | 9.  for $ix$ from $0$ to $pa$ do \\ | ||||||
| 7.  If $digs > 1$ then do \\ | \hspace{3mm}9.1  $c_{ix} \leftarrow W_{ix}$ \\ | ||||||
| \hspace{3mm}7.1.  for $ix$ from $1$ to $digs - 1$ do \\ | 10.  for $ix$ from $pa + 1$ to $oldused - 1$ do \\ | ||||||
| \hspace{6mm}7.1.1  $\hat W_{ix} \leftarrow \hat W_{ix} + \lfloor \hat W_{ix-1} / \beta \rfloor$ \\ | \hspace{3mm}10.1 $c_{ix} \leftarrow 0$ \\ | ||||||
| \hspace{6mm}7.1.2  $c_{ix - 1} \leftarrow \hat W_{ix - 1} \mbox{ (mod }\beta\mbox{)}$ \\ |  | ||||||
| 8.  else do \\ |  | ||||||
| \hspace{3mm}8.1  $ix \leftarrow 0$ \\ |  | ||||||
| 9.  $c_{ix} \leftarrow \hat W_{ix} \mbox{ (mod }\beta\mbox{)}$ \\ |  | ||||||
| \\ | \\ | ||||||
| Zero excess digits. \\ | 11.  Clamp $c$. \\ | ||||||
| 10.  If $digs < oldused$ then do \\ | 12.  Return MP\_OKAY. \\ | ||||||
| \hspace{3mm}10.1  for $n$ from $digs$ to $oldused - 1$ do \\ |  | ||||||
| \hspace{6mm}10.1.1  $c_n \leftarrow 0$ \\ |  | ||||||
| 11.  Clamp excessive digits of $c$.  (\textit{mp\_clamp}) \\ |  | ||||||
| 12.  Return(\textit{MP\_OKAY}). \\ |  | ||||||
| \hline | \hline | ||||||
| \end{tabular} | \end{tabular} | ||||||
| \end{center} | \end{center} | ||||||
| @ -2625,15 +2631,24 @@ Zero excess digits. \\ | |||||||
| \end{figure} | \end{figure} | ||||||
| 
 | 
 | ||||||
| \textbf{Algorithm fast\_s\_mp\_mul\_digs.} | \textbf{Algorithm fast\_s\_mp\_mul\_digs.} | ||||||
| This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision.  The algorithm | This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision. | ||||||
| essentially peforms the same calculation as algorithm s\_mp\_mul\_digs, just much faster. |  | ||||||
| 
 | 
 | ||||||
| The array $\hat W$ is meant to be on the stack when the algorithm is used.  The size of the array does not change which is ideal.  Note also that  | The outer loop of this algorithm is more complicated than that of the baseline multiplier.  This is because on the inside of the  | ||||||
| unlike algorithm s\_mp\_mul\_digs no temporary mp\_int is required since the result is calculated directly in $\hat W$.   | loop we want to produce one column per pass.  This allows the accumulator $\_ \hat W$ to be placed in CPU registers and | ||||||
|  | reduce the memory bandwidth to two \textbf{mp\_digit} reads per iteration. | ||||||
| 
 | 
 | ||||||
| The $O(n^2)$ loop on step four is where the Comba method's advantages begin to show through in comparison to the baseline algorithm.  The lack of | The $ty$ variable is set to the minimum count of $ix$ or the number of digits in $b$.  That way if $a$ has more digits than | ||||||
| a carry variable or propagation in this loop allows the loop to be performed with only single precision multiplication and additions.  Now that each | $b$ this will be limited to $b.used - 1$.  The $tx$ variable is set to the to the distance past $b.used$ the variable | ||||||
| iteration of the inner loop can be performed independent of the others the inner loop can be performed with a high level of parallelism. | $ix$ is.  This is used for the immediately subsequent statement where we find $iy$.   | ||||||
|  | 
 | ||||||
|  | The variable $iy$ is the minimum digits we can read from either $a$ or $b$ before running out.  Computing one column at a time | ||||||
|  | means we have to scan one integer upwards and the other downwards.  $a$ starts at $tx$ and $b$ starts at $ty$.  In each | ||||||
|  | pass we are producing the $ix$'th output column and we note that $tx + ty = ix$.  As we move $tx$ upwards we have to  | ||||||
|  | move $ty$ downards so the equality remains valid.  The $iy$ variable is the number of iterations until  | ||||||
|  | $tx \ge a.used$ or $ty < 0$ occurs. | ||||||
|  | 
 | ||||||
|  | After every inner pass we store the lower half of the accumulator into $W_{ix}$ and then propagate the carry of the accumulator | ||||||
|  | into the next round by dividing $\_ \hat W$ by $\beta$. | ||||||
| 
 | 
 | ||||||
| To measure the benefits of the Comba method over the baseline method consider the number of operations that are required.  If the  | To measure the benefits of the Comba method over the baseline method consider the number of operations that are required.  If the  | ||||||
| cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require  | cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require  | ||||||
| @ -2643,20 +2658,20 @@ and addition operations in the nested loop in parallel. | |||||||
| 
 | 
 | ||||||
| EXAM,bn_fast_s_mp_mul_digs.c | EXAM,bn_fast_s_mp_mul_digs.c | ||||||
| 
 | 
 | ||||||
| The memset on line @47,memset@ clears the initial $\hat W$ array to zero in a single step. Like the slower baseline multiplication | As per the pseudo--code we first calculate $pa$ (line @47,MIN@) as the number of digits to output.  Next we begin the outer loop | ||||||
| implementation a series of aliases (\textit{lines @67, tmpx@, @70, tmpy@ and @75,_W@}) are used to simplify the inner $O(n^2)$ loop.   | to produce the individual columns of the product.  We use the two aliases $tmpx$ and $tmpy$ (lines @61,tmpx@, @62,tmpy@) to point | ||||||
| In this case a new alias $\_\hat W$ has been added which refers to the double precision columns offset by $ix$ in each pass.   | inside the two multiplicands quickly.   | ||||||
| 
 | 
 | ||||||
| The inner loop on lines @83,for@, @84,mp_word@ and @85,}@ is where the algorithm will spend the majority of the time, which is why it has been  | The inner loop (lines @70,for@ to @72,}@) of this implementation is where the tradeoff come into play.  Originally this comba  | ||||||
| stripped to the bones of any extra baggage\footnote{Hence the pointer aliases.}.  On x86 processors the multiplication and additions amount to at the  | implementation was ``row--major'' which means it adds to each of the columns in each pass.  After the outer loop it would then fix  | ||||||
| very least five instructions (\textit{two loads, two additions, one multiply}) while on the ARMv4 processors they amount to only three  | the carries.  This was very fast except it had an annoying drawback.  You had to read a mp\_word and two mp\_digits and write  | ||||||
| (\textit{one load, one store, one multiply-add}).   For both of the x86 and ARMv4 processors the GCC compiler performs a good job at unrolling the loop  | one mp\_word per iteration.  On processors such as the Athlon XP and P4 this did not matter much since the cache bandwidth  | ||||||
| and scheduling the instructions so there are very few dependency stalls. | is very high and it can keep the ALU fed with data.  It did, however, matter on older and embedded cpus where cache is often  | ||||||
|  | slower and also often doesn't exist.  This new algorithm only performs two reads per iteration under the assumption that the  | ||||||
|  | compiler has aliased $\_ \hat W$ to a CPU register. | ||||||
| 
 | 
 | ||||||
| In theory the difference between the baseline and comba algorithms is a mere $O(qn)$ time difference.  However, in the $O(n^2)$ nested loop of the | After the inner loop we store the current accumulator in $W$ and shift $\_ \hat W$ (lines @75,W[ix]@, @78,>>@) to forward it as  | ||||||
| baseline method there are dependency stalls as the algorithm must wait for the multiplier to finish before propagating the carry to the next  | a carry for the next pass.  After the outer loop we use the final carry (line @82,W[ix]@) as the last digit of the product.   | ||||||
| digit.  As a result fewer of the often multiple execution units\footnote{The AMD Athlon has three execution units and the Intel P4 has four.} can |  | ||||||
| be simultaneously used.   |  | ||||||
| 
 | 
 | ||||||
| \subsection{Polynomial Basis Multiplication} | \subsection{Polynomial Basis Multiplication} | ||||||
| To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication.  In the following algorithms | To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication.  In the following algorithms | ||||||
| @ -2976,13 +2991,26 @@ result $a \cdot b$ is produced. | |||||||
| 
 | 
 | ||||||
| EXAM,bn_mp_toom_mul.c | EXAM,bn_mp_toom_mul.c | ||||||
| 
 | 
 | ||||||
| -- Comments to be added during editing phase. | The first obvious thing to note is that this algorithm is complicated.  The complexity is worth it if you are multiplying very  | ||||||
|  | large numbers.  For example, a 10,000 digit multiplication takes approximaly 99,282,205 fewer single precision multiplications with | ||||||
|  | Toom--Cook than a Comba or baseline approach (this is a savings of more than 99$\%$).  For most ``crypto'' sized numbers this | ||||||
|  | algorithm is not practical as Karatsuba has a much lower cutoff point. | ||||||
|  | 
 | ||||||
|  | First we split $a$ and $b$ into three roughly equal portions.  This has been accomplished (lines @40,mod@ to @69,rshd@) with  | ||||||
|  | combinations of mp\_rshd() and mp\_mod\_2d() function calls.  At this point $a = a2 \cdot \beta^2 + a1 \cdot \beta + a0$ and similiarly | ||||||
|  | for $b$.   | ||||||
|  | 
 | ||||||
|  | Next we compute the five points $w0, w1, w2, w3$ and $w4$.  Recall that $w0$ and $w4$ can be computed directly from the portions so | ||||||
|  | we get those out of the way first (lines @72,mul@ and @77,mul@).  Next we compute $w1, w2$ and $w3$ using Horners method. | ||||||
|  | 
 | ||||||
|  | After this point we solve for the actual values of $w1, w2$ and $w3$ by reducing the $5 \times 5$ system which is relatively | ||||||
|  | straight forward.   | ||||||
| 
 | 
 | ||||||
| \subsection{Signed Multiplication} | \subsection{Signed Multiplication} | ||||||
| Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required.  So far all | Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required.  So far all | ||||||
| of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established.   | of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established.   | ||||||
| 
 | 
 | ||||||
| \newpage\begin{figure}[!here] | \begin{figure}[!here] | ||||||
| \begin{small} | \begin{small} | ||||||
| \begin{center} | \begin{center} | ||||||
| \begin{tabular}{l} | \begin{tabular}{l} | ||||||
| @ -3065,7 +3093,7 @@ Column two of row one is a square and column three is the first unique column. | |||||||
| The baseline squaring algorithm is meant to be a catch-all squaring algorithm.  It will handle any of the input sizes that the faster routines | The baseline squaring algorithm is meant to be a catch-all squaring algorithm.  It will handle any of the input sizes that the faster routines | ||||||
| will not handle.   | will not handle.   | ||||||
| 
 | 
 | ||||||
| \newpage\begin{figure}[!here] | \begin{figure}[!here] | ||||||
| \begin{small} | \begin{small} | ||||||
| \begin{center} | \begin{center} | ||||||
| \begin{tabular}{l} | \begin{tabular}{l} | ||||||
| @ -3121,9 +3149,14 @@ results calculated so far.  This involves expensive carry propagation which will | |||||||
| 
 | 
 | ||||||
| EXAM,bn_s_mp_sqr.c | EXAM,bn_s_mp_sqr.c | ||||||
| 
 | 
 | ||||||
| Inside the outer loop (\textit{see line @32,for@}) the square term is calculated on line @35,r =@.  Line @42,>>@ extracts the carry from the square | Inside the outer loop (line @32,for@) the square term is calculated on line @35,r =@.  The carry (line @42,>>@) has been | ||||||
| term.  Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized on lines @45,tmpx@ and @48,tmpt@ respectively.  The doubling is performed using two | extracted from the mp\_word accumulator using a right shift.  Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized  | ||||||
| additions (\textit{see line @57,r + r@}) since it is usually faster than shifting,if not at least as fast.   | (lines @45,tmpx@ and @48,tmpt@) to simplify the inner loop.  The doubling is performed using two | ||||||
|  | additions (line @57,r + r@) since it is usually faster than shifting, if not at least as fast.   | ||||||
|  | 
 | ||||||
|  | The important observation is that the inner loop does not begin at $iy = 0$ like for multiplication.  As such the inner loops | ||||||
|  | get progressively shorter as the algorithm proceeds.  This is what leads to the savings compared to using a multiplication to | ||||||
|  | square a number.  | ||||||
| 
 | 
 | ||||||
| \subsection{Faster Squaring by the ``Comba'' Method} | \subsection{Faster Squaring by the ``Comba'' Method} | ||||||
| A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop.  Squaring has an additional | A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop.  Squaring has an additional | ||||||
| @ -3135,9 +3168,9 @@ propagation operations from the inner loop.  However, the inner product must sti | |||||||
| that $2a + 2b + 2c = 2(a + b + c)$.  That is the sum of all of the double products is equal to double the sum of all the products.  For example, | that $2a + 2b + 2c = 2(a + b + c)$.  That is the sum of all of the double products is equal to double the sum of all the products.  For example, | ||||||
| $ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$.   | $ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$.   | ||||||
| 
 | 
 | ||||||
| However, we cannot simply double all of the columns, since the squares appear only once per row.  The most practical solution is to have two mp\_word | However, we cannot simply double all of the columns, since the squares appear only once per row.  The most practical solution is to have two  | ||||||
| arrays.  One array will hold the squares and the other array will hold the double products.  With both arrays the doubling and carry propagation can be  | mp\_word arrays.  One array will hold the squares and the other array will hold the double products.  With both arrays the doubling and  | ||||||
| moved to a $O(n)$ work level outside the $O(n^2)$ level.   | carry propagation can be moved to a $O(n)$ work level outside the $O(n^2)$ level.  In this case, we have an even simpler solution in mind. | ||||||
| 
 | 
 | ||||||
| \newpage\begin{figure}[!here] | \newpage\begin{figure}[!here] | ||||||
| \begin{small} | \begin{small} | ||||||
| @ -3147,34 +3180,34 @@ moved to a $O(n)$ work level outside the $O(n^2)$ level. | |||||||
| \textbf{Input}.   mp\_int $a$ \\ | \textbf{Input}.   mp\_int $a$ \\ | ||||||
| \textbf{Output}.  $b \leftarrow a^2$ \\ | \textbf{Output}.  $b \leftarrow a^2$ \\ | ||||||
| \hline \\ | \hline \\ | ||||||
| Place two arrays of \textbf{MP\_WARRAY} mp\_words named $\hat W$ and $\hat {X}$ on the stack. \\ | Place an array of \textbf{MP\_WARRAY} mp\_digits named $W$ on the stack. \\ | ||||||
| 1.  If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits.  (\textit{mp\_grow}). \\ | 1.  If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits.  (\textit{mp\_grow}). \\ | ||||||
| 2.  If step 1 failed return(\textit{MP\_MEM}). \\ | 2.  If step 1 failed return(\textit{MP\_MEM}). \\ | ||||||
| 3.  for $ix$ from $0$ to $2a.used + 1$ do \\ |  | ||||||
| \hspace{3mm}3.1  $\hat W_{ix} \leftarrow 0$ \\ |  | ||||||
| \hspace{3mm}3.2  $\hat {X}_{ix} \leftarrow 0$ \\ |  | ||||||
| 4.  for $ix$ from $0$ to $a.used - 1$ do \\ |  | ||||||
| \hspace{3mm}Compute the square.\\ |  | ||||||
| \hspace{3mm}4.1  $\hat {X}_{ix+ix} \leftarrow \left ( a_{ix} \right )^2$ \\ |  | ||||||
| \\ | \\ | ||||||
| \hspace{3mm}Compute the double products.\\ | 3.  $pa \leftarrow 2 \cdot a.used$ \\ | ||||||
| \hspace{3mm}4.2  for $iy$ from $ix + 1$ to $a.used - 1$ do \\ | 4.  $\hat W1 \leftarrow 0$ \\ | ||||||
| \hspace{6mm}4.2.1  $\hat W_{ix+iy} \leftarrow \hat W_{ix+iy} + a_{ix}a_{iy}$ \\ | 5.  for $ix$ from $0$ to $pa - 1$ do \\ | ||||||
| 5.  $oldused \leftarrow b.used$ \\ | \hspace{3mm}5.1  $\_ \hat W \leftarrow 0$ \\ | ||||||
| 6.  $b.used \leftarrow 2a.used + 1$ \\ | \hspace{3mm}5.2  $ty \leftarrow \mbox{MIN}(a.used - 1, ix)$ \\ | ||||||
|  | \hspace{3mm}5.3  $tx \leftarrow ix - ty$ \\ | ||||||
|  | \hspace{3mm}5.4  $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\ | ||||||
|  | \hspace{3mm}5.5  $iy \leftarrow \mbox{MIN}(iy, \lfloor \left (ty - tx + 1 \right )/2 \rfloor)$ \\ | ||||||
|  | \hspace{3mm}5.6  for $iz$ from $0$ to $iz - 1$ do \\ | ||||||
|  | \hspace{6mm}5.6.1  $\_ \hat W \leftarrow \_ \hat W + a_{tx + iz}a_{ty - iz}$ \\ | ||||||
|  | \hspace{3mm}5.7  $\_ \hat W \leftarrow 2 \cdot \_ \hat W  + \hat W1$ \\ | ||||||
|  | \hspace{3mm}5.8  if $ix$ is even then \\ | ||||||
|  | \hspace{6mm}5.8.1  $\_ \hat W \leftarrow \_ \hat W + \left ( a_{\lfloor ix/2 \rfloor}\right )^2$ \\ | ||||||
|  | \hspace{3mm}5.9  $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\ | ||||||
|  | \hspace{3mm}5.10  $\hat W1 \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\ | ||||||
| \\ | \\ | ||||||
| Double the products and propagate the carries simultaneously. \\ | 6.  $oldused \leftarrow b.used$ \\ | ||||||
| 7.  $\hat W_0 \leftarrow 2 \hat W_0 + \hat {X}_0$ \\ | 7.  $b.used \leftarrow 2 \cdot a.used$ \\ | ||||||
| 8.  for $ix$ from $1$ to $2a.used$ do \\ | 8.  for $ix$ from $0$ to $pa - 1$ do \\ | ||||||
| \hspace{3mm}8.1 $\hat W_{ix} \leftarrow 2 \hat W_{ix} + \hat {X}_{ix}$ \\ | \hspace{3mm}8.1  $b_{ix} \leftarrow W_{ix}$ \\ | ||||||
| \hspace{3mm}8.2 $\hat W_{ix} \leftarrow \hat W_{ix} + \lfloor \hat W_{ix - 1} / \beta \rfloor$ \\ | 9.  for $ix$ from $pa$ to $oldused - 1$ do \\ | ||||||
| \hspace{3mm}8.3 $b_{ix-1} \leftarrow W_{ix-1} \mbox{ (mod }\beta\mbox{)}$ \\ | \hspace{3mm}9.1  $b_{ix} \leftarrow 0$ \\ | ||||||
| 9.  $b_{2a.used} \leftarrow \hat W_{2a.used} \mbox{ (mod }\beta\mbox{)}$ \\ | 10.  Clamp excess digits from $b$.  (\textit{mp\_clamp}) \\ | ||||||
| 10.  if $2a.used + 1 < oldused$ then do \\ | 11.  Return(\textit{MP\_OKAY}). \\  | ||||||
| \hspace{3mm}10.1  for $ix$ from $2a.used + 1$ to $oldused$ do \\ |  | ||||||
| \hspace{6mm}10.1.1  $b_{ix} \leftarrow 0$ \\ |  | ||||||
| 11.  Clamp excess digits from $b$.  (\textit{mp\_clamp}) \\ |  | ||||||
| 12.  Return(\textit{MP\_OKAY}). \\  |  | ||||||
| \hline | \hline | ||||||
| \end{tabular} | \end{tabular} | ||||||
| \end{center} | \end{center} | ||||||
| @ -3183,24 +3216,24 @@ Double the products and propagate the carries simultaneously. \\ | |||||||
| \end{figure} | \end{figure} | ||||||
| 
 | 
 | ||||||
| \textbf{Algorithm fast\_s\_mp\_sqr.} | \textbf{Algorithm fast\_s\_mp\_sqr.} | ||||||
| This algorithm computes the square of an input using the Comba technique.  It is designed to be a replacement for algorithm s\_mp\_sqr when | This algorithm computes the square of an input using the Comba technique.  It is designed to be a replacement for algorithm  | ||||||
| the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$.   | s\_mp\_sqr when the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$.   | ||||||
|  | This algorithm is very similar to the Comba multiplier except with a few key differences we shall make note of. | ||||||
| 
 | 
 | ||||||
| This routine requires two arrays of mp\_words to be placed on the stack.  The first array $\hat W$ will hold the double products and the second | First, we have an accumulator and carry variables $\_ \hat W$ and $\hat W1$ respectively.  This is because the inner loop | ||||||
| array $\hat X$ will hold the squares.  Though only at most $MP\_WARRAY \over 2$ words of $\hat X$ are used, it has proven faster on most  | products are to be doubled.  If we had added the previous carry in we would be doubling too much.  Next we perform an | ||||||
| processors to simply make it a full size array. | addition MIN condition on $iy$ (step 5.5) to prevent overlapping digits.  For example, $a_3 \cdot a_5$ is equal | ||||||
|  | $a_5 \cdot a_3$.  Whereas in the multiplication case we would have $5 < a.used$ and $3 \ge 0$ is maintained since we double the sum | ||||||
|  | of the products just outside the inner loop we have to avoid doing this.  This is also a good thing since we perform | ||||||
|  | fewer multiplications and the routine ends up being faster. | ||||||
| 
 | 
 | ||||||
| The loop on step 3 will zero the two arrays to prepare them for the squaring step.  Step 4.1 computes the squares of the product.  Note how  | Finally the last difference is the addition of the ``square'' term outside the inner loop (step 5.8).  We add in the square | ||||||
| it simply assigns the value into the $\hat X$ array.  The nested loop on step 4.2 computes the doubles of the products.  This loop | only to even outputs and it is the square of the term at the $\lfloor ix / 2 \rfloor$ position. | ||||||
| computes the sum of the products for each column.  They are not doubled until later. |  | ||||||
| 
 |  | ||||||
| After the squaring loop, the products stored in $\hat W$ musted be doubled and the carries propagated forwards.  It makes sense to do both |  | ||||||
| operations at the same time.  The expression $\hat W_{ix} \leftarrow 2 \hat W_{ix} + \hat {X}_{ix}$ computes the sum of the double product and the |  | ||||||
| squares in place.   |  | ||||||
| 
 | 
 | ||||||
| EXAM,bn_fast_s_mp_sqr.c | EXAM,bn_fast_s_mp_sqr.c | ||||||
| 
 | 
 | ||||||
| -- Write something deep and insightful later, Tom. | This implementation is essentially a copy of Comba multiplication with the appropriate changes added to make it faster for  | ||||||
|  | the special case of squaring.   | ||||||
| 
 | 
 | ||||||
| \subsection{Polynomial Basis Squaring} | \subsection{Polynomial Basis Squaring} | ||||||
| The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring.  The minor exception | The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring.  The minor exception | ||||||
| @ -3312,14 +3345,13 @@ By inlining the copy and shift operations the cutoff point for Karatsuba multipl | |||||||
| is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}).  On slower processors such as the Intel P4 | is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}).  On slower processors such as the Intel P4 | ||||||
| it is actually below the Comba limit (\textit{at 110 digits}). | it is actually below the Comba limit (\textit{at 110 digits}). | ||||||
| 
 | 
 | ||||||
| This routine uses the same error trap coding style as mp\_karatsuba\_sqr.  As the temporary variables are initialized errors are redirected to | This routine uses the same error trap coding style as mp\_karatsuba\_sqr.  As the temporary variables are initialized errors are  | ||||||
| the error trap higher up.  If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and mp\_clears are executed normally. | redirected to the error trap higher up.  If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and  | ||||||
| 
 | mp\_clears are executed normally. | ||||||
| \textit{Last paragraph sucks.  re-write! -- Tom} |  | ||||||
| 
 | 
 | ||||||
| \subsection{Toom-Cook Squaring} | \subsection{Toom-Cook Squaring} | ||||||
| The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used | The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used | ||||||
| instead of multiplication to find the five relations..  The reader is encouraged to read the description of the latter algorithm and try to  | instead of multiplication to find the five relations.  The reader is encouraged to read the description of the latter algorithm and try to  | ||||||
| derive their own Toom-Cook squaring algorithm.   | derive their own Toom-Cook squaring algorithm.   | ||||||
| 
 | 
 | ||||||
| \subsection{High Level Squaring} | \subsection{High Level Squaring} | ||||||
| @ -3362,12 +3394,9 @@ EXAM,bn_mp_sqr.c | |||||||
| $\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\ | $\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\ | ||||||
|                       & that have different number of digits in Karatsuba multiplication. \\ |                       & that have different number of digits in Karatsuba multiplication. \\ | ||||||
|                       & \\ |                       & \\ | ||||||
| $\left [ 3 \right ] $ & In ~SQUARE~ the fact that every column of a squaring is made up \\ | $\left [ 2 \right ] $ & In ~SQUARE~ the fact that every column of a squaring is made up \\ | ||||||
|                       & of double products and at most one square is stated.  Prove this statement. \\ |                       & of double products and at most one square is stated.  Prove this statement. \\ | ||||||
|                       & \\                       |                       & \\                       | ||||||
| $\left [ 2 \right ] $ & In the Comba squaring algorithm half of the $\hat X$ variables are not used. \\ |  | ||||||
|                       & Revise algorithm fast\_s\_mp\_sqr to shrink the $\hat X$ array. \\ |  | ||||||
|                       & \\ |  | ||||||
| $\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\ | $\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\ | ||||||
|                       & \\ |                       & \\ | ||||||
| $\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\ | $\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\ | ||||||
| @ -3375,6 +3404,14 @@ $\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3 | |||||||
| $\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\ | $\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\ | ||||||
|                       & required for equation $6.7$ to be true.  \\ |                       & required for equation $6.7$ to be true.  \\ | ||||||
|                       & \\ |                       & \\ | ||||||
|  | $\left [ 3 \right ] $ & Implement a threaded version of Comba multiplication (and squaring) where you \\ | ||||||
|  |                       & compute subsets of the columns in each thread.  Determine a cutoff point where \\ | ||||||
|  |                       & it is effective and add the logic to mp\_mul() and mp\_sqr(). \\ | ||||||
|  |                       &\\ | ||||||
|  | $\left [ 4 \right ] $ & Same as the previous but also modify the Karatsuba and Toom-Cook.  You must \\ | ||||||
|  |                       & increase the throughput of mp\_exptmod() for random odd moduli in the range \\ | ||||||
|  |                       & $512 \ldots 4096$ bits significantly ($> 2x$) to complete this challenge. \\ | ||||||
|  |                       & \\ | ||||||
| \end{tabular} | \end{tabular} | ||||||
| 
 | 
 | ||||||
| \chapter{Modular Reduction} | \chapter{Modular Reduction} | ||||||
| @ -3394,7 +3431,7 @@ other forms of residues. | |||||||
| Modular reductions are normally used to create either finite groups, rings or fields.  The most common usage for performance driven modular reductions  | Modular reductions are normally used to create either finite groups, rings or fields.  The most common usage for performance driven modular reductions  | ||||||
| is in modular exponentiation algorithms.  That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible.  This operation is used in the  | is in modular exponentiation algorithms.  That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible.  This operation is used in the  | ||||||
| RSA and Diffie-Hellman public key algorithms, for example.  Modular multiplication and squaring also appears as a fundamental operation in  | RSA and Diffie-Hellman public key algorithms, for example.  Modular multiplication and squaring also appears as a fundamental operation in  | ||||||
| Elliptic Curve cryptographic algorithms.  As will be discussed in the subsequent chapter there exist fast algorithms for computing modular  | elliptic curve cryptographic algorithms.  As will be discussed in the subsequent chapter there exist fast algorithms for computing modular  | ||||||
| exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications.  These algorithms will produce partial results in the  | exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications.  These algorithms will produce partial results in the  | ||||||
| range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms.   They have also been used to create redundancy check  | range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms.   They have also been used to create redundancy check  | ||||||
| algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems.   | algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems.   | ||||||
| @ -3610,7 +3647,7 @@ safe to do so. | |||||||
| In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance.  Ideally this value should be computed once and stored for | In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance.  Ideally this value should be computed once and stored for | ||||||
| future use so that the Barrett algorithm can be used without delay.   | future use so that the Barrett algorithm can be used without delay.   | ||||||
| 
 | 
 | ||||||
| \begin{figure}[!here] | \newpage\begin{figure}[!here] | ||||||
| \begin{small} | \begin{small} | ||||||
| \begin{center} | \begin{center} | ||||||
| \begin{tabular}{l} | \begin{tabular}{l} | ||||||
| @ -5818,6 +5855,8 @@ To explain the Jacobi Symbol we shall first discuss the Legendre function\footno | |||||||
| defined.  The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$.  Numerically it is | defined.  The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$.  Numerically it is | ||||||
| equivalent to equation \ref{eqn:legendre}. | equivalent to equation \ref{eqn:legendre}. | ||||||
| 
 | 
 | ||||||
|  | \textit{-- Tom, don't be an ass, cite your source here...!} | ||||||
|  | 
 | ||||||
| \begin{equation} | \begin{equation} | ||||||
| a^{(p-1)/2} \equiv \begin{array}{rl} | a^{(p-1)/2} \equiv \begin{array}{rl} | ||||||
|                               -1 &  \mbox{if }a\mbox{ is a quadratic non-residue.} \\ |                               -1 &  \mbox{if }a\mbox{ is a quadratic non-residue.} \\ | ||||||
|  | |||||||
							
								
								
									
										1533
									
								
								tommath.tex
									
									
									
									
									
								
							
							
						
						
									
										1533
									
								
								tommath.tex
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -137,7 +137,7 @@ | |||||||
|    #define BN_MP_ISEVEN_C |    #define BN_MP_ISEVEN_C | ||||||
|    #define BN_MP_INIT_MULTI_C |    #define BN_MP_INIT_MULTI_C | ||||||
|    #define BN_MP_COPY_C |    #define BN_MP_COPY_C | ||||||
|    #define BN_MP_ABS_C |    #define BN_MP_MOD_C | ||||||
|    #define BN_MP_SET_C |    #define BN_MP_SET_C | ||||||
|    #define BN_MP_DIV_2_C |    #define BN_MP_DIV_2_C | ||||||
|    #define BN_MP_ISODD_C |    #define BN_MP_ISODD_C | ||||||
| @ -366,6 +366,7 @@ | |||||||
|    #define BN_MP_DIV_C |    #define BN_MP_DIV_C | ||||||
|    #define BN_MP_MUL_C |    #define BN_MP_MUL_C | ||||||
|    #define BN_MP_SUB_C |    #define BN_MP_SUB_C | ||||||
|  |    #define BN_MP_NEG_C | ||||||
|    #define BN_MP_EXCH_C |    #define BN_MP_EXCH_C | ||||||
|    #define BN_MP_CLEAR_MULTI_C |    #define BN_MP_CLEAR_MULTI_C | ||||||
| #endif | #endif | ||||||
| @ -440,6 +441,7 @@ | |||||||
| #if defined(BN_MP_INVMOD_SLOW_C) | #if defined(BN_MP_INVMOD_SLOW_C) | ||||||
|    #define BN_MP_ISZERO_C |    #define BN_MP_ISZERO_C | ||||||
|    #define BN_MP_INIT_MULTI_C |    #define BN_MP_INIT_MULTI_C | ||||||
|  |    #define BN_MP_MOD_C | ||||||
|    #define BN_MP_COPY_C |    #define BN_MP_COPY_C | ||||||
|    #define BN_MP_ISEVEN_C |    #define BN_MP_ISEVEN_C | ||||||
|    #define BN_MP_SET_C |    #define BN_MP_SET_C | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user