Esempio n. 1
0
def reduce_testcases(ncases=1000):
    for i in range(ncases):
        for complexity in range(15):
            yield MM0('r', complexity)
    g = MM0('r', 18)
    assert len(g.mmdata) > MIN_LEN_ALWAYS_UNREDUCED
    yield g
Esempio n. 2
0
def test_elem_to_word(ntests=50, verbose=0):
    print("Test function test_elem_to_word()")
    for i, w in enumerate(make_testwords(monomial=False, ntests=ntests)):
        m = MM0(w)
        if verbose:
            print("\nTest %d:" % (i + 1))
            print("Testing word\n%s" % m)
        elem = Xsp2_Co1(w)
        if i < 100:
            assert m == MM0(elem)
        if verbose:
            print("This is element\n%s" % elem)
        word = elem_to_word(elem, verbose > 1)
        if verbose:
            print("Reduced word\n%s" % MM0('a', word))
        elem_1 = Xsp2_Co1('a', word)
        if verbose:
            print("Recomputed element\n%s" % elem_1)
        ok = (elem == elem_1).all()
        if verbose or not ok:
            if not ok:
                print("Instead of to 1, the element reduces to:")
                print(elem * elem_1**(-1))
                err = "WTF"
                raise ValueError(err)
        word_C = elem_to_word_C(elem)
        assert (word_C == word).all(), (word_C, word)
        word1_C = reduce_word_C(m.mmdata)
        assert (word1_C == word).all(), (word1_C, word)
Esempio n. 3
0
def test_cases(verbose = 0):
    s = "For an axis let A be the symmetric matrix corresponding to part 300x"
    print(s,"\n")
    for axis_type, g_str in AXES.items():
        if verbose:
            print("\nTest reduction of axis type %s" % axis_type)
            text = display_norm_A(axis_type).split("\n")
            for s in text:
                if s: print("  " + s)
        # Construct an axis v of the given axi type
        v = V_START * MM0(g_str)
        target_axes = reduce_targets[axis_type]
        if target_axes is None:
            if verbose:
                print("  Reduction terminates here")
            continue
        nfound = 0
        dict_found = defaultdict(int)
        for w in reduce_cases[axis_type](v, verbose):
            if leech_type(w) != 4:
                continue
            nfound += 1
            v1 = v * MM0('c', w)**(-1)
            ok = False
            for e in [1,2]:
                t_axis_type = v1.axis_type(e)
                if t_axis_type in target_axes:
                   ok = True
                   dict_found[t_axis_type] += 1
            assert ok
        assert nfound > 0
        if verbose:
            if len(dict_found):
                print("  Reduced to axis types", dict(dict_found))
Esempio n. 4
0
def test_monomial_to_word(ntests=10, verbose=0):
    print("Test function test_monomial_to_word()")
    for i, w in enumerate(make_testwords()):
        if verbose:
            print("\nTest %d:" % (i + 1))
            m = MM0(w)
            print("Testing word\n%s" % m)
        elem = Xsp2_Co1(w)
        if verbose:
            print("This is element\n%s" % elem)
        data_i = monomial_to_word(elem, verbose > 1)
        elem_0 = elem.copy().mul_data(data_i)
        try:
            x = elem_0.as_xsp()
            ok = True
        except:
            raise
            ok = False
        if verbose or not ok:
            m_i = MM0("a", data_i)
            print("Reduced inverse word\n%s" % str(m_i))
            if not ok:
                print("Product with inverse\n%s" % elem_0)
                err = "WTF"
                raise ValueError(err)
            else:
                print("Result is:", hex(x))
            print("Test %d ok" % (i + 1))
        data_C = monomial_to_word_C(elem)
        assert (data_C == data_i).all(), (data_C, data_i)
