def mat_from_linear_func(m, n, func): mat = matrix(GF(2), n, m) for i, e in enumerate(reversed(range(m))): x = 1 << e res = tobin(func(x), n) mat.set_column(i, res) return mat
def as_matrix(self): assert self.is_linear() m = matrix(GF(2), self.n, self.m) for e in range(self.m): x = 1 << e m.set_column(self.m - 1 - e, tobin(self[x], self.n)) return m
def as_table(self, h, w=None): if w is None: assert 2**self.m % h == 0 w = 2**self.m // h else: assert h * w == 2**self.m m = matrix(h, w) for x in range(self.insize): m[divmod(x, w)] = self[x] return m
def mat_field_mul_const(field, c): assert field.base_ring() == GF(2) d = field.degree() m = matrix(GF(2), d, d) for i, e in enumerate(reversed(range(d))): x = 1 << e res = field.fetch_int(x) * field.fetch_int(c) res = tobin(res.integer_representation(), d) m.set_column(i, res) return m
def add_xor_ddt(self): axddt = matrix(ZZ, self.insize, self.outsize) for x in xrange(self.insize): for dx in xrange(1, self.insize): x2 = (x + dx) % self.insize y = self[x] y2 = self[x2] dy = y ^ y2 axddt[dx, dy] += 1 return axddt
def xor_add_ddt(self): axddt = matrix(ZZ, self.insize, self.outsize) for x in xrange(self.insize): for dx in xrange(1, self.insize): x2 = x ^ dx y = self[x] y2 = self[x2] dy = (y2 - y) % self.outsize axddt[dx, dy] += 1 return axddt
def add_add_ddt(self): addt = matrix(ZZ, self.insize, self.outsize) for x in xrange(self.insize): for dx in xrange(1, self.insize): x2 = (x + dx) % self.insize y = self[x] y2 = self[x2] dy = (y2 - y) % self.outsize addt[dx, dy] += 1 return addt
def kddt(self, k=3, zero_zero=False): kddt = matrix(ZZ, self.insize, self.outsize) for xs in Combinations(range(self.insize), k): ys = map(self, xs) dx = reduce(lambda a, b: a ^ b, xs) dy = reduce(lambda a, b: a ^ b, ys) kddt[dx, dy] += 1 if zero_zero: kddt[0, 0] = 0 return kddt
def cmul_xor_ddt(self, F=None): if F is None: F = GF(self.insize, name='a') cxddt = matrix(ZZ, self.insize, self.outsize) for x in xrange(1, self.insize): for dx in xrange(2, self.insize): x2 = (F.fetch_int(x) * F.fetch_int(dx)).integer_representation() y = self[x] y2 = self[x2] dy = y2 ^ y cxddt[dx, dy] += 1 return cxddt
def hdim(self, right_to_left=False): """ hdim[i,j] = i-th output bit contains monomial x1...xn/xj """ res = matrix(GF(2), self.in_bits, self.out_bits) anf = mobius(tuple(self)) for j in xrange(self.in_bits): mask = (1 << self.in_bits) - 1 mask ^= 1 << (self.in_bits - 1 - j) res.set_column(j, tobin(anf[mask], self.out_bits)) if right_to_left: res = res[::-1, ::-1] return res
def minilat(self, abs=False): """LAT taken on a basis points""" res = matrix(ZZ, self.m, self.n) for eu in xrange(self.m): for ev in xrange(self.n): u = Integer(2**eu) v = Integer(2**ev) for x in xrange(2**self.m): res[eu, ev] += ((u & x).popcount() & 1 == (v & self[x]).popcount() & 1) if abs: res = res.apply_map(_abs) return res
def xor_cmul_ddt(self, F=None): if F is None: F = GF(self.insize, name='a') xcddt = matrix(ZZ, self.insize, self.outsize) for x in xrange(self.insize): for dx in xrange(1, self.insize): x2 = x ^ dx y = self[x] y2 = self[x2] dy = (F.fetch_int(y2) * F.fetch_int(y) **(self.outsize - 2)).integer_representation() xcddt[dx, dy] += 1 return xcddt
def matrix_is_mds(mat): """@mat is considered as operator M*x""" n = mat.ncols() m = mat.nrows() mat2 = matrix(mat.base_ring(), m * 2, n) mat2[:m, :n] = identity_matrix(mat.base_ring(), m, n) mat2[m:, :n] = mat # linear code: x -> (x || M*x) C = LinearCode(mat2.transpose()) D = C.minimum_distance() K = n N = 2 * m # Singleton bound # MDS on equality assert D <= N - K + 1 return D == N - K + 1