def get_lag(self): l = 1 v = self.c while l <= self.n and gf2.dot(v, self.a) == 0: l = l + 1 v = gf2.dot(v, self.B) return l
def CF2(self): B = self.B a0 = np.zeros(self.n, dtype=int) a0[0] = 1 # bring B to the Frobenius form P = self.A() B = gf2.dot(gf2.dot(gf2.inv(P), B), P) a = gf2.dot(gf2.inv(P), self.a) c = gf2.dot(self.c, P) # use the facts: A^{-1}.B.A = B and A^{-1}.a = a0 return XS(a0, B, gf2.dot(c, P))
def inv(self): assert (self.is_invertible()) if self.get_type() == 1: B1 = gf2.inv(self.B) a1 = gf2.dot(B1, self.a) c1 = gf2.dot(self.c, B1) else: M = gf2.inv(self.M()) a1 = M[:-1, -1] B1 = M[:-1, :-1] c1 = M[-1, :-1] return XS(a1, B1, c1)
def is_strong_regular(self): if self.is_regular() == False: return False l = self.get_lag() if l == 1: return True Bl = self.B for i in range(1, l): Bl = gf2.dot(Bl, self.B) m = v = self.c for i in range(1, self.n): v = gf2.dot(v, Bl) m = np.vstack((m, v)) return gf2.det(m) == 1
def CF1(self): B = self.B c0 = np.zeros(self.n, dtype=int) c0[-1] = 1 # bring B to the Frobenius form P = self.A() B = gf2.dot(gf2.dot(gf2.inv(P), B), P) a = gf2.dot(gf2.inv(P), self.a) c = gf2.dot(self.c, P) # find P = P(c): P.B.P^{-1} = B and c.P^{-1} = c0 M = gf2.eye(self.n) P = gf2.dot(c, M) b = B[:, -1] for i in range(self.n - 1, 0, -1): M = gf2.dot(B, M) M = gf2.add(M, b[i] * gf2.eye(self.n)) P = np.vstack((gf2.dot(c, M), P)) return XS(gf2.dot(P, a), B, c0)
def GNAF2(circ, t): a, B, c = circ.aBc() if t < circ.n: return 0 if t == circ.n: return 1 f = gf2.add(a, B[:, -1]) min_d = t for s0 in itertools.product([0, 1], repeat=circ.n): d = np.sum(s0) if d == 0: continue s = list(s0) for i in range(t - circ.n): s = np.append(s[1:], gf2.dot(s, f)) d = d + s[-1] if d < min_d: min_d = d return min_d
def rho2(self): v = self.c gamma = np.zeros(self.n) for i in range(0, self.n): gamma[i] = gf2.dot(v, self.a) v = gf2.dot(v, self.B) ret = 0 A1 = gf2.inv(self.A()) for r in range(0, self.n): y = np.zeros(self.n) y[r] = 1 y[r + 1:] = gamma[:self.n - 1 - r] y = gf2.dot(y, A1) for i in range(0, self.n): y = gf2.dot(y, self.B) t = 0 while True: t = t + 1 if gf2.dot(y, self.a) != gamma[self.n - r + t - 2]: break y = gf2.dot(y, self.B) if t > ret: ret = t return self.n + ret
def A(self): m = v = self.a for i in range(1, self.n): v = gf2.dot(v, self.B.T) m = np.vstack((m, v)) return m.T
def C(self): m = v = self.c for i in range(1, self.n): v = gf2.dot(v, self.B) m = np.vstack((v, m)) return m
def is_invertible(self): if gf2.det(self.B) == 0: return gf2.det(self.M()) == 1 return gf2.dot(gf2.dot(self.c, gf2.inv(self.B)), self.a) == 0