Esempio n. 5
0
def test_2A_axes_classes(verbose=0):
    """Test computation of samples classes of 2A axes.

    If this function is called with parameter ``verbose == 1``
    then function displays the information relevant for 
    distinguishing between classes of 2A axes.
    """
    do_test_baby_sample_axes(baby_sample_axes)
    do_test_sample_axes(sample_axes)
    if verbose:
        print(HEADER)

    NUM_AXES = len(sample_axes.g_strings)
    for i in range(NUM_AXES):  # sorted_axes(sample_axes):
        g = MM0(sample_axes.g_strings[i])
        v = MMVectorCRT(20, sample_axes.v_start)
        v *= g
        g1 = MM0(sample_axes.g_beautifiers[i])
        v *= g1
        Afloat = 256 * v["A"]
        A = np.array(Afloat, dtype=np.int32)
        assert (A == Afloat).all()
        if verbose:
            class_ = sample_axes.g_classes[i]
            print("\nClass " + class_, end=", ")
            print("stage = " + str(sample_axes.g_stages[i]), end="")
            powers = sample_axes.powers[i]
            s_powers = ", powers: " + powers if len(powers) else ""
            print(s_powers)
            print("Automorphism group:", sample_axes.groups[i])
            print(display_norm_A(i), end="")
            print("Eigenvalues", block_eigenvalues(A))
            display_A(A)
Esempio n. 6
0
def one_test_reduce(g, verbose=0):
    g1 = MM0(g)
    g2 = MM(g).reduce()
    if verbose:
        print(g1)
        print(g2)
    if len(g1.mmdata) > MIN_LEN_ALWAYS_UNREDUCED:
        assert len(g2.mmdata) < len(g1.mmdata)
    assert MM0(g2) == g1
Esempio n. 7
0
def beautify_after_signs_10B(A):
    for i in (5, 6):
        if A[1, i] < 0:
            src = [7, 5, 6] if i == 6 else [6, 7, 5]
            src = [0, 1, 2, 3, 4] + src
            dest = list(range(7))
            #return MM0()
            return MM0('p', AutPL(0, zip(src, dest), 0))
    return MM0()
Esempio n. 8
0
def beautify_block_size3(A):
    """Try to order a matrix with a 3 times 3 block

    If matrix ``A`` has a 3 times 3 block in rows 0, 1, and 2, then
    the function checks the diagonal entries with index >= 3. It 
    looks for a set of equal diagonal entries such that the union
    of the indices of these entries with the set [1,2,3] is an octad.
    If this is the case then the function returns an element ``g`` 
    that that moves this octad to the first 8 rows and columns.

    In case of success that element is returned as an instance of 
    class ``MM0``. Otherwise the neutral element in class ``MM0``
    is returned.    
    """
    bl = blocks(A)
    if mat24.bw24(bl[0]) != 3:
        return MM0()
    blist = [x for x in range(24) if bl[0] & (1 << x)]
    if (blist != [0, 1, 2]):
        return MM0()
    d = defaultdict(list)
    for b in bl:
        if b & (b - 1) == 0:
            index = b.bit_length() - 1
            d[A[index, index]].append(index)
    for lst in d.values():
        if len(lst) < 8:
            try:
                gc = GCode(blist + lst).bit_list
                assert len(gc) == 8
            except:
                continue
            isect = set(blist) & set(gc)
            #print("isect", isect)
            if len(isect) == 3:
                src0 = [x for x in gc if x in isect]
                src1 = [x for x in gc if not x in isect]
                dest = range(6)
                pi = AutPL(0, zip(src0 + src1[:3], dest), 0)
                return MM0(pi)
            if len(isect) == 1:
                src = gc
                dest = list(range(8))
                src0 = [x for x in gc if not x in isect]
                src1 = [x for x in gc if x in isect]
                src2 = [x for x in blist if x not in src1]
                dest = list(range(10))
                for i in range(1000):
                    shuffle(src0)
                    shuffle(src2)
                    try:
                        pi = AutPL(0, zip(src0 + src1 + src2, dest))
                        return MM0(pi)
                    except:
                        pass
    return MM0()
Esempio n. 9
0
def conj_G_x0_to_Q_x0(g):
    gg = Xsp2_Co1(g)
    a = np.zeros(7, dtype=np.uint32)
    lv = chk_qstate12(xsp2co1_elem_conj_G_x0_to_Q_x0(gg._data, a))
    length, q = lv >> 25, lv & 0x1ffffff
    h = MM0('a', a[:length])
    gh = MM0(g)**h
    assert gh.in_Q_x0()
    assert gh == MM0('q', q)
    return h
Esempio n. 10
0
def test_axes():
    for key in AXES:
        v = V(*START_AXIS) * MM0(AXES[key])
        assert v.axis_type() == key
        for i in range(20):
            w = v * MM0('r', 'G_x0')
            assert w.axis_type() == key
            if (i > 5): continue
            e = randint(1, 2)
            we = w.axis_type(e)
            assert isinstance(we, str)
