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}