def union(other)
      if other.is_a?(RelativeComplement)
        # A ∪ ¬B = ¬B ∪ A
        other.union(self)
      elsif other.is_a?(AbstractSet)
        unless other.is_a?(RelativeSet) and size < other.size
          hash = other.inject(@hash.clone){|h,o| h[o] = true; h }

          if hash.empty?
            NullSet.build
          else
            RelativeSet.new(hash)
          end
        else
          # For efficiency, iterate the smaller of the two sets: A ∪ B = B ∪ A
          if other.empty?
            self
          else
            other.union(self)
          end
        end
      else
        union(Cantor.build(other))
      end
    end
def union(other)
      if other.is_a?(RelativeComplement)
        # A ∪ ¬B = ¬B ∪ A
        other.union(self)
      elsif other.is_a?(AbstractSet)
        unless other.is_a?(RelativeSet) and size < other.size
          hash = other.inject(@hash.clone){|h,o| h[o] = true; h }

          if hash.empty?
            NullSet.build
          else
            RelativeSet.new(hash)
          end
        else
          # For efficiency, iterate the smaller of the two sets: A ∪ B = B ∪ A
          if other.empty?
            self
          else
            other.union(self)
          end
        end
      else
        union(Cantor.build(other))
      end
    end
(see AbstractSet#intersection)