def __or__(self, other): if isinstance(other, GcVector): return GcVector(self.value | other.value) elif isinstance(other, GCode): return GCode(self.value | mat24.gcode_to_vect(other.value)) else: return NotImplemented
def find_octad_permutation_odd(v, result, verbose=0): """ Find a suitable permutation for an octad. Similar to function ``find_octad_permutation`` in module ``mmgroup.dev.generators.gen_leech_reduce_n``. Here ``v, o, c`` are as in that function; but the scalar product of ``o`` and ``c`` must be 1. Apart from that operation is as in function ``find_octad_permutation``. We compute a permutation that maps octad ``o`` to the standard octad (0,1,2,3,4,5,6,7). If the cocode part ``c`` of ``v`` is not a suboctad of octad ``o`` then we map (one shortest representative of) ``c`` into the set (0,1,2,3,...7,8). """ coc = (v ^ mat24.ploop_theta(v >> 12)) & 0xfff w = mat24.gcode_weight(v >> 12) vect = mat24.gcode_to_vect((v ^ ((w & 4) << 21)) >> 12) src = mat24.vect_to_list(vect, 5) if mat24.cocode_weight(coc) == 4: sextet = mat24.cocode_to_sextet(coc) for i in range(0, 24, 4): syn = (1 << sextet[i]) | (1 << sextet[i + 1]) syn |= (1 << sextet[i + 2]) | (1 << sextet[i + 3]) special = syn & vect if special & (special - 1): break else: syn = mat24.cocode_syndrome(coc, 24) src.append(mat24.lsbit24(syn & ~vect)) return apply_perm(v, src, OCTAD_PLUS, 6, result, verbose)
def ref_gen_leech2_reduce_n(v, verbose=0): vtype = gen_leech2_subtype(v) subtype = vtype & 0xf out = [] if subtype & 1: coc = (v ^ mat24.ploop_theta(v >> 12)) & 0xfff syn = mat24.cocode_syndrome(coc) src = mat24.vect_to_list(syn, mat24.bw24(syn)) assert len(src) in [1, 3] lst = [1, 2, 3] if subtype == 3 else [0] apply_perm(v, src, lst, len(src), out) v = gen_leech2_op_atom(v, out[0]) out.append(0xC0000000 + ((v >> 12) & 0x7ff)) v = gen_leech2_op_atom(v, out[1]) out.append(0xB0000000 + ((v >> 13) & 0x800)) elif subtype == 6: gv = (v >> 12) & 0xfff vect = mat24.gcode_to_vect(gv) src = mat24.vect_to_list(vect, mat24.bw24(vect)) assert len(src) == 12 dest = STD_DODECAD if (vtype == 0x36): coc = (v ^ mat24.ploop_theta(v >> 12)) & 0xfff w = mat24.bw24(mat24.cocode_as_subdodecad(coc, gv)) if w & 2: dest = CPL_DODECAD pi = mat24.perm_from_dodecads(dest, src) out.append(0xA0000000 + mat24.perm_to_m24num(pi)) op_y_x(v, TABLE_DODECAD, out) elif subtype in [2, 4]: if vtype == 0x34: find_octad_permutation_odd(v, out) else: find_octad_permutation(v, out) op_y_x(v, TABLE_OCTAD, out) elif subtype in [0, 8]: if ((v & 0x7ff) == 0): out.append(0xA0000000) out.append(0xC0000000) x = 0x800 if v & 0x1800000 == 0x1800000 else 0 out.append(0x90000000 + x) else: syn = mat24.cocode_syndrome(v & 0x7ff, 0) src = mat24.vect_to_list(syn, mat24.bw24(syn)) j = mat24.bw24(syn) & 2 lst, y0 = ([2, 3], 0x200) if j else ([0, 1, 2, 3], 0x400) apply_perm(v, src, lst, len(lst), out) v = gen_leech2_op_atom(v, out[0]) y = y0 if v & 0x800000 else 0 out.append(0xC0000000 + y) v = gen_leech2_op_atom(v, out[1]) x = y0 if v & 0x1000000 else 0 out.append(0xB0000000 + x) else: raise ValueError("Bad subtype " + hex(vtype)) assert len(out) == 3 return vtype, np.array(out, dtype=np.uint32)
def vector(self): """Return bit vector corresponding to the Golay code word as an int. We have ``0 <= v < 0x1000000`` for the returned number ``v``. Bit ``i`` of the number ``v`` is the ``i``-th coordinate of the corresponding bit vector. """ return mat24.gcode_to_vect(self.value)
def __and__(self, other): if isinstance(other, GcVector): return GcVector(self.value & other.value) elif isinstance(other, GCode): return GCode(self.value & mat24.gcode_to_vect(other.value)) else: if import_pending: complete_import() return Cocode(self).__and__(other)
def __add__(self, other): if (isinstance(other, GCode)): return GCode((self.value ^ other.value) & 0xfff) elif isinstance(other, GcVector): return GcVector(mat24.gcode_to_vect(self.value) ^ other.value) elif other == 0: return GCode(self) else: return NotImplemented
def random_dodecad(): while True: gc = random.randint(0, 0xfff) if mat24.gcode_weight(gc) == 3: v = mat24.gcode_to_vect(gc) w, l = mat24.vect_to_bit_list(v) assert w == 12 l = l[:12] random.shuffle(l) return l
def __and__(self, other): if import_pending: complete_import() if isinstance(other, GCode): return PLoopIntersection(self, other) elif isinstance(other, Cocode): return Parity(mat24.scalar_prod(self.value, other.value)) elif isinstance(value, GcVector): return GcVector(mat24.gcode_to_vect(self.value) & other.value) else: return NotImplemented
def bits(self): """Return the Golay code word as a ``24``-bit vector. The function returns a list with ``24`` entries equal to ``0`` or ``1``. """ try: return self.bit_vector except: v = mat24.gcode_to_vect(self.value) self.bit_vector = ([(v >> i) & 1 for i in range(24)]) return self.bit_vector
def __init__(self, value): if import_pending: complete_import() if isinstance(value, Integral): self.value = value & 0xffffff elif isinstance(value, GCode): self.value = mat24.gcode_to_vect(value.value) elif isinstance(value, GcVector): self.value = value.value elif isinstance(value, PLoopIntersection): self.value = (mat24.gcode_to_vect(value.v1) & mat24.gcode_to_vect(value.v2) & 0xffffff) elif isinstance(value, str): self.value = randint(0, 0xffffff) if 'e' in value and not 'o' in value: if mat24.bw24(self.value) & 1: self.value ^= 1 << randint(0, 23) if 'o' in value and not 'e' in value: if not mat24.bw24(self.value) & 1: self.value ^= 1 << randint(0, 23) else: self.value = as_vector24(value)
def xi_reduce_odd_type4(v, verbose=0): r"""Compute power of :math:`\xi` that reduces a vector ``v`` Let ``v`` be a vector in the Leech lattice mod 2 in Leech lattice encoding. We assume that ``v`` is of subtype 0x43. We compute an exponent ``e`` such that :math:`\xi^e` maps ``v`` to a vector of subtype 0x42 or 0x44. The function returns ``e`` if ``v`` is mapped to type 0x42 and ``0x100 + e`` if ``v`` is mapped to type 0x44. A negative return value indicates that no such exponent ``e`` exists. """ assert v & 0x800 # Error if cocode part ov v is even coc = (v ^ mat24.ploop_theta(v >> 12)) & 0xfff # Obtain cocode as table of bit fields of 5 bits tab = mat24.syndrome_table(coc & 0x7ff) # Check if the syndrome bits are in 3 different MOG columns. # We first XOR bit field i with bit field (i-1)(mod 3) # and then zero the lowest two bits of each bit field. tab ^= ((tab >> 5) & 0x3ff) ^ ((tab & 0x1f) << 10) tab &= 0x739c # Now all three bit fields are nonzero iff the syndrome bits # are in three differnt columns. Next add 32 - 4 to each bit # field in order to produce a carry if the field is nonzero. tab += 0x739c # Next we isolate the three carry bits tab &= 0x8420 # Return -1 if all carry bits are set, i.e all syndrome bits # are in different columns. if (tab == 0x8420): return -1 # Let scalar be the scalar product of the Golay part of v # with the standard tetrad \omega scalar = (v >> 22) & 1 # Exponent for element \xi of G_x0 is 2 - scalar exp = 2 - scalar if verbose: w = gen_leech2_op_atom(v, 0x60000000 + exp) print( "Reducing c = %s, subtype %s, t=%s, e=%d, to v = %s, subtype %s" % (hex(mat24.cocode_syndrome(coc, 0)), hex(gen_leech2_subtype(v)), hex(tab), exp, hex( mat24.gcode_to_vect(w >> 12)), hex(gen_leech2_subtype(w)))) # Return exponent for \xi in the lower 4 bits of the retrun value; # Return 0 in bit 8 if all syndrome bits of v are in the same # MOG column and 1 in bit 8 otherwise. return ((tab != 0) << 8) + exp
def find_octad_permutation(v, result, verbose=0): coc = (v ^ mat24.ploop_theta(v >> 12)) & 0xfff w = mat24.gcode_weight(v >> 12) vect = mat24.gcode_to_vect((v ^ ((w & 4) << 21)) >> 12) src = mat24.vect_to_list(vect, 5) syn = mat24.cocode_syndrome(coc, src[0]) & ~vect if syn: v5 = (1 << src[0]) | (1 << src[1]) | (1 << src[2]) v5 |= syn special = mat24.syndrome(v5, 24) src = src[:3] src.append(mat24.lsbit24(special & vect)) src.append(mat24.lsbit24(vect & ~(special | v5))) src.append(mat24.lsbit24(syn)) syn &= ~(1 << src[-1]) src.append(mat24.lsbit24(syn)) return apply_perm(v, src, OCTAD, len(src), result, verbose)
def xi_reduce_dodecad(v, verbose=0): r"""Compute power of :math:`\xi` that reduces a vector ``v`` Let ``v`` be a vector in the Leech lattice mod 2 in Leech lattice encoding. We assume that ``v`` is of subtype 0x46. We compute an exponent ``e`` such that :math:`\xi^e` maps ``v`` to a vector of subtype 0x44. The function returns ``e`` if such an eponent exists. A negative return value indicates that no such exponent ``e`` exists. """ # Let ``vect`` be the Golay code part of v as a bit vector. vect = mat24.gcode_to_vect(v >> 12) # Set bit 4*i of s if all bits 4*i, 4*i+1, 4*i+2, 4*i+3 of # ``vect`` are equal, otherwise clear bit 4*i, for 0 <= i < 6. s1 = vect | (vect >> 2) s1 = s1 | (s1 >> 1) s0 = vect & (vect >> 2) s0 = s0 & (s0 >> 1) s = (s0 | ~s1) & 0x111111 # If the Golay code part of v is a docecad then either no or two # bits in s are set. Fail if no bit in s is set. if (s == 0): return -1 # Here two bits of s (in two different MOG columns) are set. # Set all bits in a MOG column if one bit is set in that column. # Thus the bits being set in s form a grey even octad. s *= 15 # Let 'coc' be the cocode part of v coc = v ^ mat24.ploop_theta(v >> 12) # Compute scalar product of octad s and ``coc`` in ``scalar`` tab = mat24.syndrome_table((mat24.recip_basis[0] ^ coc) & 0x7ff) scalar = s ^ (s >> (tab & 31)) ^ (s >> ((tab >> 5) & 31)) scalar ^= (s >> ((tab >> 10) & 31)) scalar &= 1 # The requested exponent is now equal to ``2 - scalar``. exp = 2 - scalar return exp
def apply_perm(v, src, dest, n, log_list, verbose=0): r"""Apply permutation to vector in Leech lattice mod 2. The function computes a permutation :math:`\pi` that maps the entries of the array ``src`` of length ``n`` to the entries of the array ``dest`` (of the same length) in the given order. Let :math:`v_2` be the vector in the Leech lattice mod 2 given by parameter ``v2``. The function returns :math:`v_2 x_\pi`. Parameter ``v2`` and the return value are given in Leech lattice encoding. Parameter ``p_res`` points to an integer where the function stores the element :math:`x_\pi` as a generator of the monster group as as described in file ``mmgroup_generators.h``. That generator is stored with tag ``MMGROUP_ATOM_TAG_IP`` so that we can compute the inverse of :math:`\pi` very efficiently. We compute the inverse of the lowest permutation (in lexical order) that maps ``dest[:n]`` to ``src[:n]``. """ res, p = mat24.perm_from_map(dest[:n], src[:n]) assert res > 0, (res, dest[:n], src[:n]) p_inv = mat24.inv_perm(p) p_num = mat24.perm_to_m24num(p) log_list.append(0xA0000000 + p_num) xd = (v >> 12) & 0xfff xdelta = (v ^ mat24.ploop_theta(xd)) & 0xfff m = mat24.perm_to_matrix(p_inv) xd = mat24.op_gcode_matrix(xd, m) xdelta = mat24.op_cocode_perm(xdelta, p_inv) v_out = (xd << 12) ^ xdelta ^ mat24.ploop_theta(xd) if verbose: print("Apply permutation (mapping v to gcode %s):\n%s" % (hex(mat24.gcode_to_vect(v_out >> 12)), p_inv)) return v_out
def reduce_type2_ortho(v, verbose=0): r"""Map (orthgonal) short vector in Leech lattice to standard vector This is a python implementation of the C function ``gen_leech2_reduce_type2_ortho`` in file ``gen_leech.c``. Let ``v \in \Lambda / 2 \Lambda`` of type 2 be given by parameter ``v`` in Leech lattice encoding. In the real Leech lattice, (the origin of) the vector ``v`` must be orthogonal to the standard short vector ``beta``. Here ``beta`` is the short vector in the Leech lattice propotional to ``e_2 - e_3``, where ``e_i`` is the ``i``-th basis vector of ``\{0,1\}^{24}``. Let ``beta'`` be the short vector in the Leech lattice propotional to ``e_2 + e_3``. Then the function constructs a ``g \in G_{x0}`` that maps ``v`` to ``beta'`` and fixes ``beta``. The element ``g`` is returned as a word in the generators of ``G_{x0}`` of length ``n \leq 6``. Each atom of the word ``g`` is encoded as defined in the header file ``mmgroup_generators.h``. The function stores ``g`` as a word of generators in the array ``pg_out`` and returns the length ``n`` of that word. It returns a negative number in case of failure, e.g. if ``v`` is not of type 2, or not orthogonal to ``beta'`` in the real Leech lattice. """ vtype = gen_leech2_subtype(v) if (vtype >> 4) != 2: raise ValueError("Vector is not short") if gen_leech2_type(v ^ 0x200) != 4: raise ValueError("Vector not orthogonal to standard vector") result = [] for _i in range(4): if verbose: coc = (v ^ mat24.ploop_theta(v >> 12)) & 0xfff vt = gen_leech2_subtype(v) coc_anchor = 0 if vt in [0x22]: w = mat24.gcode_weight(v >> 12) vect = mat24.gcode_to_vect((v ^ ((w & 4) << 21)) >> 12) coc_anchor = mat24.lsbit24(vect) coc_syn = Cocode(coc).syndrome_list(coc_anchor) gcode = mat24.gcode_to_vect(v >> 12) print("Round %d, v = %s, subtype %s, gcode %s, cocode %s" % (_i, hex(v & 0xffffff), hex(vt), hex(gcode), coc_syn)) assert vtype == gen_leech2_subtype(v) if vtype == 0x21: exp = xi_reduce_odd_type2(v) vtype = 0x22 elif vtype == 0x22: exp = xi_reduce_octad(v) if exp < 0: w = mat24.gcode_weight(v >> 12) vect = mat24.gcode_to_vect((v ^ ((w & 4) << 21)) >> 12) if vect & 0x0c: vect &= ~0x0c src = mat24.vect_to_list(vect, 2) + [2, 3] dest = [0, 1, 2, 3] else: src = [2, 3] + mat24.vect_to_list(vect, 3) v5 = (1 << src[2]) | (1 << src[3]) | (1 << src[4]) v5 |= 0x0c special = mat24.syndrome(v5, 24) src.append(mat24.lsbit24(special & vect)) dest = [2, 3, 4, 5, 6, 7] v = apply_perm(v, src, dest, len(src), result, verbose) exp = xi_reduce_octad(v) assert exp >= 0 vtype = 0x20 elif vtype == 0x20: if ((v & 0xffffff) == 0x800200): return np.array(result, dtype=np.uint32) syn = (mat24.cocode_syndrome(v, 0)) & ~0xc if syn and syn != 3: src = mat24.vect_to_list(syn, 2) + [2, 3] v = apply_perm(v, src, [0, 1, 2, 3], 4, result, verbose) exp = 2 - ((v >> 23) & 1) else: raise ValueError("WTF") if exp: exp = 0xE0000003 - exp v = gen_leech2_op_atom(v, exp) result.append(exp) raise ValueError("WTF1")
def reduce_type2(v, verbose=1): r"""Map (orthgonal) short vector in Leech lattice to standard vector This is a python implementation of the C function ``gen_leech2_reduce_type2`` in file ``gen_leech.c``. Let ``v \in \Lambda / 2 \Lambda`` of type 2 be given by parameter ``v`` in Leech lattice encoding. Let ``beta`` be the short vector in the Leech lattice propotional to ``e_2 - e_3``, where ``e_i`` is the ``i``-th basis vector of ``\{0,1\}^{24}``. Then the function constructs a ``g \in G_{x0}`` that maps ``v`` to ``beta``. The element ``g`` is returned as a word in the generators of ``G_{x0}`` of length ``n \leq 6``. Each atom of the word ``g`` is encoded as defined in the header file ``mmgroup_generators.h``. The function stores ``g`` as a word of generators in the array ``pg_out`` and returns the length ``n`` of that word. It returns a negative number in case of failure, e.g. if ``v`` is not of type 2. """ vtype = gen_leech2_subtype(v) if (vtype >> 4) != 2: raise ValueError("Vector is not short") result = [] for _i in range(4): if verbose: coc = (v ^ mat24.ploop_theta(v >> 12)) & 0xfff vt = gen_leech2_subtype(v) coc_anchor = 0 if vt in [0x22]: w = mat24.gcode_weight(v >> 12) vect = mat24.gcode_to_vect((v ^ ((w & 4) << 21)) >> 12) coc_anchor = mat24.lsbit24(vect) coc_syn = Cocode(coc).syndrome_list(coc_anchor) gcode = mat24.gcode_to_vect(v >> 12) print("Round %d, v = %s, subtype %s, gcode %s, cocode %s" % (_i, hex(v & 0xffffff), hex(vt), hex(gcode), coc_syn)) assert vtype == gen_leech2_subtype(v) if vtype == 0x21: exp = xi_reduce_odd_type2(v) vtype = 0x22 elif vtype == 0x22: exp = xi_reduce_octad(v) if exp < 0: w = mat24.gcode_weight(v >> 12) vect = mat24.gcode_to_vect((v ^ ((w & 4) << 21)) >> 12) src = mat24.vect_to_list(vect, 4) dest = [0, 1, 2, 3] v = apply_perm(v, src, dest, 4, result, verbose) exp = xi_reduce_octad(v) assert exp >= 0 vtype = 0x20 elif vtype == 0x20: exp = 0 # map v to stadard cocode word [2,3] if v & 0x7fffff != 0x200: syn = (mat24.cocode_syndrome(v, 0)) src = mat24.vect_to_list(syn, 2) v = apply_perm(v, src, [2, 3], 2, result, verbose) # correct v2 if v2 is the cocode word [2,3] + Omega if v & 0x800000: atom = 0xC0000200 # operation y_d such that d has odd scalar # product with cocode word [2,3] v = gen_leech2_op_atom(v, atom) result.append(atom) assert v & 0xffffff == 0x200 return np.array(result, dtype=np.uint32) else: raise ValueError("WTF") if exp: exp = 0xE0000003 - exp v = gen_leech2_op_atom(v, exp) result.append(exp) raise ValueError("WTF1")
def mul24_y(v, y): y1 = gcode_to_vect(y) for i in range(24): if (y1 >> i) & 1: v[i] = -v[i]
def reduce_type4_std(v, verbose=0): r"""Map type-4 vector in Leech lattice to standard vector This is (almost) a python implementation of the C function ``gen_leech2_reduce_type4`` in file ``gen_leech.c``. Let ``v \in \Lambda / 2 \Lambda`` of type 4 be given by parameter ``v`` in Leech lattice encoding. Let ``Omega`` be the type- vector in the Leech lattice corresponding to the standard coordinate frame in the Leech lattice. Then the function constructs a ``g \in G_{x0}`` that maps ``v`` to ``Omega``. The element ``g`` is returned as a word in the generators of ``G_{x0}`` of length ``n \leq 6``. Each atom of the word ``g`` is encoded as defined in the header file ``mmgroup_generators.h``. The function stores ``g`` as a word of generators in the array ``pg_out`` and returns the length ``n`` of that word. It returns a negative number in case of failure, e.g. if ``v`` is not of type 4. We remark that the C function ``gen_leech2_reduce_type4`` treats certain type-4 vectors ``v`` in a special way as indicated in function ``reduce_type4``. """ if verbose: print("Transforming type-4 vector %s to Omega" % hex(v & 0x1ffffff)) vtype = gen_leech2_subtype(v) result = [] for _i in range(5): coc = (v ^ mat24.ploop_theta(v >> 12)) & 0xfff if verbose: vt = gen_leech2_subtype(v) coc_anchor = 0 if vt in [0x42, 0x44]: w = mat24.gcode_weight(v >> 12) vect = mat24.gcode_to_vect((v ^ ((w & 4) << 21)) >> 12) coc_anchor = mat24.lsbit24(vect) coc_syn = Cocode(coc).syndrome_list(coc_anchor) gcode = mat24.gcode_to_vect(v >> 12) print("Round %d, v = %s, subtype %s, gcode %s, cocode %s" % (_i, hex(v & 0xffffff), hex(vt), hex(gcode), coc_syn)) assert vtype == gen_leech2_subtype(v) if vtype == 0x48: if verbose: res = list(map(hex, result)) print("Transformation is\n", res) return np.array(result, dtype=np.uint32) elif vtype == 0x40: if v & 0x7ffbff: syn = mat24.cocode_syndrome(coc, 0) src = mat24.vect_to_list(syn, 4) v = apply_perm(v, src, LSTD, 4, result, verbose) #print("after type 40", hex(v), Cocode(v).syndrome(0)) exp = 2 - ((v >> 23) & 1) vtype = 0x48 elif vtype in [0x42, 0x44]: exp = xi_reduce_octad(v) if exp < 0: v = find_octad_permutation(v, result, verbose) exp = xi_reduce_octad(v) assert exp >= 0 vtype = 0x40 elif vtype == 0x46: exp = xi_reduce_dodecad(v, verbose) if exp < 0: vect = mat24.gcode_to_vect(v >> 12) src = mat24.vect_to_list(vect, 4) v = apply_perm(v, src, LSTD, len(src), result, verbose) exp = xi_reduce_dodecad(v, verbose) assert exp >= 0 vtype = 0x44 elif vtype == 0x43: exp = xi_reduce_odd_type4(v, verbose) if exp < 0: vect = mat24.gcode_to_vect(v >> 12) syn = mat24.cocode_syndrome(coc, 24) src = mat24.vect_to_list(syn, 3) #print("coc list", src) v = apply_perm(v, src, LSTD[1:], len(src), result, verbose) exp = xi_reduce_odd_type4(v, verbose) assert exp > 0 vtype = 0x42 + ((exp & 0x100) >> 7) exp &= 3 else: raise ValueError("WTF") if exp: exp = 0xE0000003 - exp v_old = v v = gen_leech2_op_atom(v, exp) assert v & 0xfe000000 == 0, (hex(v_old), hex(exp), hex(v)) result.append(exp) raise ValueError("WTF1")
def leech2_start_type4(v): """Return subtype of a Leech lattice frame ``v`` used for reduction The function returns the subtype of a vector ``v`` of type 4 in the Leech lattice modulo 2. Parameter ``v2`` must be in Leech lattice encoding. The function returns the subtype of ``v`` that will be used for reduction in function ``gen_leech2_reduce_type4``. In that function we take care of the special case that ``v + v0`` is of type 2 for a specific short vector ``v0``. A simpler (but slower) implementation of thhis function is: If ``v ^ v0`` is of type 2 the return the subtype of ``v ^ v0``. Otherwise return the subtype of ``v``. The function returns 0 if ``v`` is equal to ``Omega`` and a negative value if ``v`` has not type 4. This is a refernece implementation for function ``gen_leech2_start_type4()`` in file ``gen_leech.c``. """ if v & 0x7ff800 == 0: # Then v or v + Omega is an even cocode element. # Return 0 if v == Omega and -1 if v == 0. if v & 0x7fffff == 0: return 0 if v & 0x800000 else -1 # Let w be the cocode weight. Return -2 if w == 2. if mat24.cocode_weight(v) != 4: return -2 # Here v has type 4. Let v23 be the standard type-2 vector. # Return 0x20 if v ^ v23 has type 2 and 0x40 otherwise. return 0x20 if mat24.cocode_weight(v ^ 0x200) == 2 else 0x40 if mat24.scalar_prod(v >> 12, v): # Then v has type 3 and we return -3 return -3 if v & 0x800: # Then the cocode word 'coc' of v is odd. coc = (v ^ mat24.ploop_theta(v >> 12)) & 0xfff syn = mat24.cocode_syndrome(coc) # If 'coc' has weight 1 then v is of type 2 and we return -2. if (syn & (syn - 1)) == 0: return -2 # Here v is of type 4. # Return 0x21 if v ^ v23 is of type 2 and 0x43 otherwise. if (syn & 0xc) == 0xc and (v & 0x200000) == 0: return 0x21 return 0x43 # Let w be the weight of Golay code part divided by 4 w = mat24.gcode_weight(v >> 12) if w == 3: # Then the Golay code part of v is a docecad and we return 0x46. return 0x46 # Here the Golay code part of v is a (possibly complemented) octad. # Add Omega to v if Golay part is a complemented octad. v ^= (w & 4) << 21 # Put w = 1 if that part is an octad and w = 0 otherwise. w = (w >> 1) & 1 # Let 'octad' be the octad in the Golay code word in vector rep. octad = mat24.gcode_to_vect(v >> 12) coc = v ^ mat24.ploop_theta(v >> 12) # cocode element of v # Return -2 if v is of type 2. sub = suboctad_type(octad, w, coc) if sub == 0: return -2 # Return 0x22 if v ^ v23 is shsort if suboctad_type(octad, w, coc ^ 0x200) == 0: return 0x22 # Otherwise return the subtype of v return 0x44 if sub & 2 else 0x42
def scalar_prod_table_entry(self, v1): v = mat24.gcode_to_vect(v1) return [ self.smask(self.P, v >> j) for j in range(0, 32, self.INT_FIELDS) ]