Home | History | Annotate | Download | only in libtommath
      1 #include <tommath.h>
      2 #ifdef BN_MP_TOOM_SQR_C
      3 /* LibTomMath, multiple-precision integer library -- Tom St Denis
      4  *
      5  * LibTomMath is a library that provides multiple-precision
      6  * integer arithmetic as well as number theoretic functionality.
      7  *
      8  * The library was designed directly after the MPI library by
      9  * Michael Fromberger but has been written from scratch with
     10  * additional optimizations in place.
     11  *
     12  * The library is free for all purposes without any express
     13  * guarantee it works.
     14  *
     15  * Tom St Denis, tomstdenis (at) gmail.com, http://math.libtomcrypt.com
     16  */
     17 
     18 /* squaring using Toom-Cook 3-way algorithm */
     19 int
     20 mp_toom_sqr(mp_int *a, mp_int *b)
     21 {
     22     mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
     23     int res, B;
     24 
     25     /* init temps */
     26     if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
     27        return res;
     28     }
     29 
     30     /* B */
     31     B = a->used / 3;
     32 
     33     /* a = a2 * B**2 + a1 * B + a0 */
     34     if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
     35        goto ERR;
     36     }
     37 
     38     if ((res = mp_copy(a, &a1)) != MP_OKAY) {
     39        goto ERR;
     40     }
     41     mp_rshd(&a1, B);
     42     mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
     43 
     44     if ((res = mp_copy(a, &a2)) != MP_OKAY) {
     45        goto ERR;
     46     }
     47     mp_rshd(&a2, B*2);
     48 
     49     /* w0 = a0*a0 */
     50     if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
     51        goto ERR;
     52     }
     53 
     54     /* w4 = a2 * a2 */
     55     if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
     56        goto ERR;
     57     }
     58 
     59     /* w1 = (a2 + 2(a1 + 2a0))**2 */
     60     if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
     61        goto ERR;
     62     }
     63     if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
     64        goto ERR;
     65     }
     66     if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
     67        goto ERR;
     68     }
     69     if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
     70        goto ERR;
     71     }
     72 
     73     if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
     74        goto ERR;
     75     }
     76 
     77     /* w3 = (a0 + 2(a1 + 2a2))**2 */
     78     if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
     79        goto ERR;
     80     }
     81     if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
     82        goto ERR;
     83     }
     84     if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
     85        goto ERR;
     86     }
     87     if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
     88        goto ERR;
     89     }
     90 
     91     if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
     92        goto ERR;
     93     }
     94 
     95 
     96     /* w2 = (a2 + a1 + a0)**2 */
     97     if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
     98        goto ERR;
     99     }
    100     if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
    101        goto ERR;
    102     }
    103     if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
    104        goto ERR;
    105     }
    106 
    107     /* now solve the matrix
    108 
    109        0  0  0  0  1
    110        1  2  4  8  16
    111        1  1  1  1  1
    112        16 8  4  2  1
    113        1  0  0  0  0
    114 
    115        using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
    116      */
    117 
    118      /* r1 - r4 */
    119      if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
    120         goto ERR;
    121      }
    122      /* r3 - r0 */
    123      if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
    124         goto ERR;
    125      }
    126      /* r1/2 */
    127      if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
    128         goto ERR;
    129      }
    130      /* r3/2 */
    131      if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
    132         goto ERR;
    133      }
    134      /* r2 - r0 - r4 */
    135      if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
    136         goto ERR;
    137      }
    138      if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
    139         goto ERR;
    140      }
    141      /* r1 - r2 */
    142      if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
    143         goto ERR;
    144      }
    145      /* r3 - r2 */
    146      if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
    147         goto ERR;
    148      }
    149      /* r1 - 8r0 */
    150      if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
    151         goto ERR;
    152      }
    153      if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
    154         goto ERR;
    155      }
    156      /* r3 - 8r4 */
    157      if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
    158         goto ERR;
    159      }
    160      if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
    161         goto ERR;
    162      }
    163      /* 3r2 - r1 - r3 */
    164      if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
    165         goto ERR;
    166      }
    167      if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
    168         goto ERR;
    169      }
    170      if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
    171         goto ERR;
    172      }
    173      /* r1 - r2 */
    174      if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
    175         goto ERR;
    176      }
    177      /* r3 - r2 */
    178      if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
    179         goto ERR;
    180      }
    181      /* r1/3 */
    182      if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
    183         goto ERR;
    184      }
    185      /* r3/3 */
    186      if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
    187         goto ERR;
    188      }
    189 
    190      /* at this point shift W[n] by B*n */
    191      if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
    192         goto ERR;
    193      }
    194      if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
    195         goto ERR;
    196      }
    197      if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
    198         goto ERR;
    199      }
    200      if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
    201         goto ERR;
    202      }
    203 
    204      if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
    205         goto ERR;
    206      }
    207      if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
    208         goto ERR;
    209      }
    210      if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
    211         goto ERR;
    212      }
    213      if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
    214         goto ERR;
    215      }
    216 
    217 ERR:
    218      mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
    219      return res;
    220 }
    221 
    222 #endif
    223 
    224 /* $Source: /cvs/libtom/libtommath/bn_mp_toom_sqr.c,v $ */
    225 /* $Revision: 1.3 $ */
    226 /* $Date: 2006/03/31 14:18:44 $ */
    227