Exemplo n.º 1
0
 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
Exemplo n.º 2
0
def mul_Tx(tag, octad, sub, g):
    d = m24.octad_to_gcode(octad)
    c = m24.suboctad_to_cocode(sub, d)
    e = g.pl
    s = m24.ploop_comm(d, e)
    s ^= m24.scalar_prod(e, c)
    return s, tag, octad, sub
Exemplo n.º 3
0
def test_cocode():
    print("")
    for i in range(200):
        # Test power map, inveriosn, sign, theta, and conversion to GCode
        n1 = randint(0, 0x1fff)
        p1 = PLoop(n1)
        ccvector = randint(0, 0xffffff)
        coc = mat24.vect_to_cocode(ccvector)
        cclist = [i for i in range(24) if (ccvector >> i) & 1]
        cc1 = Cocode(cclist)
        cc2 = Cocode(coc)
        if i < 1:
            print("\nTesting", GcVector(ccvector), ", cocode =", cc1)
        assert cc1 == cc2
        u = Parity(mat24.scalar_prod(p1.value, cc1.value))
        assert p1 & cc1 == u == cc1 & p1 == u * 1 == u + 0
        par = Parity(randint(0, 1))
        assert cc1 + par == par + cc1 == cc1.value // 0x800 + par
        assert cc1 % 2 == Parity(cc1)
        assert len(cc1) == mat24.cocode_weight(cc1.value)
        if len(cc1) < 4:
            syndrome = mat24.cocode_syndrome(cc1.value)
            assert cc1.syndrome().value == syndrome
            syn_from_list = sum(1 << i
                                for i in GcVector(ccvector).syndrome_list())
            assert syn_from_list == syndrome
        i = randint(0, 23)
        assert cc1.syndrome(i).value == mat24.cocode_syndrome(cc1.value, i)
        syndrome_list = cc1.syndrome(i).bit_list
        assert len(cc1) == len(syndrome_list)
        assert syndrome_list == mat24.cocode_to_bit_list(cc1.value, i)
Exemplo n.º 4
0
def mul_Ty(tag, octad, sub, g):
    d = m24.octad_to_gcode(octad)
    c = m24.suboctad_to_cocode(sub, d)
    e = g.pl
    c1 = m24.ploop_cap(d, e) ^ c
    sub1 = m24.cocode_to_suboctad(c1, d)
    s = m24.scalar_prod(e, c)
    return s, tag, octad, sub1
Exemplo n.º 5
0
def mul_Xp(tag, d, i, g):
    eps, pi, rep = g.cocode, g.perm, g.rep
    d1 = m24.op_ploop_autpl(d, rep)
    i1 = pi[i]
    s = d1 >> 12
    if eps & 0x800:  # if eps is odd:
        s ^= m24.scalar_prod(d, m24.vect_to_cocode(1 << i))
        s ^= m24.pow_ploop(d, 2) >> 12
    return s, tag, d1 & 0x7ff, i1
Exemplo n.º 6
0
 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
Exemplo n.º 7
0
    def theta(self, g2=None):
        """Return cocycle of Golay code words.

        The cocycle ``theta`` maps a pair of Golay code words 
        to an integer modulo ``2``. 
        It is linear in its second argument, so it
        may also be considered as a mapping from the Golay code
        to the cocode of the Golay code.


        :param g2:  ``None`` (default) or another Golay code word of
                    type |GCode|.
        :returns:
            * If ``g2`` is a code word of type |GCode|, we return
              the value ``g1.theta(g2) = theta(g1, g2)`` 
              as a |Parity| object.
            * If ``g2`` is ``None`` (default), we return the value
              ``g1.theta() = theta(g1)``  as a |Cocode| object.
              Note that  ``g1.theta(g2) == g1.theta() & g2 .``

        The importance of the ``theta`` function comes from the
        fact that the multiplication of elements of the Parker loop
        is based on the cocycle. We embed the set of Golay code words  
        into  the set of positive Parker loop elements, which are 
        instances of class |PLoop|. 
 
        Let ``g1`` and ``g2`` be Golay code words of type |GCode|.
        Then  ``PLoop(g1)`` and ``PLoop(g2)`` are the corresponding
        positive Parker loop elements,  and  ``g1.theta(g2)`` is an 
        integer  modulo ``2`` of type |Parity|. We have:  
       
        ``PLoop(g1) * PLoop(g2) == (-1)**g1.theta(g2) * PLoop(g1 + g2) .``
        """
        th = mat24.ploop_theta(self.value)
        if g2 == None:
            complete_import()
            return Cocode(th)
        if isinstance(g2, GCode):
            return Parity(mat24.scalar_prod(g2.value, th))
        err = "Types %s is illegal for method theta()"
        raise TypeError(err % type(g2))
Exemplo n.º 8
0
def sign_t_YZ(d, i):
    return (m24.scalar_prod(d, m24.vect_to_cocode(1 << i)) ^
            (m24.pow_ploop(d, 2)) >> 12)
Exemplo n.º 9
0
def sign_t_XY(d, i):
    return m24.scalar_prod(d, m24.vect_to_cocode(1 << i))
Exemplo n.º 10
0
def mul_Cy(tag, i, j, g):
    c = m24.vect_to_cocode((1 << i) + (1 << j))
    e = g.pl
    s = m24.scalar_prod(e, c)
    tag = C - s
    return s, tag, i, j
Exemplo n.º 11
0
def mul_Ay(tag, i, j, g):
    c = m24.vect_to_cocode((1 << i) ^ (1 << j))
    e = g.pl
    s = m24.scalar_prod(e, c)
    if i == j: assert s == 0
    return s, tag, i, j
Exemplo n.º 12
0
 def __and__(self, other):
     if isinstance(other, GCode):
         return Parity(mat24.scalar_prod(self.value, other.value))
     else:
         return NotImplemented
Exemplo n.º 13
0
def mul_Yy(tag, d, i, g):
    e = g.pl & 0xfff
    s = m24.scalar_prod(e, m24.vect_to_cocode(1 << i))
    s ^= m24.ploop_comm(d, e)
    return s, Y, d & 0x7ff, i
Exemplo n.º 14
0
def mul_Bx(tag, i, j, g):
    c = m24.vect_to_cocode((1 << i) ^ (1 << j))
    e = g.pl
    s = m24.scalar_prod(e, c)
    return s, tag, i, j
Exemplo n.º 15
0
def mul_Zx(tag, d, i, g):
    e = g.pl
    ed = m24.mul_ploop(m24.pow_ploop(e, 3), d)
    s = m24.scalar_prod(e, m24.vect_to_cocode(1 << i))
    s = (ed >> 12)
    return s & 1, Z, ed & 0x7ff, i
Exemplo n.º 16
0
def mul_Zy(tag, d, i, g):
    e = g.pl
    de = m24.mul_ploop(d, e)
    s = m24.scalar_prod(e, m24.vect_to_cocode(1 << i))
    s ^= de >> 12
    return s, Z, de & 0x7ff, i
Exemplo n.º 17
0
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
Exemplo n.º 18
0
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)