def lfsr_connection_polynomial(s): """ INPUT: - ``s`` -- a sequence of elements of a finite field of even length OUTPUT: - ``C(x)`` -- the connection polynomial of the minimal LFSR. This implements the algorithm in section 3 of J. L. Massey's article [Mas1969]_. EXAMPLES:: sage: F = GF(2) sage: F Finite Field of size 2 sage: o = F(0); l = F(1) sage: key = [l,o,o,l]; fill = [l,l,o,l]; n = 20 sage: s = lfsr_sequence(key,fill,n); s [1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0] sage: lfsr_connection_polynomial(s) x^4 + x + 1 sage: from sage.matrix.berlekamp_massey import berlekamp_massey sage: berlekamp_massey(s) x^4 + x^3 + 1 Notice that ``berlekamp_massey`` returns the reverse of the connection polynomial (and is potentially must faster than this implementation). """ # Initialization: FF = s[0].base_ring() R = PolynomialRing(FF, "x") x = R.gen() C = R.one() B = R.one() m = 1 b = FF.one() L = 0 N = 0 while N < len(s): if L > 0: r = min(L + 1, C.degree() + 1) d = s[N] + sum([(C.list())[i] * s[N - i] for i in range(1, r)]) if L == 0: d = s[N] if d == 0: m += 1 N += 1 if d > 0: if 2 * L > N: C = C - d * b**(-1) * x**m * B m += 1 N += 1 else: T = C C = C - d * b**(-1) * x**m * B L = N + 1 - L m = 1 b = d B = T N += 1 return C
def __call__(self, P): r""" Return a rational point P in the abstract Homset J(K), given: 0. A point P in J = Jac(C), returning P; 1. A point P on the curve C such that J = Jac(C), where C is an odd degree model, returning [P - oo]; 2. A pair of points (P, Q) on the curve C such that J = Jac(C), returning [P-Q]; 3. A list of polynomials (a,b) such that `b^2 + h*b - f = 0 mod a`, returning [(a(x),y-b(x))]. EXAMPLES:: sage: P.<x> = PolynomialRing(QQ) sage: f = x^5 - x + 1; h = x sage: C = HyperellipticCurve(f,h,'u,v') sage: P = C(0,1,1) sage: J = C.jacobian() sage: Q = J(QQ)(P) sage: for i in range(6): i*Q (1) (u, v - 1) (u^2, v + u - 1) (u^2, v + 1) (u, v + 1) (1) :: sage: F.<a> = GF(3) sage: R.<x> = F[] sage: f = x^5-1 sage: C = HyperellipticCurve(f) sage: J = C.jacobian() sage: X = J(F) sage: a = x^2-x+1 sage: b = -x +1 sage: c = x-1 sage: d = 0 sage: D1 = X([a,b]) sage: D1 (x^2 + 2*x + 1, y + x + 2) sage: D2 = X([c,d]) sage: D2 (x + 2, y) sage: D1+D2 (x^2 + 2*x + 2, y + 2*x + 1) """ if isinstance(P, (Integer, int)) and P == 0: R = PolynomialRing(self.value_ring(), 'x') return JacobianMorphism_divisor_class_field( self, (R.one(), R.zero())) elif isinstance(P, (list, tuple)): if len(P) == 1 and P[0] == 0: R = PolynomialRing(self.value_ring(), 'x') return JacobianMorphism_divisor_class_field( self, (R.one(), R.zero())) elif len(P) == 2: P1 = P[0] P2 = P[1] if is_Integer(P1) and is_Integer(P2): R = PolynomialRing(self.value_ring(), 'x') P1 = R(P1) P2 = R(P2) return JacobianMorphism_divisor_class_field(self, (P1, P2)) if is_Integer(P1) and is_Polynomial(P2): R = PolynomialRing(self.value_ring(), 'x') P1 = R(P1) return JacobianMorphism_divisor_class_field(self, (P1, P2)) if is_Integer(P2) and is_Polynomial(P1): R = PolynomialRing(self.value_ring(), 'x') P2 = R(P2) return JacobianMorphism_divisor_class_field(self, (P1, P2)) if is_Polynomial(P1) and is_Polynomial(P2): return JacobianMorphism_divisor_class_field(self, tuple(P)) if is_SchemeMorphism(P1) and is_SchemeMorphism(P2): return self(P1) - self(P2) raise TypeError("argument P (= %s) must have length 2" % P) elif isinstance( P, JacobianMorphism_divisor_class_field) and self == P.parent(): return P elif is_SchemeMorphism(P): x0 = P[0] y0 = P[1] R, x = PolynomialRing(self.value_ring(), 'x').objgen() return self((x - x0, R(y0))) raise TypeError( "argument P (= %s) does not determine a divisor class" % P)