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 test_no_mod(self): expected = [1, 1.0/2.0, 1.0/6.0, 0, -1.0/30.0, 0, 1.0/42] expected = map(lambda x: round(x, 5), expected) b = Bernoulli(0, 0) actual = list(b.bernoulli(6)) actual = map(lambda x: round(x, 5), actual) self.assertEqual(expected, actual)
def test_low_mod(self): m = ModularSolver(modulus=31,primitive_root=3) numerators = [1, 1, 1, 0, -1, 0, 1] denominators = [1, 2, 6, 1, 30, 1, 42] expected = [m.div(n, d) for n, d in izip(numerators, denominators)] b = Bernoulli(modulus=31, primitive_root=3) actual = list(b.bernoulli(6)) self.assertEqual(expected, actual)