NTT - Number Theoretic Transform
Overview
The Number Theoretic Transform (NTT) is a variant of the Fourier Transform used over finite fields, particularly those of integers modulo a prime number. NTT operates in a discrete domain and is used primarily in applications requiring modular arithmetic, such as cryptography and polynomial multiplication.
NTT is defined similarly to the Discrete Fourier Transform (DFT), but instead of using complex roots of unity, it uses roots of unity within a finite field. The definition hinges on the properties of the finite field, specifically the existence of a primitive root of unity of order (where is typically a power of 2), and the modulo operation is performed with respect to a specific prime number that supports these roots.
Formally, given a sequence of integers , the NTT of this sequence is another sequence of integers , computed as follows:
where:
- is the size of the input sequence and is a power of 2,
- is a prime number such that for some integer , ensuring that supports the existence of th roots of unity,
- is a primitive th root of unity modulo , meaning and no smaller positive power of is congruent to 1 modulo ,
- ranges from 0 to , and it indexes the output sequence.
NTT is particularly useful because it enables efficient polynomial multiplication under modulo arithmetic, crucial for algorithms in cryptographic protocols and other areas requiring fast modular arithmetic operations.
There exists also INTT which is the inverse operation of NTT. INTT can take as input an output sequence of integers from an NTT and reconstruct the original sequence.
C++ API
Ordering
The Ordering
enum defines how inputs and outputs are arranged for the NTT operation, offering flexibility in handling data according to different algorithmic needs or compatibility requirements. It primarily affects the sequencing of data points for the transform, which can influence both performance and the compatibility with certain algorithmic approaches. The available ordering options are:
-
kNN
(Natural-Natural): Both inputs and outputs are in their natural order. This is the simplest form of ordering, where data is processed in the sequence it is given, without any rearrangement. -
kNR
(Natural-Reversed): Inputs are in natural order, while outputs are in bit-reversed order. This ordering is typically used in algorithms that benefit from having the output in a bit-reversed pattern. -
kRN
(Reversed-Natural): Inputs are in bit-reversed order, and outputs are in natural order. This is often used with the Cooley-Tukey FFT algorithm. -
kRR
(Reversed-Reversed): Both inputs and outputs are in bit-reversed order. -
kNM
(Natural-Mixed): Inputs are provided in their natural order, while outputs are arranged in a digit-reversed (mixed) order. This ordering is good for mixed radix NTT operations, where the mixed or digit-reversed ordering of outputs is a generalization of the bit-reversal pattern seen in simpler, radix-2 cases. -
kMN
(Mixed-Natural): Inputs are in a digit-reversed (mixed) order, while outputs are restored to their natural order. This ordering would primarily be used for mixed radix NTT
Choosing an algorithm is heavily dependent on your use case. For example Cooley-Tukey will often use kRN
and Gentleman-Sande often uses kNR
.
enum class Ordering {
kNN, /**< Inputs and outputs are in natural-order. */
kNR, /**< Inputs are in natural-order and outputs are in bit-reversed-order. */
kRN, /**< Inputs are in bit-reversed-order and outputs are in natural-order. */
kRR, /**< Inputs and outputs are in bit-reversed-order. */
kNM, /**< Inputs are in natural-order and outputs are in digit-reversed-order. */
kMN /**< Inputs are in digit-reversed-order and outputs are in natural-order. */
};
NTTConfig
Struct
The NTTConfig
struct configures the NTT operation. It allows customization of parameters like the batch size, column batch computation, order of inputs and outputs etc.
template <typename S>
struct NTTConfig {
icicleStreamHandle stream;
S coset_gen;
int batch_size;
bool columns_batch;
Ordering ordering;
bool are_inputs_on_device;
bool are_outputs_on_device;
bool is_async;
ConfigExtension* ext = nullptr;
};