Binary operation: logical and

        :param b: The other operand
        :return:

def bitwise_and(self, t):
        """
        Binary operation: logical and

        :param b: The other operand
        :return:
        """
        """
        The following code implements the and operations as presented in the paper
        'Signedness-Agnostic Program Analysis: Precise Integer Bounds for Low-Level Code'
        """
        s = self

        def number_of_ones(n):
            ctr = 0
            while n > 0:
                ctr += 1
                n &= n - 1
            return ctr

        # Optimization: if one of the two intervals is an integer and contains only one one we can be precise
        for a, b in [[s, t], [t, s]]:
            if a.is_integer and number_of_ones(a.lower_bound) == 1:
                if a.lower_bound == (1 << (t.bits - 1)):
                    # It's testing the sign bit
                    stride = 1 << (a.bits - 1)
                    if b.is_integer:
                        if b.lower_bound == stride:
                            return StridedInterval(bits=b.bits, stride=0, lower_bound=stride, upper_bound=stride)
                        else:
                            return StridedInterval(bits=b.bits, stride=0, lower_bound=0, upper_bound=0)
                    else:
                        is_sol = (a.lower_bound - b.lower_bound) % b.stride == 0 and b.lower_bound <= a.lower_bound <= b.upper_bound
                        if is_sol:
                            return StridedInterval(bits=b.bits, stride=stride, lower_bound=0, upper_bound=stride)
                        else:
                            return StridedInterval(bits=b.bits, stride=0, lower_bound=0, upper_bound=0)
                else:
                    #FIXME: implement case only one 1 not in first position
                    pass

        # paper's and
        new_interval = s.bitwise_not().bitwise_or(t.bitwise_not()).bitwise_not()
        return new_interval.normalize()