77 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "tommath_private.h"
 | |
| #ifdef BN_MP_DIV_3_C
 | |
| /* LibTomMath, multiple-precision integer library -- Tom St Denis
 | |
|  *
 | |
|  * LibTomMath is a library that provides multiple-precision
 | |
|  * integer arithmetic as well as number theoretic functionality.
 | |
|  *
 | |
|  * The library was designed directly after the MPI library by
 | |
|  * Michael Fromberger but has been written from scratch with
 | |
|  * additional optimizations in place.
 | |
|  *
 | |
|  * The library is free for all purposes without any express
 | |
|  * guarantee it works.
 | |
|  */
 | |
| 
 | |
| /* divide by three (based on routine from MPI and the GMP manual) */
 | |
| int mp_div_3(const mp_int *a, mp_int *c, mp_digit *d)
 | |
| {
 | |
|    mp_int   q;
 | |
|    mp_word  w, t;
 | |
|    mp_digit b;
 | |
|    int      res, ix;
 | |
| 
 | |
|    /* b = 2**DIGIT_BIT / 3 */
 | |
|    b = ((mp_word)1 << (mp_word)DIGIT_BIT) / (mp_word)3;
 | |
| 
 | |
|    if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
 | |
|       return res;
 | |
|    }
 | |
| 
 | |
|    q.used = a->used;
 | |
|    q.sign = a->sign;
 | |
|    w = 0;
 | |
|    for (ix = a->used - 1; ix >= 0; ix--) {
 | |
|       w = (w << (mp_word)DIGIT_BIT) | (mp_word)a->dp[ix];
 | |
| 
 | |
|       if (w >= 3u) {
 | |
|          /* multiply w by [1/3] */
 | |
|          t = (w * (mp_word)b) >> (mp_word)DIGIT_BIT;
 | |
| 
 | |
|          /* now subtract 3 * [w/3] from w, to get the remainder */
 | |
|          w -= t+t+t;
 | |
| 
 | |
|          /* fixup the remainder as required since
 | |
|           * the optimization is not exact.
 | |
|           */
 | |
|          while (w >= 3u) {
 | |
|             t += 1u;
 | |
|             w -= 3u;
 | |
|          }
 | |
|       } else {
 | |
|          t = 0;
 | |
|       }
 | |
|       q.dp[ix] = (mp_digit)t;
 | |
|    }
 | |
| 
 | |
|    /* [optional] store the remainder */
 | |
|    if (d != NULL) {
 | |
|       *d = (mp_digit)w;
 | |
|    }
 | |
| 
 | |
|    /* [optional] store the quotient */
 | |
|    if (c != NULL) {
 | |
|       mp_clamp(&q);
 | |
|       mp_exch(&q, c);
 | |
|    }
 | |
|    mp_clear(&q);
 | |
| 
 | |
|    return res;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| /* ref:         $Format:%D$ */
 | |
| /* git commit:  $Format:%H$ */
 | |
| /* commit time: $Format:%ai$ */
 |