Reputation: 557
I need to repeatedly evaluate a polynomial of the form
f(x)=c(0)+c(1)*x+...+c(k-1)*x^(k-1) mod p
where k is an integer, p is a large prime number and c(0),...,c(p) are between 1 and p. For my applications, k=10, p should be greater than 1000.
I would prefer to do this in Python and as fast as possible. I don't know enough about modulo arithmetic in Python to implement this efficiently (e.g. how to exploit that we can use Mersenne primes p=2^q-1 in which case about should use that multiplication is a register shift, avoid trouble by adding integers over different orders of magnitude,...).
Motivation: k-independent hashing, see https://en.wikipedia.org/wiki/K-independent_hashing. This seems to a very popular academic subject but I was not able to find any implementations for k>2.
Upvotes: 0
Views: 2040
Reputation: 21288
In general, you can compute the value of a polynomial using the following construction:
def value(poly, x):
"""Evaluates a polynomial POLY for a given x.
The polynomial is expressed as a list of coefficients, with
the coefficient for x ** N at poly[N].
This means that x ** 2 + 2*x + 3 is expressed as [3, 2, 1].
"""
v = 0
# Bit messy, but we're basically generating the indexes of
# our polynomial coefficients from highest to lowest
for coeff in reverse(poly):
v = v * x + coeff
return v
To evaluate this modulo a value, we can simply change the inner loop to v = v * x + poly[ix] % p
(and pass our modulus as the parameter p).
We can show that the example polynom (x^2 + 2x + 3) is computed correctly by unwinding the loop and see that what we have is (((1) * x + 2) * x + 3)
(each parenthesis level is one iteration through the loop), this can be simplified to 1 * x * x + 2 * x + 3, which is clearly the expected polynomial.
By using this, we should never end up with an intermediate value larger than p * x
.
Upvotes: 1