ANY AVL_SET NONE
class interface AVL_SET[E->COMPARABLE]
   --
   -- Definition of a mathematical set of comparable objects. All common
   -- operations on mathematical sets are available.
   --

creation
   make
      -- Creation of an empty SET.
      ensure
         is_empty

   from_collection (model: COLLECTION[E])

feature(s) from SET
   -- Counting:

   count: INTEGER
      -- Cardinality of the set (i.e. actual count of stored elements).

   is_empty: BOOLEAN
      -- Is the set empty?
      ensure
         Result = (count = 0)

feature(s) from SET
   -- Adding and removing:

   add (e: E)
      -- Add a new item to the set: the mathematical definition of
      -- adding in a set is followed.
      require
         e /= Void
      ensure
         added: has(e);
         not_in_then_added: not old has(e) implies count = old count + 1;
         in_then_not_added: old has(e) implies count = old count

   remove (e: E)
      -- Remove item e from the set: the mathematical definition of
      -- removing from a set is followed.
      require
         e /= Void
      ensure
         removed: not has(e);
         not_in_not_removed: not old has(e) implies count = old count;
         in_then_removed: old has(e) implies count = old count - 1

   clear_count
      -- Empty the current set (is_empty is True after that call). If possible, the actual implementation 
      -- is supposed to keep its internal storage area in order to refill Current in an efficient way.
      -- See also clear_count_and_capacity to select the most appropriate.
      ensure
         is_empty

   clear_count_and_capacity
      -- Empty the current set (is_empty is True after that call). If possible, the actual implementation 
      -- is supposed to release its internal storage area for this memory to be used by other objects.
      -- See also clear_count to select the most appropriate.
      ensure
         is_empty: count = 0

feature(s) from SET
   -- Looking and searching:

   has (e: E): BOOLEAN
      -- Is element e in the set?
      require
         e /= Void
      ensure
         Result implies not is_empty

   fast_has (e: E): BOOLEAN
      -- Is element e in the set?
      require
         e /= Void
      ensure
         Result implies not is_empty

   reference_at (e: E): E
      -- When Is element e in the set?
      require
         e /= Void;
         not e.is_expanded_type
      ensure
         has(e) implies Result /= Void

feature(s) from SET
   -- To provide iterating facilities:

   lower: INTEGER

   upper: INTEGER
      ensure
         Result = count

   valid_index (index: INTEGER): BOOLEAN
      ensure
         Result = index.in_range(lower,upper)

   item (index: INTEGER): E
      -- Return the item indexed by index.
      require
         valid_index(index)
      ensure
         has(Result)

   get_new_iterator: ITERATOR[E]

feature(s) from SET
   -- Mathematical operations:

   union (other: like Current)
      -- Make the union of the Current set with other.
      require
         other /= Void
      ensure
         count <= old count + other.count

   infix "+" (other: like Current): like Current
      -- Return the union of the Current set with other.
      require
         other /= Void
      ensure
         Result.count <= count + other.count;
         Current.is_subset_of(Result) and then other.is_subset_of(Result)

   intersection (other: like Current)
      -- Make the intersection of the Current set with other.
      require
         other /= Void
      ensure
         count <= other.count.min(old count)

   infix "^" (other: like Current): like Current
      -- Return the intersection of the Current set with other.
      require
         other /= Void
      ensure
         Result.count <= other.count.min(count);
         Result.is_subset_of(Current) and then Result.is_subset_of(other)

   minus (other: like Current)
      -- Make the set Current - other.
      require
         other /= Void
      ensure
         count <= old count

   infix "-" (other: like Current): like Current
      -- Return  the set Current - other.
      require
         other /= Void
      ensure
         Result.count <= count;
         Result.is_subset_of(Current)

feature(s) from SET
   -- Comparison:

   is_subset_of (other: like Current): BOOLEAN
      -- Is the Current set a subset of other?
      require
         other /= Void
      ensure
         Result implies count <= other.count

   is_disjoint_from (other: like Current): BOOLEAN
      -- Is the Current set disjoint from other ?
      require
         other /= Void
      ensure
         Result = (Current ^ other).is_empty

   is_equal (other: like Current): BOOLEAN
      -- Is the Current set equal to other?
      require
         other /= Void
      ensure
         double_inclusion: Result = (is_subset_of(other) and other.is_subset_of(Current));
         generating_type = other.generating_type implies Result = other.is_equal(Current)

feature(s) from SET
   copy (other: like Current)
      -- Copy 'other' into the current set
      require
         same_dynamic_type(other)
      ensure
         is_equal(other)

   from_collection (model: COLLECTION[E])

feature(s) from SET
   -- Agents based features:

   do_all (action: ROUTINE[ANY,TUPLE[COMPARABLE]])
      -- Apply action to every item of Current.

   for_all (test: FUNCTION[ANY,TUPLE[COMPARABLE],BOOLEAN]): BOOLEAN
      -- Do all items satisfy test?

   exists (test: FUNCTION[ANY,TUPLE[COMPARABLE],BOOLEAN]): BOOLEAN
      -- Does at least one item satisfy test?

feature(s) from SET
   make
      -- Creation of an empty SET.
      ensure
         is_empty

feature(s) from AVL_HELPER
   -- Interface used by descendants:

   new_node (e: E): AVL_SET_NODE[E]
      require
         e /= Void
      ensure
         --old lost_nodes.count > 0 implies
         --   (lost_nodes.count = old lost_nodes.count - 1
         --    and then Result = old lost_nodes.last)

   discard_node (n: AVL_SET_NODE[E])
      require
         n /= Void
      ensure
         discarded: lost_nodes /= Void implies lost_nodes.count = old lost_nodes.count + 1

feature(s) from AVL_HELPER
   -- Internals:

   lost_nodes: COLLECTION[AVL_SET_NODE[E]]
      -- Keeps discarded nodes to avoid memory leaks. Should be a once function. May return Void if lost
      -- nodes are not kept.

   a_new_node (e: E): AVL_SET_NODE[E]
      require
         e /= Void
      ensure
         Result /= Void;
         Result.item = e

feature(s) from SAFE_EQUAL
   test (e1, e2: E): BOOLEAN
      -- In order to avoid run-time type errors, feature safe_equal calls
      -- is_equal only when e1 and e2 have exactly the same dynamic
      -- type. Furthermore, this feature avoids argument passing from some
      -- expanded type to the corresponding reference type (no automatic
      -- allocation of some reference type during the comparison).

   safe_equal (e1, e2: E): BOOLEAN
      -- In order to avoid run-time type errors, feature safe_equal calls
      -- is_equal only when e1 and e2 have exactly the same dynamic
      -- type. Furthermore, this feature avoids argument passing from some
      -- expanded type to the corresponding reference type (no automatic
      -- allocation of some reference type during the comparison).

feature(s) from AVL_SET
   root: AVL_SET_NODE[E]

feature(s) from AVL_SET
   debug_string: STRING

feature(s) from AVL_SET
   -- Iterating internals:

   build_map
      require
         build_needed: map_dirty
      ensure
         build_done: not map_dirty

   map: FAST_ARRAY[AVL_SET_NODE[E]]
      -- Elements in a row for iteration. See build_map.

   map_dirty: BOOLEAN
      -- True when the map needs to be built again for the iterators. See
      -- build_map.

feature(s) from AVL_SET
   -- from AVL_HELPER

   node_memo: MEMO[AVL_SET_NODE[E]]

   inserted_node_memo: MEMO[AVL_SET_NODE[E]]


invariant

    not map_dirty implies map.count = count;

    count > 0 implies root /= Void and then root.count = count;

end of AVL_SET[E->COMPARABLE]