class Faulhaber(ModularSolver): def __init__(self, max_degree, modulus, primitive_root, *args, **kwargs): super(Faulhaber, self).__init__(modulus=modulus, primitive_root=primitive_root, *args, **kwargs) self._max_degree = max_degree self._bernoulli = Bernoulli(modulus=modulus, primitive_root=primitive_root) self._bn = list(self._bernoulli.bernoulli(max_degree)) self._choose = Choose(modulus=modulus, primitive_root=primitive_root) def base_polynomial(self, p, scalar=1): # returns a Polynomial P (of degree p + 1) such that P(x) == scalar * sum(i^p for i in range(1, x + 1)) if p + 1 > self._max_degree: raise ValueError # compute p(x) = sum(i^p for i in range(1, n + 1)) coef = list(repeat(0, p + 2)) for i in range(p + 1): coef[p + 1 - i] = self.mult(self._choose.choose(p + 1, i), self._bn[i]) poly = Polynomial(coef, modulus=self._modulus, primitive_root=self._primitive_root) poly.scalarmult(self.div(scalar, p + 1)) return poly def general_polynomial(self, poly): # returns a Polynomial P such that P(x) == sum(poly(i) for i in range(1, x + 1)) p = Polynomial([], modulus=self._modulus, primitive_root=self._primitive_root) for i, c in enumerate(poly._coef): if c: p.add_polynomial(self.base_polynomial(i, c)) return p
def __init__(self, max_degree, modulus, primitive_root, *args, **kwargs): super(Faulhaber, self).__init__(modulus=modulus, primitive_root=primitive_root, *args, **kwargs) self._max_degree = max_degree self._bernoulli = Bernoulli(modulus=modulus, primitive_root=primitive_root) self._bn = list(self._bernoulli.bernoulli(max_degree)) self._choose = Choose(modulus=modulus, primitive_root=primitive_root)
def test_mod_31(self): c = Choose(31, 3) self.assertEqual(6, c.choose(4, 2)) self.assertEqual(6 * 5 * 4 / (3 * 2 * 1) % 31, c.choose(6, 3))