Make a pointer gate on `num_qubits`. The one-qubit gate U will act on the
    qubit addressed by the pointer qubits interpreted as an unsigned binary
    integer.

    There are P = floor(lg(num_qubits)) pointer qubits, and qubits numbered

        N - 1
        N - 2
        ...
        N - P

    are those reserved to represent the pointer. The first N - P qubits
    are the qubits which the one-qubit gate U can act on.

def pointer_gate(num_qubits, U):
    """
    Make a pointer gate on `num_qubits`. The one-qubit gate U will act on the
    qubit addressed by the pointer qubits interpreted as an unsigned binary
    integer.

    There are P = floor(lg(num_qubits)) pointer qubits, and qubits numbered

        N - 1
        N - 2
        ...
        N - P

    are those reserved to represent the pointer. The first N - P qubits
    are the qubits which the one-qubit gate U can act on.
    """
    ptr_bits = int(floor(np.log2(num_qubits)))
    data_bits = num_qubits - ptr_bits
    ptr_state = 0
    assert ptr_bits > 0

    program = pq.Program()

    program.defgate("CU", controlled(ptr_bits, U))

    for _, target_qubit, changed in gray(ptr_bits):
        if changed is None:
            for ptr_qubit in range(num_qubits - ptr_bits, num_qubits):
                program.inst(X(ptr_qubit))
                ptr_state ^= 1 << (ptr_qubit - data_bits)
        else:
            program.inst(X(data_bits + changed))
            ptr_state ^= 1 << changed

        if target_qubit < data_bits:
            control_qubits = tuple(data_bits + i for i in range(ptr_bits))
            program.inst(("CU",) + control_qubits + (target_qubit,))

    fixup(program, data_bits, ptr_bits, ptr_state)
    return program