Esempio n. 11
0
def beautify_block_size2(A):
    """Try to order a matrix with 2 times 2 block

    If matrix ``A`` has  2 times 2 blocks then the function checks 
    the diagonal entries. It looks for a set of equal diagonal entries 
    such that the union of the indices an octad (up to a syndrome of
    length at most 3).
    If this is the case then the function returns an element ``g`` 
    that that moves this octad to the first 8 rows and columns.

    In case of success that element is returned as an instance of 
    class ``MM0``. Otherwise the neutral element in class ``MM0``
    is returned.    
    """
    bl = blocks(A)
    if mat24.bw24(bl[0]) != 2:
        return MM0()
    blist = [x for x in range(24) if bl[0] & (1 << x)]
    d = defaultdict(list)
    for b in bl:
        if b & (b - 1) == 0:
            index = b.bit_length() - 1
            d[A[index, index]].append(index)
    for lst in d.values():
        if len(lst) <= 8:
            try:
                #print(lst)
                gc = GCode(blist + lst).bit_list
                #print("GC =", gc)
            except:
                continue
            if set(blist).issubset(gc) and len(gc) == 8:
                src0 = [x for x in gc if x in blist]
                src1 = [x for x in gc if x not in blist]
                dest = list(range(8))
                for i in range(1000):
                    shuffle(src1)
                    try:
                        pi = AutPL(0, zip(src0 + src1, dest), 0)
                        return MM0(pi)
                    except:
                        pass
            if len(set(blist) & set(gc)) == 0 and len(gc) == 8:
                src0 = gc
                src1 = blist
                dest = list(range(10))
                for i in range(10000):
                    shuffle(src0)
                    try:
                        pi = AutPL(0, zip(src0 + src1, dest), 0)
                        return MM0(pi)
                    except:
                        pass
    return MM0()
Esempio n. 12
0
def make_axis_testcases():
    #V = V_START.space
    yield V_START.copy(), 1
    yield V("I", 11, 9), 1
    yield V("I", 11, 9), 0
    for i in range(10):
        yield V_START * MM0("r", "G_x0"), i & 1
    for ax in AXES:
        v0 = V_START * MM0(AXES[ax])
        for i in range(20):
            yield v0 * MM0("r", "G_x0"), i & 1
    for quality in range(2, 11):
        for i in range(3):
            yield V_START * MM0("r", quality), i & 1
Esempio n. 13
0
def beautify_diagonal_matrix(A):
    """Try to order a diagonal matrix

    If matrix ``A`` is diagonal then the function looks for a set 
    of equal diagonal entries that is close to an octad or to a
    dodecad.  If this is the case then the function returns an 
    element ``g`` that that moves this Golay code word to a
    standard position.

    In case of success that element is returned as an instance of 
    class ``MM0``. Otherwise the neutral element in class ``MM0``
    is returned.    
    """
    bl = blocks(A)
    if mat24.bw24(bl[0]) != 1:
        return MM0()
    d = defaultdict(list)
    for b in bl:
        if b & (b - 1) == 0:
            index = b.bit_length() - 1
            d[A[index, index]].append(index)
    singleton = None
    for lst in d.values():
        if len(lst) == 1: singleton = lst
    for lst in d.values():
        dest = list(range(8))
        if len(lst) == 8:
            #print(lst)
            for i in range(10000):
                shuffle(lst)
                try:
                    pi = AutPL(0, zip(lst, dest), 0)
                    #print("yeah")
                    return MM0(pi)
                except:
                    continue
        elif len(lst) == 11 and singleton:
            print("dodecad")
            DOD = 0xeee111
            dest = [i for i in range(24) if (1 << i) & DOD]
            src = singleton + lst
            #print(dest)
            #print(src)
            #return MM0()
            pi = mat24.perm_from_dodecads(src, dest)
            return MM0('p', pi)
        elif singleton:
            pi = pi = AutPL(0, zip(singleton, [0]), 0)
            return MM0('p', pi)
    return MM0()
Esempio n. 14
0
def rand_BM(quality=8):
    r"""Generate certain 'random' element in the Baby Monster`

    Let ``v_0`` be the element of the subgroup  ``Q_x0`` of ``G_x0``
    corresponding to the Golay cocode element ``[2,3]``.

    The function generates a random element of the centralizer
    of ``v_0`` in the monster.
    """
    a = MM0()
    for i in range(quality):
        a *= rand_Co2()
        a *= MM0('t', 'r')
    return a
