def inv_op_unit(self, tag, d, j): if tag == 'X': tag1 = 'X' d1 = d ^ self.lin_d[0] j1 = j sign = (self.sign_XYZ[d] & 1) sign ^= (self.lin_i[0] >> j) & 1 if self.odd: cc = m24.vect_to_cocode(1 << j) sign ^= m24.scalar_prod(d, cc) elif tag in 'ZY': s = self.odd ^ (tag == 'Y') tag1 = 'ZY'[s] s += 1 d1 = d ^ self.lin_d[s] j1 = j sign = (self.sign_XYZ[d] >> s) & 1 sign ^= (self.lin_i[s] >> j) & 1 elif tag == 'T': tag1 = 'T' d1 = d te = self.s_T[d] so_exp = _as_suboctad(self.f, d) assert te & 0x3f == so_exp, (hex(te), hex(so_exp)) j1 = j ^ (te & 0x3f) sign = m24.suboctad_scalar_prod(j, (te >> 8) & 0x3f) sign ^= (te >> 14) & 1 sign ^= m24.suboctad_weight(j) & self.odd & 1 assert ((te >> 15) ^ self.odd) & 1 == 0 else: raise ValueError("Illegal tag " + str(tag)) return sign & 1, tag1, d1, j1
def mul_Tp(tag, octad, sub, g): d = m24.octad_to_gcode(octad) c = m24.suboctad_to_cocode(sub, d) eps, pi, rep = g.cocode, g.perm, g.rep d1 = m24.op_ploop_autpl(d, rep) c1 = m24.op_cocode_perm(c, pi) s = d1 >> 12 s ^= (eps >> 11) & 1 & m24.suboctad_weight(sub) octad1 = m24.gcode_to_octad(d1) sub1 = m24.cocode_to_suboctad(c1, d1) return s, tag, octad1, sub1
def test_octads(): print("") OMEGA = ~PLoop(0) for i in range(200): no = randint(0, 758) o = Octad(no) assert o == PLoop(mat24.octad_to_gcode(no)) assert o == Octad(sample(o.bit_list, 5)) assert o.octad == no o_signbit, o_cpl = randint(0, 1), randint(0, 1) signed_o = PLoopZ(o_signbit, o_cpl) * o assert signed_o.octad == no assert signed_o.sign == (-1)**o_signbit assert o.gcode == mat24.octad_to_gcode(no) assert signed_o.gcode == (o * PLoopZ(0, o_cpl)).gcode assert signed_o.split_octad() == (o_signbit, o_cpl, o) nsub = randint(0, 63) sub = (-1)**o_signbit * SubOctad(no, nsub) sub1 = (-1)**o_signbit * SubOctad(o, nsub) sub_weight = mat24.suboctad_weight(nsub) assert sub == sub1 assert o == (-1)**o_signbit * Octad(sub) * OMEGA**sub_weight assert sub.octad_number() == no ploop, cocode = sub.isplit() sign, gcode = (-1)**(ploop >> 12), ploop & 0xfff assert gcode == o.gcode ^ 0x800 * sub_weight #assert sub.suboctad == nsub assert sign == signed_o.sign == (-1)**o_signbit coc = mat24.suboctad_to_cocode(nsub, o.gcode) assert cocode == coc assert Cocode(sub) == Cocode(coc) assert sub == SubOctad(sub.sign * o, Cocode(coc)) assert sub == sub.sign * SubOctad(no, Cocode(coc)) o2 = Octad(randint(0, 758)) sub2 = SubOctad(o, o2) assert Cocode(sub2) == Cocode(o & o2) assert len(Cocode(sub2)) // 2 & 1 == int((o & o2) / 2) t_sign, t_tag, t_i0, t_i1 = sub.vector_tuple() assert t_tag == 'T' assert t_sign == sign, (hex(sub.value), t_sign, o_signbit) assert t_i0 == no assert t_i1 == nsub
class Perm64_xy(MM_Op): """Yet to be documented!!!!!!!!!!!!!!!!!!!!! """ weights = sum(mat24.suboctad_weight(j) << j for j in range(64)) mask = (1 << 64) - 1 hi_list = [0, mask, weights, weights ^ mask] directives = {} def __init__(self, p): """Initialise for calulations with small integers modulo p p+1 must be a power of two. Calculations modulo p are described in more detail in the base classes of this class. """ super(Perm64_xy, self).__init__(p) self.t_hi = self.hi_table() self.t_lo = self.lo_table() self.tables.update(self.make_tables()) def table_value(self, index): i0 = index & 0x3f v = sum(mat24.suboctad_scalar_prod(j, i0) << j for j in range(64)) return self.hi_list[(index >> 6) & 3] ^ v def table_part(self, index): tbl = self.table_value(index) p, i_fields = self.P, self.INT_FIELDS return [self.smask(p, tbl >> i) for i in range(0, 64, i_fields)] def hi_table(self): return sum((self.table_part(i) for i in range(0, 256, 16)), []) def lo_table(self): return sum((self.table_part(i) for i in range(16)), []) def make_tables(self): return { "TABLE_PERM64_XY_LOW": self.t_lo, "TABLE_PERM64_XY_HIGH": self.t_hi, }
def op_xy(v, eps, e, f): """Multiply unit vector v with group element This function multplies a (multiple of a) unit vector v with the group element g = d_<eps> * (x_<e>)**(-1) * (y_<f>)**(-1) . It returns the vector w = v * g. This function uses the same formula for calculating w = v * g, which is used in the implementation of the monster group for computing v = w * g ** (-1). Input vector v must be given as a tuple as described in class mmgroup.structures.abstract_mm_rep_space.AbstractMmRepSpace. Output vector is returned as a tuple of the same shape. """ if len(v) == 3: v = (1,) + v v_value, v_tag, v_d, v_j = v parity = (eps >> 11) & 1 # parity of eps if v_tag == 'X': w_d = v_d ^ (f & 0x7ff) sign = v_d >> 12 d = v_d & 0x7ff c = m24.vect_to_cocode(1 << v_j) sign += m24.gcode_weight(e ^ f) sign += m24.gcode_weight(f) sign += m24.gcode_weight(d) * (parity + 1) sign += m24.gcode_weight(d ^ e ^ f) sign += m24.scalar_prod(e, c) cc = c if parity else 0 cc ^= eps ^ m24.ploop_theta(f) ^ m24.ploop_cap(e, f) sign += m24.scalar_prod(d, cc) sign += f >> 12 return (-1)**sign * v_value, 'X', w_d, v_j elif v_tag in 'YZ': tau = v_tag == 'Y' sigma = (tau + parity) & 1 w_tag = "ZY"[sigma] sign = (v_d >> 12) + ((v_d >> 11) & tau) w_d = (v_d ^ e ^ (f & ~-sigma)) & 0x7ff #print("YZ, w_d", hex(w_d), hex(v_d ^ (e & 0x7ff) ^ (f & sigma_1)), err) # Next we check the sign d = v_d & 0x7ff c = m24.vect_to_cocode(1 << v_j) sign += m24.ploop_cocycle(f, e) * (sigma + 1) sign += m24.gcode_weight(f) * (sigma) sign += m24.gcode_weight(d ^ e) sign += m24.gcode_weight(d ^ e ^ f) sign += m24.scalar_prod(f, c) cc = eps ^ m24.ploop_theta(e) cc ^= m24.ploop_theta(f) * ((sigma ^ 1) & 1) sign += m24.scalar_prod(d, cc) sign += (e >> 12) + (f >> 12) * (sigma + 1) sign += ((e >> 11) & sigma) return (-1)**sign * v_value, w_tag, w_d, v_j elif v_tag == 'T': d = m24.octad_to_gcode(v_d) w_j = v_j ^ as_suboctad(f, d) sign = m24.gcode_weight(d ^ e) + m24.gcode_weight(e) sign += m24.scalar_prod(d, eps) sign += m24.suboctad_scalar_prod(as_suboctad(e ^ f, d), v_j) sign += m24.suboctad_weight(v_j) * parity return (-1)**sign * v_value, 'T', v_d, w_j elif v_tag in 'BC': m = v_tag == 'C' c = m24.vect_to_cocode((1 << v_d) ^ (1 << v_j)) n = m ^ m24.scalar_prod(f, c) w_tag = "BC"[n] w_i, w_j = max(v_d, v_j), min(v_d, v_j) sign = m * parity + m24.scalar_prod(e ^ f, c) return (-1)**sign * v_value, w_tag, w_i, v_j elif v_tag == 'A': w_i, w_j = max(v_d, v_j), min(v_d, v_j) c = m24.vect_to_cocode((1 << v_d) ^ (1 << v_j)) sign = m24.scalar_prod(f, c) return (-1)**sign * v_value,'A', w_i, v_j else: raise ValueError("Bad tag " + v_tag)