def gen_xi_leech_to_short(x1): """Convert Leech lattice to short vector encoding. Both, Leech lattice and short vector encoding of a short vector in Q_x are decribed in the header of this module. The function returns the short vector encoding of element x1 given in Leech lattice encoding. The function returns 0 if the vector x1 is not short. """ sign = (x1 >> 24) & 1 x1 ^= Mat24.ploop_theta(x1 >> 12) gcodev = Mat24.gcode_to_vect(x1 >> 12) cocodev = Mat24.cocode_syndrome(x1, min(23, Mat24.lsbit24(gcodev)) ) w = Mat24.gcode_weight(x1 >> 12) if x1 & 0x800: if (Mat24.bw24(cocodev) > 1 or Mat24.scalar_prod(x1 >> 12, x1) != (w & 1)): return 0 y = Mat24.lsbit24(cocodev) code = (x1 & 0x7ff000) >> 7 | y box = 4 + (code >> 15) code &= 0x7fff else: if w == 3: return 0 elif w in [2,4]: if w == 4: gcodev ^= 0xffffff x1 ^= 0x800000 w_bad = (Mat24.bw24(cocodev) ^ 2 ^ w) & 3 if w_bad or (cocodev & gcodev) != cocodev: return 0 c = Mat24.extract_b24(cocodev, gcodev) if (c & 0x80): c ^= 0xff y1 = Mat24.gcode_to_octad(x1 >> 12) code = (y1 << 6) | (c >> 1) if code >= 24000: # this is (15 + 360) * 64 code -= 24000 box = 3 elif code >= 960: # this is 15 * 64 code -= 960 box = 2 else: code += 1536 box = 1 else: y1 = Mat24.lsbit24(cocodev) cocodev ^= 1 << y1 y2 = Mat24.lsbit24(cocodev) if cocodev != (1 << y2) or y1 >= 24: return 0 code = 384 * (w & 2) + 32 * y2 + y1 box = 1 return (box << 16) | (sign << 15) | code
def gen_xi_short_to_leech(x1): """Convert short vector to Leech lattice encoding. Both, Leech lattice and short vector encoding of a short vector in Q_x are decribed in the header of this module. The function returns the Leech lattice encoding of element x1 given in short vector encoding. The function returns 0 for an illegal input x1. """ box, sign, code = x1 >> 16, (x1 >> 15) & 1, x1 & 0x7fff octad = 0xffff if box == 1: if code < 1536: # this is 2 * 24 * 32 gcode = code >= 768 if gcode: code -= 768 gcode <<= 11 i, j = code >> 5, code & 31 cocode = Mat24.vect_to_cocode((1 << i) ^ (1 << j)) if cocode == 0 or cocode & 0x800: return 0 elif code < 2496: # this is 2 * 24 * 32 + 15 * 64 octad = code - 1536 else: return 0 elif box == 2: if code >= 23040: # this is 360 * 64 return 0 octad = code + 960 # this is 15 * 64 elif box == 3: if code >= 24576: # this is 384 * 64 return 0 octad = code + 24000 # this is (15 + 360) * 64 elif box < 6: code += (box - 4) << 15 cocode = Mat24.vect_to_cocode(1 << (x1 & 31)) if cocode == 0: return 0 gcode = (code >> 5) & 0x7ff w = Mat24.gcode_weight(gcode) ^ Mat24.scalar_prod(gcode, cocode) gcode ^= (w & 1) << 11 else: return 0 if octad < 48756: # this is 759 * 64 cc = octad & 0x3f w = Mat24.bw24(cc) cc = (cc << 1) ^ (w & 1) w += w & 1 gcode = Mat24.octad_to_gcode(octad >> 6) gcodev = Mat24.gcode_to_vect(gcode) cocode = Mat24.vect_to_cocode(Mat24.spread_b24(cc, gcodev)) gcode ^= ((w >> 1) & 1) << 11 cocode ^= Mat24.ploop_theta(gcode) return (sign << 24) | (gcode << 12) | cocode
def y_table(g, cocodes, sign, code_omega, cocode_x, verbose = 0): """Return table for function ``gen_leech2_reduce_n`` This table is used to map an entry :math:`x_d x_\delta`, where :math:`d` is a (signed) octad or dodecad, and where :math:`\delta` is even, to a standard form. The table is to be used for a fixed Golay code element :math:`d` up to sign and up to a factor :math:`\Omega`. Such a mapping is done via conjugation with an element of shape :math:`y_e x_\epsilon`, with math:`e` a Goly code word math:`\epsilon` an even cocode word.. Here :math:`d` is given by parameter ``g``. Thee we choose a Golay code word ``e`` with :math:`g \cap e = \delta`. Using the returned table, ``e`` may be calculated as :math:`e = \sum_{i=0}^10 \delta_i \cdot t_i` , where :math:`\delta_i` is the ``i``-th bit of :math:`\delta`, and :math:`t_i` is the entry ``table[i+1]`` of the table. ``table[0]`` is equal to :math:`\theta(d)`. ``table[12]`` is a sign bit ``s``. If the bit 23 of :math:`v \cdot y_e` differs from ``s`` then we have to replace :math:`e` by :math:`e + e'`, where :math:`e'` is given by ``table[13]``. This operation adds :math:`x_\Omega` to :math:`x_d` in the cases relevant for function ``gen_leech2_reduce_n``. If :math:`v \cdot y_{e + e'}` has a sign bit set then we have to multiply that vector with :math:`x_\epsilon`, where the cocode word :math:`epsilon` is given by ``table[13]``. Entries ``table[11,12,13]`` are copied from parameters ``sign, code_omega, cocode_x``, respectively. Parameter ``cocode_x`` is an list of cocode words that will be meapped to zero by applying the table. On input, all Golay code and cocode word must be given as list of integers representing the bit positions set. In the returned table, all Golay code or cocode words are given as bit vector in **Golay code** or **cocode** representation, respectively. """ gv = Mat24.vect_to_gcode(list_to_vect(g)) b = [] for i in range(11): b.append((Mat24.ploop_cap(gv, 1 << i) << 12) + (1 << i)) for c in cocodes: b.append(Mat24.vect_to_cocode(list_to_vect(c)) << 12) if verbose: print("Function y_table, g =", hex(list_to_vect(g))) print("cocodes =", cocodes) print("cocode_x =", cocode_x) print("b =", [hex(x) for x in b]) b, columns = pivot_binary_high(b) if verbose: print("reduced b =", [hex(x) for x in b]) print("columns =", columns) table = [Mat24.ploop_theta(gv)] table1 = [] for i in range(10, -1, -1): if columns[0] == i + 12: table1.append(b[0] & 0xfff) b, columns = b[1:], columns[1:] else: table1.append(0) table1.reverse() table += table1 table.append(sign) table.append(Mat24.vect_to_gcode(list_to_vect(code_omega))) table.append(Mat24.vect_to_cocode(list_to_vect(cocode_x))) if verbose: print("table =", [hex(x) for x in table]) return table
def vector(gcode, cocode): gc = Mat24.vect_to_gcode(sum(1 << x for x in gcode)) coc = Mat24.vect_to_cocode(sum(1 << x for x in cocode)) return (gc << 12) ^ coc ^ Mat24.ploop_theta(gc)