Skip to content

Issue with NTT and GF(2) (and other FieldArray) #542

@iyanmv

Description

@iyanmv

Hi,

If the array passed to ntt is a GF(2) array, then the default modulus will never satisfy the required criteria (unless the array has size 1). This is because the characteristic of the field is used, i.e., p=2, as modulus in

modulus = type(x).characteristic

which causes _ntt to never enter this loop to compute a valid modulus

galois/src/galois/_ntt.py

Lines 249 to 254 in 25baec4

if modulus is None:
m = int(np.ceil(np.max(x) / size)) # The smallest m such that modulus > max(x)
while not is_prime(m * size + 1):
m += 1
modulus = m * size + 1
m = (modulus - 1) // size

This is documented in the docstring, though, so perhaps I'm not understanding something here:

(...) However, if $x$ is a $\mathrm{GF}(p)$ array, then None corresponds to $p$ from the specified field.

I would expect that calling ntt should work correctly, by default, on any FieldArray. For example, I think this code should work:

from galois import GF2, ntt

ntt(GF2.Random(10))

But at the moment it raises a ValueError that the user did not passed.

ValueError: Argument 'modulus' must equal m * size + 1, where 'size' is the size of the NTT transform.

A workaround, is to manually choose a valid modulus, e.g.

import numpy as np
from galois import GF2, ntt, intt

arr = GF2.Random(10)
assert np.array_equal(arr, intt(ntt(arr, modulus=11)))

This also happens with other fields. For example,

from galois import GF

gf = GF(3)

arr = gf.Random(10)
ntt(gf)

Commenting the two lines from ntt solves the issue for me:

galois/src/galois/_ntt.py

Lines 114 to 115 in 25baec4

if modulus is None and isinstance(x, FieldArray):
modulus = type(x).characteristic

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions