code: def sign_extend(self, new_length):
          
  
          msb = self.extract(self.bits - 1, self.bits - 1).eval(2)
          if msb == [ 0 ]:
              # All positive numbers
              return self.zero_extend(new_length)
          if msb == [ 1 ]:
              # All negative numbers
              si = self.copy()
              si._bits = new_length
              mask = (2 ** new_length - 1) - (2 ** self.bits - 1)
              si._lower_bound |= mask
              si._upper_bound |= mask
  
          else:
              # Both positive numbers and negative numbers
              numbers = self._nsplit()
              # Since there are both positive and negative numbers, there must be two bounds after nsplit
              # assert len(numbers) == 2
  
              all_resulting_intervals = list()
  
              assert len(numbers) > 0
  
              for n in numbers:
                  a, b = n.lower_bound, n.upper_bound
                  mask_a = 0
                  mask_b = 0
                  mask_n = ((1 << (new_length - n.bits)) - 1) << n.bits
  
                  if StridedInterval._get_msb(a, n.bits) == 1:
                      mask_a = mask_n
                  if StridedInterval._get_msb(b, n.bits) == 1:
                      mask_b = mask_n
  
                  si_ = StridedInterval(bits=new_length, stride=n.stride, lower_bound=a | mask_a, upper_bound=b | mask_b)
                  all_resulting_intervals.append(si_)
              si = StridedInterval.least_upper_bound(*all_resulting_intervals).normalize()
  
          si.uninitialized = self.uninitialized
          return si
docs: Unary operation: SignExtend
  
          :param new_length: New length after sign-extension
          :return: A new StridedInterval