Multi-modular techniques

Naive algorithms for bidirectional multi-modular transformers are implemented in crt_naive.hpp.

The following piece of code computes 101 modulo 2, 3, 5, and 7:

#include "crt_int.hpp"
…
crt_naive_transformer<int> crter (vec (2, 3, 5, 7));
mmout << direct_crt (101, crter) << "\n";

Here crt_int.hpp contains specific routines for hardware integers.

1.Coverings

Let be a subset of a ring . A covering of is a set of coprime elements of such that any element of is uniquely charaterized by its residues modulo all the elements of .

The class moduli_helper<C,Modulus> provides the user with a default covering in a specific size whose definition actually depends on . For example for the integers, the following instructions fill the vector with a covering for integers of 30 bits.

vector<modulus<int> > p;
bool t= moduli_helper<int, modulus<int> >::covering (p, 30);

Here the default covering being used is made of the sequence of the prime numbers: 2, 3, 5, 7, 11, etc. The value returned in t is false if no covering can be made for the specified size. Otherwise true is returned.

The sequence used for the covering can be specified as an extra argument:

#define Seq fft_prime_sequence_int<10>
vector<modulus<int> > p;
bool t= moduli_helper<int, modulus<int>, Seq>::covering (p, 30);

Here are used prime numbers of at most 10 bits. The first ones are well-suited to FFT.

Support for long integers is available in crt_integer.hpp. The following piece of code covers signed integers of 1000 bits with prime hardware integers of at most 20 bits:

#include <algebramix/crt_integer.hpp>
#define Seq fft_prime_sequence_int<20>
vector<modulus<int, modulus_int_preinverse<20> > > p;
bool t= moduli_helper<int, modulus<int>, Seq>::covering (p, 1000);

2.Transformers

The divide and conquer algorithm is implemented in crt_dicho.hpp:

#include <algebramix/crt_integer.hpp>
// let p be a covering obtained as described above
crt_dicho_transformer<integer> crter (p);

If the moduli are small, it is often faster to use the naive algorithm. While for large moduli the divide and conquer has soft linear cost. In crt_blocks.hpp is implemented a class to stack two different kinds of transformers in the following way:

#define Crter_naive crt_naive_transformer<integer, modulus<int> >
#define Crter_dicho crt_dicho_transformer<integer>
#define Crter crt_blocks_transformer<Crter_naive, Crter_dicho, 10>

Here 10 is the threshold between the two transformers: each block of 10 moduli is using the naive algorithm, and then the dichotomic algorithm is called with the moduli obtained from the products of those of each block.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License. If you don't have this file, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.