Esempio n. 15
0
def try_make_blocks_positive(A, block=0, first_row_only=False, tag='y'):
    """Make block of matrix ``A`` acting on the Leech lattice positive

    Here ``block`` is a block of rows of columns of the matrix 
    given as a set of integers. Block may also be a nonzero
    integer encoding a block in the bits being set in that integer.
    In case ``block = 0`` (default) we take the largest block,
    where a block is as in function ``blocks()``.

    The function tries to compute an integer ``d`` encoding an 
    element of of the Golay code, so that the transfromation
    with that Golay code element makes all entries of that 
    block nonnegative. In case of success the function returns 
    the element ``return MM0('y', d)`` of the Monster group that 
    changes the signs appropriately.

    If this fails then the functoion raises ValueError. 
    """
    if isinstance(block, Iterable):
        bl_list = list(block)
    else:
        bl = block if block else blocks(A)[0]
        bl_list = [x for x in range(24) if (1 << x) & bl]
    row_list = bl_list[:1] if first_row_only else bl_list
    d = change_signs_A(A, [(bl_list, row_list)])
    return MM0(tag, d)
Esempio n. 16
0
def beautify(axis, verbose=0):
    if axis.g == MM0():
        return axis
    bl = blocks(axis.A())
    if verbose:
        print("Blocksizes", [bit_count(x) for x in bl])
    bl_size = bit_count(bl[0])
    if max(bit_count(b) for b in bl) > 3:
        if bl_size > 5 and verbose:
            print("vector type:", mat24.vect_type(bl[0]))
        axis.apply(make_blocks_positive)
        if len(bl) > 1:
            axis.apply(beautify_large_block)
        else:
            axis.apply(beautify_single_block)
        bl = axis.blocks()
        if bit_count(bl[0]) == 8 and bit_count(bl[1]) == 1:
            axis = beautify_10B(axis)
    elif bl_size == 3:
        axis.apply(beautify_large_block)
        axis.apply(sort_single_size3_block)
        axis.apply(beautify_block_size3)
        axis.apply(beautify_signs_size2_3)
    elif bl_size == 2:
        axis.apply(beautify_block_size2)
        axis.apply(beautify_signs_size2_3)
    elif bl_size == 1:
        axis.apply(beautify_diagonal_matrix)
    else:
        raise ValueError("Beautifying of matrix A failed")
    beautify_permutation(axis)
    axis.trim_axis_type()
    return axis
Esempio n. 17
0
def test_display_axes(verbose=0):
    if verbose:
        print(HEADER)
    else:
        print("\nClasses of 2A axes (relative to G_x0):\n")
    for cl in get_axes():
        axis = get_axes()[cl]
        print("Class:", axis.g_class, ", stage =", axis.stage, ", powers:",
              axis.powers)
        print("Automorphism group:", axis.group)
        print(display_norm_A(axis), end="")
        print("Eigenvalues of A part of axis v:", eigen(axis.A()))
        if verbose:
            n, c = (g_central * axis.reflection()).half_order()
            print("Half order:", n, ", central involution: ", c)
            if c:
                print("Character of central involution:", c.chi_G_x0())
                (analyze_xy(c))
            print("Axis type of axis v * MM('t',1):", axis.axis_type(1))
            print("Dim intersection with Q_x0:",
                  24 - len(x_equations(axis, 0)))
            print("Dim intersection with Q_y0:",
                  24 - len(x_equations(axis, 1)))
            #print("Dim intersection with Q_z0:", 24 - len(x_equations(axis,2)))
            opp_axis_type = (v_axis_opp15 * MM0(axis.g)).axis_type()
            print("Image of opposite axis: ", opp_axis_type)
            print("A part of axis v:")
            display_A(axis.A())
            print("\nA part of axis v * MM('t', 1):")
            display_A(axis.Ax())
            print("A part of opposite axis v:")
            display_A(axis.A_opp())
        print("")
