docs: def with_slots(cls):
      """
      Decorator for a class with _slots_. It automatically defines
      the methods __eq__, __ne__, assert_equal.
      """
      def _compare(self, other):
          for slot in self.__class__._slots_:
              attr = operator.attrgetter(slot)
              source = attr(self)
              target = attr(other)
              if isinstance(source, numpy.ndarray):
                  eq = numpy.array_equal(source, target)
              elif hasattr(source, '_slots_'):
                  source.assert_equal(target)
                  eq = True
              else:
                  eq = source == target
              yield slot, source, target, eq
  
      def __eq__(self, other):
          return all(eq for slot, source, target, eq in _compare(self, other))
  
      def __ne__(self, other):
          return not self.__eq__(other)
  
      def assert_equal(self, other, ignore=()):
          for slot, source, target, eq in _compare(self, other):
              if not eq and slot not in ignore:
                  raise AssertionError('slot %s: %s is different from %s' %
                                       (slot, source, target))
  
      cls._slots_  # raise an AttributeError for missing slots
      cls.__eq__ = __eq__
      cls.__ne__ = __ne__
      cls.assert_equal = assert_equal
      return cls