| 
									
										
										
										
											2018-05-02 21:43:17 +02:00
										 |  |  | #include "tommath_private.h"
 | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | #ifdef BN_FAST_S_MP_SQR_C
 | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  | /* LibTomMath, multiple-precision integer library -- Tom St Denis
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |  * LibTomMath is a library that provides multiple-precision | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |  * integer arithmetic as well as number theoretic functionality. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |  * The library was designed directly after the MPI library by | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |  * Michael Fromberger but has been written from scratch with | 
					
						
							|  |  |  |  * additional optimizations in place. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-12-29 17:56:20 +01:00
										 |  |  |  * SPDX-License-Identifier: Unlicense | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | /* the jist of squaring...
 | 
					
						
							| 
									
										
										
										
											2017-08-30 05:51:11 +02:00
										 |  |  |  * you do like mult except the offset of the tmpx [one that | 
					
						
							|  |  |  |  * starts closer to zero] can't equal the offset of tmpy. | 
					
						
							| 
									
										
										
										
											2005-03-12 11:55:11 +00:00
										 |  |  |  * So basically you set up iy like before then you min it with | 
					
						
							| 
									
										
										
										
											2017-08-30 05:51:11 +02:00
										 |  |  |  * (ty-tx) so that it never happens.  You double all those | 
					
						
							| 
									
										
										
										
											2005-03-12 11:55:11 +00:00
										 |  |  |  * you add in the inner loop | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | After that loop you do the squares and add them in. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-20 16:59:43 +02:00
										 |  |  | int fast_s_mp_sqr(const mp_int *a, mp_int *b) | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-08-29 22:23:48 +02:00
										 |  |  |    int       olduse, res, pa, ix, iz; | 
					
						
							|  |  |  |    mp_digit   W[MP_WARRAY], *tmpx; | 
					
						
							|  |  |  |    mp_word   W1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* grow the destination as required */ | 
					
						
							|  |  |  |    pa = a->used + a->used; | 
					
						
							|  |  |  |    if (b->alloc < pa) { | 
					
						
							|  |  |  |       if ((res = mp_grow(b, pa)) != MP_OKAY) { | 
					
						
							|  |  |  |          return res; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* number of output digits to produce */ | 
					
						
							|  |  |  |    W1 = 0; | 
					
						
							|  |  |  |    for (ix = 0; ix < pa; ix++) { | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  |       int      tx, ty, iy; | 
					
						
							|  |  |  |       mp_word  _W; | 
					
						
							|  |  |  |       mp_digit *tmpy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* clear counter */ | 
					
						
							|  |  |  |       _W = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* get offsets into the two bignums */ | 
					
						
							|  |  |  |       ty = MIN(a->used-1, ix); | 
					
						
							|  |  |  |       tx = ix - ty; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* setup temp aliases */ | 
					
						
							|  |  |  |       tmpx = a->dp + tx; | 
					
						
							|  |  |  |       tmpy = a->dp + ty; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-03-12 11:55:11 +00:00
										 |  |  |       /* this is the number of times the loop will iterrate, essentially
 | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  |          while (tx++ < a->used && ty-- >= 0) { ... } | 
					
						
							|  |  |  |        */ | 
					
						
							|  |  |  |       iy = MIN(a->used-tx, ty+1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-30 05:51:11 +02:00
										 |  |  |       /* now for squaring tx can never equal ty
 | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  |        * we halve the distance since they approach at a rate of 2x | 
					
						
							|  |  |  |        * and we have to round because odd cases need to be executed | 
					
						
							|  |  |  |        */ | 
					
						
							| 
									
										
										
										
											2015-10-17 18:28:05 +02:00
										 |  |  |       iy = MIN(iy, ((ty-tx)+1)>>1); | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* execute loop */ | 
					
						
							|  |  |  |       for (iz = 0; iz < iy; iz++) { | 
					
						
							| 
									
										
										
										
											2017-10-15 19:58:35 +02:00
										 |  |  |          _W += (mp_word)*tmpx++ * (mp_word)*tmpy--; | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* double the inner product and add carry */ | 
					
						
							|  |  |  |       _W = _W + _W + W1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* even columns have the square term in them */ | 
					
						
							| 
									
										
										
										
											2017-10-15 19:57:12 +02:00
										 |  |  |       if (((unsigned)ix & 1u) == 0u) { | 
					
						
							| 
									
										
										
										
											2017-10-15 19:58:35 +02:00
										 |  |  |          _W += (mp_word)a->dp[ix>>1] * (mp_word)a->dp[ix>>1]; | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* store it */ | 
					
						
							| 
									
										
										
										
											2017-10-15 19:58:35 +02:00
										 |  |  |       W[ix] = _W & MP_MASK; | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* make next carry */ | 
					
						
							| 
									
										
										
										
											2017-10-15 19:58:35 +02:00
										 |  |  |       W1 = _W >> (mp_word)DIGIT_BIT; | 
					
						
							| 
									
										
										
										
											2017-08-29 22:23:48 +02:00
										 |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* setup dest */ | 
					
						
							|  |  |  |    olduse  = b->used; | 
					
						
							|  |  |  |    b->used = a->used+a->used; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    { | 
					
						
							|  |  |  |       mp_digit *tmpb; | 
					
						
							|  |  |  |       tmpb = b->dp; | 
					
						
							|  |  |  |       for (ix = 0; ix < pa; ix++) { | 
					
						
							|  |  |  |          *tmpb++ = W[ix] & MP_MASK; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* clear unused digits [that existed in the old copy of c] */ | 
					
						
							|  |  |  |       for (; ix < olduse; ix++) { | 
					
						
							|  |  |  |          *tmpb++ = 0; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |    mp_clamp(b); | 
					
						
							|  |  |  |    return MP_OKAY; | 
					
						
							| 
									
										
										
										
											2003-02-28 16:08:34 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-08-01 16:37:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-28 16:27:26 +02:00
										 |  |  | /* ref:         $Format:%D$ */ | 
					
						
							|  |  |  | /* git commit:  $Format:%H$ */ | 
					
						
							|  |  |  | /* commit time: $Format:%ai$ */ |