multimap_incl.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 
------------------------->  GNU Sather - sourcefile  <-------------------------
-- Copyright (C) 2000 by K Hopper, University of Waikato, New Zealand        --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute  and/or modify it under the terms of the GNU Library General --
-- Public  License (LGPL)  as published  by the  Free  Software  Foundation; --
-- either version 2 of the license, or (at your option) any later version.   --
-- This  library  is distributed  in the  hope that it will  be  useful, but --
-- WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See Doc/LGPL for more details.       --
-- The license text is also available from:  Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                     --
-------------->  Please email comments to <bug-sather@gnu.org>  <--------------


partial class RO_MULTIMAP_INCL{KEY,ETP}

partial class RO_MULTIMAP_INCL{KEY,ETP} is -- This partial class contains all of those multimap features which are -- common irrespective of the kinds of KEY and ETP. -- Version 1.2 Nov 98. Copyright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 1 Jun 96 bg Original -- 4 Apr 97 kh Changed for INT to CARD -- 10 Nov 98 kh Revised for 1.2, added pre/post conditions. include CONTAINER{TUP{KEY,ETP}} contains ->, unique! -> ; stub create : SAME ; -- This routine returne a new empty map. stub copy : SAME ; -- This routine returns a new map which is an exact copy of self. stub n_targets( key : KEY ) : CARD ; -- This routine returns the number of elements mapped by the given key. stub add( elem : TUP{KEY,ETP} ) : SAME ; -- This routine returns a new multimap which has all of the elements of -- self and in addition the element elem. stub delete( elem : TUP{KEY,ETP} ) : SAME ; -- This routine returns a new map which is identical to self except that -- the indicated element has been removed. stub delete_all( elem : TUP{KEY,ETP} ) : SAME ; -- This routine returns a new multimap which is the result of removing -- all of the elements matching elem from the initial value of self. stub ind! : KEY ; -- This iter yields the indices of the multimap in an arbitrary order, stub elt! : ETP ; -- This iter yields the elements of the map in an arbitrary order. stub target!( once key : KEY ) : ETP ; -- This iter yields the values mapped by the given index in an arbitrary -- order. stub unique! : TUP{KEY,ETP} ; -- This iter yields the unique elements of the map in an implementation- -- dependent order. stub pair! : TUP{KEY,ETP} ; -- This iter yields all of the key value pairs in the multimap in an -- implementation-dependent order. create( arg : $ELT{TUP{KEY,ETP}} ) : SAME is -- This routine creates a new multimap from the elements of the argument -- array. res : SAME := create ; loop res := res.add(arg.elt!) end ; return res end ; array : ARRAY{TUP{KEY,ETP}} pre ~void(self) post (result.size = size) is -- This routine returns an array which contains all of the elements -- of self. res : ARRAY{TUP{KEY,ETP}} := ARRAY{TUP{KEY,ETP}}::create(size) ; loop res.set!(elt!) end ; return res end ; is_empty : BOOL is -- This predicate returns true if and only if the size of the map is zero -- - it has no elements. return size = 0 end ; has_ind( key : KEY ) : BOOL is -- This predicate returns true if and only if there is at least one -- target in the map corresponding to the given key. return n_targets(key) > 0 end ; equals( other : $RO_BAG{TUP{KEY,ETP}} ) : BOOL is -- This predicate returns true if and only if all of the mapped elements -- in other and self are mapped from the corresponding keys in equal numbers. if size /= other.size then return false end ; loop if ~contains(other.elt!) then return false end end ; return true end ; is_subset_of( arg : $RO_BAG{TUP{KEY,ETP}} ) : BOOL is -- This predicate returns true if and only if self contains a subset of -- the elements in arg. For elements that occur multiple times, the number -- of occurences of the element in arg must be greater than or equal to the -- number of occurrences in self. loop loc_elem : TUP{KEY,ETP} := unique! ; if count(loc_elem) > arg.count(loc_elem) then return false end end ; return true end ; count( arg : TUP{KEY,ETP} ) : CARD pre ~void(self) post (result <= size) is -- This routine returns the number of occurrences of arg in the multimap. res : CARD := 0 ; loop loc_elem : TUP{KEY,ETP} := elt! ; if elt_eq(arg,loc_elem) then res := res + 1 end end ; return res end ; n_unique : CARD pre true post (result <= size) is -- This routine returns the number of unique element pairs in self. res : CARD := 0 ; loop discard : TUP{KEY,ETP} := unique! ; res := res + 1 end ; return res end ; n_ind : CARD pre true post (result <= size) is -- This routine returns the count of unique keys in this multimap. res : CARD := 0 ; loop discard : KEY := ind! ; res := res + 1 end ; return res end ; add( key : KEY, elem : ETP ) : SAME pre ~void(self) post (result.size = size + 1) is -- This routine is a call for which the key and element are separate -- arguments. return add(TUP{KEY,ETP}::create(key,elem)) end ; delete( key : KEY, elem : ETP ) : SAME pre ~void(self) post (result.size >= (size - 1)) is -- This routine is a delete call for which the two components of the -- element are presented separately. The given element is deleted if present. return delete(TUP{KEY,ETP}::create(key,elem)) end ; delete_ind( key : KEY ) : SAME pre ~void(self) post ((result.size < size) and (result.n_ind = (n_ind - 1))) or ~self.has_ind(key) is -- This routine returns a new multimap from which all elements keyed by -- the given key have been deleted. res : SAME := copy ; loop res.delete(key,target!(key)) end ; return res end ; concat( arg : $ELT{TUP{KEY,ETP}} ) : SAME pre ~void(self) post (result.size = (size + arg.size)) is -- This routine returns a new multimap containing all the elements of -- self and arg. For elements that occur multiple times, the result -- contains the sum of the number of occurences in self and arg. res : SAME := copy ; loop res := res.add(arg.elt!) end ; return res end ; union( arg : $RO_BAG{TUP{KEY,ETP}} ) : SAME pre ~void(self) post (result.size <= (size + arg.size)) is -- This routine returns a new multimap containing the elements of self -- and arg. For elements that occur multiple times, the result contains -- the maximum number of occurrences in either self or arg. This definition -- permits the union of maps to be consistent with the union of bags. res : SAME := copy ; loop arg_elt : TUP{KEY,ETP} := arg.elt! ; if ~res.contains(arg_elt) then res := res.add(arg_elt) else if arg.count(arg_elt) > res.count(arg_elt) then res := res.add(arg_elt) end end end ; return res end ; intersection( arg : $RO_BAG{TUP{KEY,ETP}} ) : SAME pre ~void(self) post ((size > arg.size) and (result.size <= size)) or (result.size <= arg.size) is -- This routine returns a new mu;ltima[ which is the intersection of -- self and arg. For elements that occur multiple times, the result contains -- the minimum number of occurrences in either self or arg. res : SAME := copy ; num_to_delete : CARD ; loop loc_elem : TUP{KEY,ETP} := unique! ; if count(loc_elem) > arg.count(loc_elem) then num_to_delete := count(loc_elem) - arg.count(loc_elem) ; loop num_to_delete.times! ; res := res.delete(loc_elem) end end end ; return res end ; diff( arg : $RO_BAG{TUP{KEY,ETP}} ) : SAME pre ~void(self) post (result.size <= size) is -- This routine returns a new multimap containing all the elements of -- self that are not in arg. For elements that occur multiple times in self, -- the number of occurrences in the result is reduced by the number of -- occurrences in arg. res : SAME := copy ; num_to_delete : CARD ; loop loc_elem : TUP{KEY,ETP} := unique! ; num_to_delete := arg.count(loc_elem) ; loop num_to_delete.times! ; res := res.delete(loc_elem) end end ; return res end ; sym_diff( arg : $RO_BAG{TUP{KEY,ETP}} ) : SAME pre ~void(self) post (result.size < (size + arg.size)) -- ??????? is -- This routine returns a new multimap which is the result of carrying out the symmetric difference operation on self and arg. For elements that occur in both, the result contains the absolute value of the difference in the number of occurences. loc_union : SAME := union(arg) ; loc_intersect : SAME := intersection(arg) ; return loc_union.diff(loc_intersect) end ; end ; -- RO_MULTIMAP_INCL{KEY,ETP}

partial class MULTIMAP_INCL{KEY,ETP}

partial class MULTIMAP_INCL{KEY,ETP} is -- This is a partial class which implements the common features of -- muktimaps as specified in $MULTIMAP. -- The stubs must be replaced by a real function in any descendant that -- actually implements the abstraction. Particular implementations may -- replace also some of the non-stub operations by substantially more -- efficient versions, that make use of properties of the actual -- implementation. -- Version 1.2 Nov 98. Copyright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 1 Jun 96 bg Original -- 4 Apr 97 kh Changed for INT to CARD -- 10 Nov 98 kh Complete rewrite for 1.2, added pre/posts! include RO_MULTIMAP_INCL{KEY,ETP} ; stub aset( key : KEY, elem : ETP ) ; -- This routine sets the value of the element indicate by key to be elem. stub delete( key : KEY, elem : ETP ) ; -- This routine deletes the element of self indicated by the given -- key/element pair. stub delete( key : KEY ) ; -- This routine deletes all of the elements of self indicated by the -- given key. stub delete_all( key : KEY, elem : ETP ) ; -- This routine deletes all of the elements of self which are element -- equal to the given key/element pair. as_value : VMULTIMAP{KEY,ETP} pre ~void(self) post (result.size = size) is -- This routine returns a new multimap with the same value as self. return VMULTIMAP{KEY,ETP}::create(self) end ; clear pre ~void(self) post (size = 0) is -- This routine deletes all of the elements of self - leaving the -- multimap empty. loc_arr : ARRAY{TUP{KEY,ETP}} := ARRAY{TUP{KEY,ETP}}::create(n_unique) ; loop loc_arr.set!(unique!) end ; loop loc_elt : TUP{KEY,ETP} := loc_arr.elt! ; delete_all(loc_elt.t1,loc_elt.t2) end end ; add( elem : TUP{KEY,ETP} ) pre ~void(self) post self.size >= initial(size) is -- This routine merely adds the given element to self. [elem.t1] := elem.t2 end ; add( elem : TUP{KEY,ETP} ) : SAME pre ~void(self) post result.has_ind(elem.t1) is -- This routine returns a new multimap containing all the elements of -- self and elem. res : SAME := copy ; res[elem.t1] := elem.t2 ; return res end ; delete( elem : TUP{KEY,ETP} ) : SAME pre ~void(self) post ((size - result.size) <= 1) is -- This routine returns a new multimap which contains all of the -- elements of self except for an element equal to elem, if one exists. If -- more than one element is equal to elem, only one of them is deleted. res : SAME := copy ; res.delete(elem.t1,elem.t2) ; return res end ; delete_all( elem : TUP{KEY,ETP} ) : SAME pre ~void(self) post ((size - result.size) <= 1) is -- This routine returns a new multimap containing all the elements of -- self except for any elements equal to elem. res : SAME := copy ; res.delete_all(elem.t1,elem.t2) ; return res end ; to_union( arg : $RO_BAG{TUP{KEY,ETP}} ) pre ~void(self) post true -- (self = initial(self.union(arg))) is -- This routine modifies self so that it becomes the union of the -- initial value of self and arg. loop arg_elt : TUP{KEY,ETP} := arg.elt! ; if ~contains(arg_elt) then [arg_elt.t1] := arg_elt.t2 else if arg.count(arg_elt) > count(arg_elt) then [arg_elt.t1] := arg_elt.t2 end end end end ; to_intersection( arg : $RO_BAG{TUP{KEY,ETP}} ) pre ~void(self) post true -- (self = initial(self.intersection(arg))) is -- This routine modifies self to become the intersection of the original -- value of self and arg. In order to avoid iteration while deleting the -- unique elements are copied. num_to_delete : CARD ; loc_elem : TUP{KEY,ETP} ; loc_arr : ARRAY{TUP{KEY,ETP}} := ARRAY{TUP{KEY,ETP}}::create(n_unique) ; loop loc_arr.set!(unique!) end ; loop loc_elem := loc_arr.elt! ; if ~arg.contains(loc_elem) then delete_all(loc_elem.t1,loc_elem.t2) end end ; -- For elements in the intersection, reduce the number of -- repetitions to the minimum number of occurrences loop loc_elem := arg.unique! ; if count(loc_elem) > arg.count(loc_elem) then num_to_delete := count(loc_elem) - arg.count(loc_elem) ; loop num_to_delete.times! ; delete(loc_elem.t1,loc_elem.t2) end end end end ; end ; -- MULTIMAP_INCL{KEY,ETP}