Esempio n. 18
0
def test_in_gx0(verbose = 0):
    print("Testing function check_mm_in_g_x0()")
    for n, (g, in_g_x0) in enumerate(in_gx0_testdata()):
        g = MM0(g)
        if verbose:
            print("Test", n+1)
            print("g =", g)
        g1 = check_mm_in_g_x0(g)
        if verbose:
            print("reduced", g1)
            if g1 is None:
                r = err_in_g_x0_c
                print("Reason for non-membership (.c):", r)
        g1_py = py_check_mm_in_g_x0(g)
        if verbose:
            print("reduced (py)", g1_py)
            if g1_py is None:
                r = err_in_g_x0_py
                print("Reason for non-membership (py):", r)
        if in_g_x0:
            assert g1_py is not None
        else:
            assert g1_py is None
        if g1_py:
            assert g == g1_py 
        assert g1 == g1_py
        #assert g.in_G_x0() == in_g_x0
        pass
Esempio n. 19
0
def get_axes():
    global AXES
    if len(AXES):
        return AXES
    for i, g1 in enumerate(sample_axes.g_strings):
        g2 = sample_axes.g_beautifiers[i]
        g = MM0(g1) * MM0(g2)
        g_class = sample_axes.g_classes[i]
        axis = Axis(g, g_class)
        axis.mark = sample_axes.g_marks[i]
        axis.group = sample_axes.groups[i]
        axis.powers = sample_axes.powers[i]
        axis.stage = sample_axes.g_stages[i]
        axis.v15 = v_axis15 * MM0(sample_axes.g_strings[i])
        axis.norm15 = mm_op15_norm_A(axis.v15.data)
        AXES[g_class] = axis
    return AXES
Esempio n. 20
0
def rand_Co2(quality=5):
    r"""Generate certain 'random' element in a subgroup of ``G_x0``

    Let ``v_0`` be the element of the subgroup  ``Q_x0`` of ``G_x0``
    corresponding to the Golay cocode element ``[2,3]``.

    The function generates a random element of the centralizer
    of ``v_0`` in ``G_x0``.
    """
    a = MM0()
    for i in range(quality):
        pi = rand_pi_mat22()
        x1 = randint(0, 0xfff) & ~0x200
        y1 = randint(0, 0xfff) & ~0x200
        e = randint(0, 2)
        a *= MM0([('p', pi), ('x', x1), ('y', y1), ('l', e)])
    return a
Esempio n. 21
0
def eval_a_ref(v, v2, e=0):
    if (e % 3):
        v = v * MM0('t', e)
    A = np.array(v["A"], dtype=np.int32)
    v2_sp = mm_aux_index_leech2_to_sparse(v2)
    v_2 = np.zeros(24, dtype=np.int32)
    res = mm_aux_index_sparse_to_leech(v2_sp, v_2)
    return (v_2 @ A @ v_2) % 15
Esempio n. 22
0
def sort_single_size3_block(A):
    """Sort entries of matrix with single 3 times 3 block

    If matrix ``A`` contains a single 3 times 3 block and some
    diagonal entries the the function returns a permutation that 
    moves the 3 times 3 block to rows and columns 0, 1, and 2.
    That permutation is returned as an instance of class ``MM0``.
    
    Otherwise the function returns the neutral element in
    class ``MM0``.
    """
    bl = blocks(A)
    if mat24.bw24(bl[0]) != 3 or mat24.bw24(bl[1]) != 1:
        return MM0()
    blist = [x for x in range(24) if bl[0] & (1 << x)]
    dlist = sorted([(-A[x, x], x) for x in blist])
    src = [x[1] for x in dlist]
    return MM0('p', AutPL(0, zip(src, [0, 1, 2]), 0))
Esempio n. 23
0
def xsp2co1_fast_half_order(wx):
    assert isinstance(wx, Xsp2_Co1)
    buf = np.zeros(10, dtype=np.uint32)
    m = MM0(wx)
    res = chk_qstate12(xsp2co1_half_order_word(m._data, m.length, buf))
    o, l = divmod(res, 256)
    assert 0 <= l <= 10
    out = Xsp2_Co1()
    chk_qstate12(xsp2co1_mul_elem_word(out._data, buf, l))
    return o, out
Esempio n. 24
0
def beautify_signs_10B(A):
    sign_list = []

    def sgn(i0, i1, s):
        t = A[i0, i1]
        if t * s: sign_list.append((i0, i1, t * s < 0))

    for i in range(0, 4):
        sgn(0, i + 4, +1)
    for i in range(1, 4):
        sgn(4, i, -1)
    #sgn(0, 4, 1)
    try:
        y = solve_gcode_diag(sign_list)
        print("Beautification found in case 10B")
        return MM0('y', y)
    except:
        print("Beautification failed in case 10B")
        return MM0()
