1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include <tommath.h> 2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef BN_MP_REDUCE_C 3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomMath, multiple-precision integer library -- Tom St Denis 4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomMath is a library that provides multiple-precision 6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * integer arithmetic as well as number theoretic functionality. 7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library was designed directly after the MPI library by 9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Michael Fromberger but has been written from scratch with 10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * additional optimizations in place. 11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express 13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works. 14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com 16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* reduces x mod m, assumes 0 < x < m**2, mu is 19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * precomputed via mp_reduce_setup. 20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * From HAC pp.604 Algorithm 14.42 21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint mp_reduce (mp_int * x, mp_int * m, mp_int * mu) 23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_int q; 25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int res, um = m->used; 26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* q = x */ 28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((res = mp_init_copy (&q, x)) != MP_OKAY) { 29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return res; 30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* q1 = x / b**(k-1) */ 33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_rshd (&q, um - 1); 34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* according to HAC this optimization is ok */ 36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) { 37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { 38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto CLEANUP; 39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef BN_S_MP_MUL_HIGH_DIGS_C 42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { 43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto CLEANUP; 44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) 46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { 47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto CLEANUP; 48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else 50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project { 51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project res = MP_VAL; 52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto CLEANUP; 53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* q3 = q2 / b**(k+1) */ 58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_rshd (&q, um + 1); 59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* x = x mod b**(k+1), quick (no division) */ 61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { 62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto CLEANUP; 63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* q = q * m mod b**(k+1), quick (no division) */ 66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { 67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto CLEANUP; 68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* x = x - q */ 71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((res = mp_sub (x, &q, x)) != MP_OKAY) { 72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto CLEANUP; 73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* If x < 0, add b**(k+1) to it */ 76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (mp_cmp_d (x, 0) == MP_LT) { 77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_set (&q, 1); 78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) 79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto CLEANUP; 80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((res = mp_add (x, &q, x)) != MP_OKAY) 81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto CLEANUP; 82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* Back off if it's too big */ 85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (mp_cmp (x, m) != MP_LT) { 86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((res = s_mp_sub (x, m, x)) != MP_OKAY) { 87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto CLEANUP; 88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source ProjectCLEANUP: 92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project mp_clear (&q); 93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return res; 95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtommath/bn_mp_reduce.c,v $ */ 99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.3 $ */ 100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/03/31 14:18:44 $ */ 101