def _find_minimal_alignment(offset, base_alignment, prev_end):
    """
    Returns the minimal alignment that must be set for a field with
    ``base_alignment`` (the one inherent to the type),
    so that the compiler positioned it at ``offset`` given that the previous field
    ends at the position ``prev_end``.
    """
    # Essentially, we need to find the minimal k such that:
    # 1) offset = m * base_alignment * 2**k, where m > 0 and k >= 0;
    #    (by definition of alignment)
    # 2) offset - prev_offset < base_alignment * 2**k
    #    (otherwise the compiler can just as well take m' = m - 1).
    alignment = base_alignment
    while True:
        if offset % alignment != 0:
            raise ValueError(
                ("Field cannot be positioned at offset {offset}, "
                "since it is not multiple of the minimal alignment {alignment}").format(
                    offset=offset, alignment=alignment))
        if alignment > offset:
            raise ValueError(
                "Could not find a suitable alignment for the field at offset {offset}".format(
                    offset=offset))
        if offset - prev_end >= alignment:
            alignment *= 2
            continue

        return alignment