Esempio n. 25
0
 def trim_axis_type(self):
     t = self.axis_type(0)
     if self.axis_type(2) != t:
         self *= MM0('d', 0x800)
     if self.axis_type(1) != t:
         Ax = self.Ax()
         if t in trim_cooctad_required:
             self *= trim_cooctad(Ax)
             Ax = self.Ax()
         if t in positive_blocks:
             d = change_signs_A(Ax, positive_blocks[t], ignore=True)
             #if (d): print("d =", d)
             self *= MM0('x', d)
         elif t in negative_blocks:
             d = change_signs_A(Ax, [], negative_blocks[t], ignore=True)
             if (d): print("d =", d)
             self *= MM0('x', d)
         else:
             self *= make_blocks_positive(Ax, tag='x')
     return self
Esempio n. 26
0
def make_involution_samples():
    # sample obtained from former error cases
    NEW_SAMPLES = [
        # The following sample led to a bug in MacOS
        (MM0("y_80fh*d_1h"), [(4, 4), (275, 43, 8, 0), (9, 4, 1, 4, 16)]),
    ]
    for h, invar in NEW_SAMPLES:
        yield h, invar
    for invar, g in INVOLUTION_SAMPLES:
        g = MM0(g)
        g.in_G_x0()
        yield g, invar
        n_samples = 20 if invariant_status(invar) == 3 else 10
        last = g
        for i in range(n_samples):
            t = MM0('r', 'G_x0')
            h = g**t
            h.in_G_x0()
            if h != last:
                yield h, invar
            last = h
Esempio n. 27
0
def gA_from_type4(v_type4):
    r"""Comupute a group element reducing a type-4 Leech lattice vector 
    
    Let ``v_type_4`` be a vector of type 4 in the Leech lattice mod 2
    in **Leech lattice encoding**.  The function returns an element
    ``g`` of the subgroup :math:`G_{x0}` of the monster that maps
    `v_type_4`` to the standard frame :math:`\Omega`. The group
    element ``g`` is returned as a string.   
    """
    g_data = np.zeros(10, dtype=np.uint32)
    len_g = gen_leech2_reduce_type4(v_type4, g_data)
    gA = MM0('a', g_data[:len_g])
    return str(gA)
Esempio n. 28
0
def reduce_v_axis_C(v, std_axis):
    va = mm_vector(15, 2)
    vc, work = va[0].data, va[1].data
    mm_op15_copy(v.data, vc)
    r = np.zeros(200, dtype=np.uint32)
    res = mm_reduce_vector_vp(vc, std_axis, r, work)
    if not 0 < res <= 200:
        raise ValueError(ERR_REDUCE_V_AXIS, res)
    g = MM0('a', r[:res])
    axis_found = r[res - 1]
    assert axis_found & 0xfe000000 == 0x84000000
    axis_found &= 0x1ffffff
    return g, axis_found
Esempio n. 29
0
def character(g, verbose=0):
    assert isinstance(g, Xsp2_Co1_Element)
    a = xsp2co1_traces(g)
    if verbose: print("Subcharacters", a)
    chi24, chisq24, chi4096, chi98260 = map(int, a[:4])
    chi299 = (chi24**2 + chisq24) // 2 - 1
    assert chi24 >= 0
    if chi24 == 0: assert chi4096 >= 0
    chi_M = chi299 + chi98260 + chi24 * chi4096
    #print("MMMM", MM0(g))
    chi_g = MM0(g).chi_G_x0()
    assert chi_g == (chi_M, chi299, chi24, chi4096)
    return chi_M
Esempio n. 30
0
def do_test_2A_involution(n_tests=30, verbose=1):
    for i, g in enumerate(make_2A_samples(n_tests)):
        if verbose:
            print("Test", i + 1)
            print("g=", g)
        itype, h = g.conjugate_involution(ntrials=40, verbose=verbose)
        assert itype == 1
        res = (g**h)
        res.in_G_x0()
        if verbose:
            print("h=", h)
            print("g**h=", res)
        assert res in (Z_2A, MM0('x', 0x200) * Z_2A)