diff options
Diffstat (limited to 'mpi/mpi-mpow.c')
-rw-r--r-- | mpi/mpi-mpow.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/mpi/mpi-mpow.c b/mpi/mpi-mpow.c new file mode 100644 index 000000000..5ac3c6399 --- /dev/null +++ b/mpi/mpi-mpow.c @@ -0,0 +1,119 @@ +/* mpi-mpow.c - MPI functions + * Copyright (c) 1998 by Werner Koch (dd9jn) + * + * This file is part of G10. + * + * G10 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * G10 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" +#include <assert.h> + +static int +build_index( MPI *exparray, int k, int i, int t ) +{ + int j, bitno; + int index = 0; + + bitno = t-i; + for(j=k-1; j >= 0; j-- ) { + index <<= 1; + if( mpi_test_bit( exparray[j], bitno ) ) + index |= 1; + } + /*log_debug("t=%d i=%d index=%d\n", t, i, index );*/ + return index; +} + +/**************** + * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M + */ +void +mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m) +{ + int k; /* number of elements */ + int t; /* bit size of largest exponent */ + int i, j, idx; + MPI *G; /* table with precomputed values of size 2^k */ + MPI tmp; + + for(k=0; basearray[k]; k++ ) + ; + assert(k); + for(t=0, i=0; (tmp=exparray[i]); i++ ) { + /*log_mpidump("exp: ", tmp );*/ + j = mpi_get_nbits(tmp); + if( j > t ) + t = j; + } + /*log_mpidump("mod: ", m );*/ + assert(i==k); + assert(t); + assert( k < 10 ); + + G = m_alloc_clear( (1<<k) * sizeof *G ); + #if 0 + /* do the precomputation */ + G[0] = mpi_alloc_set_ui( 1 ); + for(i=1; i < (1<<k); i++ ) { + for(j=0; j < k; j++ ) { + if( (i & (1<<j) ) ) { + if( !G[i] ) + G[i] = mpi_copy( basearray[j] ); + else + mpi_mulm( G[i], G[i], basearray[j], m ); + } + } + if( !G[i] ) + G[i] = mpi_alloc(0); + } + #endif + /* and calculate */ + tmp = mpi_alloc( mpi_get_nlimbs(m)+1 ); + mpi_set_ui( res, 1 ); + for(i = 1; i <= t; i++ ) { + mpi_mulm(tmp, res, res, m ); + idx = build_index( exparray, k, i, t ); + assert( idx >= 0 && idx < (1<<k) ); + if( !G[idx] ) { + if( !idx ) + G[0] = mpi_alloc_set_ui( 1 ); + else { + for(j=0; j < k; j++ ) { + if( (idx & (1<<j) ) ) { + if( !G[idx] ) + G[idx] = mpi_copy( basearray[j] ); + else + mpi_mulm( G[idx], G[idx], basearray[j], m ); + } + } + if( !G[idx] ) + G[idx] = mpi_alloc(0); + } + } + mpi_mulm(res, tmp, G[idx], m ); + } + + /* cleanup */ + m_free(tmp); + for(i=0; i < (1<<k); i++ ) + mpi_free(G[i]); + m_free(G); +} + |