bag_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_BAG_INCL{ETP}
partial class RO_BAG_INCL{ETP} is
-- This is a partial class for read-only implementations. It implements
-- other operations in terms of has and elt!
-- Version 1.2 Nov 98. Copyright K Hopper, U of Waikato
-- Development History
-- -------------------
-- Date Who By Detail
-- ---- ------ ------
-- 1 Jun 96 bg Original
-- 13 Mar 97 kh Adapted to use CARD
-- 5 Nov 98 kh Redefined as 1.2 dist, added pre/post conds.
include CONTAINER{ETP}
unique! -> ;
-- The following stubs are for core features which must be defined.
stub create : SAME ;
-- This creation routine returns an empty bag.
stub add(
elem : ETP
) : SAME ;
-- This routine returns a new bag consisting of self and the new element.
stub delete(
elem : ETP
) : SAME ;
-- This routine returns a new bag consisting of self except for a single
-- element matching the given one (if any).
stub delete_all(
elem : ETP
) : SAME ;
-- This routine returns a new bag consisting of selfexcept for all
-- occurrences of the element equal to elem.
stub unique! : ETP ;
-- This iter yields one object of each value in the bag, irrespective
-- of how many copies there are.
stub copy : SAME ;
-- This routine returns a new copy of the baga nd its contents.
create(
arg : $ELT{ETP}
) : SAME
pre ~void(arg)
post ~void(result)
is
-- This routine creates a new bag containing all of the elements of arg.
me : SAME := create ;
loop
me := me.add(arg.elt!)
end ;
return me
end ;
create(
arg : ARRAY{ETP}
) : SAME
pre ~void(arg)
post ~void(result)
is
-- This routine creates a new bag containing all of the elements of arg.
--
-- NOTE The provision of this separate routine from the one above permits
-- the use of type inference so that the following may be written :--
--
-- carrier : BAG{CARD} := create(|1, 2, 3|) ;
me : SAME := create ;
loop
me := me.add(arg.elt!)
end ;
return me
end ;
is_empty : BOOL is
-- This predicate returns true if and only if there are no elements in
-- the bag.
return size = 0
end ;
equals(
other : $RO_BAG{ETP}
) : BOOL
pre ~void(self)
and ~void(other)
post true
is
-- This routine returns true if and only if the bags self and other
-- have identical counts of identical elements.
if size /= other.size then
return false
end ;
loop
elem : ETP := unique! ;
if count(elem) /= other.count(elem) then
return false
end
end ;
return true
end ;
is_subset_of(
other : $RO_BAG{ETP}
) : BOOL
pre ~void(self)
and ~void(other)
post true
is
-- This routine returns true if and only if self is a subset of other.
-- This is defined to be the condition in which other has all of
-- the different elements within self and, for each one, has a greater or
-- equal count.
loop
elem : ETP := unique! ;
if count(elem) > other.count(elem) then
return false
end
end ;
return true
end ;
n_unique : CARD
pre ~void(self)
post (result >= 1)
and (result <= size)
is
-- This routine returns the number of unique elements in self.
res : CARD := 0 ;
loop
discard : ETP := unique! ;
res := res + 1
end ;
return res
end ;
concat(
arg : $ELT{ETP}
) : SAME
pre ~void(self)
and ~void(arg)
post (result.size <= (self.size + arg.size))
is
-- This routine returns a new bag consisting of all of the elements of
-- both self and arg in which elements having multiple occurrences have the
-- sum of the number in self and arg.
res : SAME := copy ;
loop
res := res.add(arg.elt!)
end ;
return res
end ;
union(
other : $RO_BAG{ETP}
) : SAME
pre ~void(self)
and ~void(other)
post (result.size <= (self.size + other.size))
is
-- This routine returns a bag which contains all of the elements in
-- both self and other, the result having counts which are the sum of
-- the individual counts in each.
res : SAME := copy ;
loop
loc_elt : ETP := other.elt! ;
if ~res.contains(loc_elt) then
res := res.add(loc_elt)
else
if other.count(loc_elt) > res.count(loc_elt) then
res := res.add(loc_elt)
end
end
end ;
return res
end ;
intersection(
other : $RO_BAG{ETP}
) : SAME
pre ~void(self)
and ~void(other)
post ~void(result)
is
-- This routine returns the bag which contains all of the different
-- elements in both bags, the count of each element being the lower of
-- the count in self and other.
res : SAME := copy ;
loop
elem : ETP := unique! ;
num_to_delete : CARD := (count(elem) - other.count(elem)) ;
if num_to_delete > 0 then
loop
num_to_delete.times! ;
res := res.delete(elem)
end
end
end ;
return res
end ;
end ; -- RO_BAG_INCL
partial class BAG_INCL{ETP}
partial class BAG_INCL{ETP} is
-- This is a partial class which implements the mathematical notion of
-- a bag of elements which may occur as multiple copies of identical elements.
-- Version 1.0 Nov 98. Copyright K Hopper, U of Waikato
-- Development History
-- -------------------
-- Date Who By Detail
-- ---- ------ ------
-- 5 Nov 98 kh From 1.2 dist, added pre/post conditions.
include RO_BAG_INCL{ETP} ;
create(
arg : $ELT{ETP}
) : SAME
pre ~void(arg)
post (result.size = arg.size)
is
-- This routine creates and returns a new bag containing all of the
-- elements of arg.
me : SAME := create ;
loop
me := me.add(arg.elt!)
end ;
return me
end ;
as_value : VBAG{ETP}
pre ~void(self)
post ~void(result)
is
-- This routine returns the value associated with this reference to
-- a bag.
return VBAG{ETP}::create(self)
end ;
clear
pre ~void(self)
post size = 0
is
-- This routine deletes all exisiting elements of self,leaving the
-- bag empty. This is done by making a list of all of the different
-- elements and then deleting all occurrences of that element in a loop.
list : ARRAY{ETP} := ARRAY{ETP}::create(n_unique) ;
loop
list.set!(unique!)
end ;
loop
delete_all(list.elt!)
end
end ;
add(
elem : ETP
) : SAME
pre ~void(self)
post result.contains(elem)
is
-- This routine returns a new bag containing all the elements of self
-- and the new element given.
res : SAME := copy ;
res.add(elem) ;
return res
end ;
delete(
elem : ETP
) : SAME
pre ~void(self)
post (contains(elem)
and ((result.size + 1) = self.size))
or (~contains(elem)
and (result.size = self.size))
is
-- This routine returns a new bag which is identical to self except that
-- it has one less copy of the element which equals the given one.
res : SAME := copy ;
res.delete(elem) ;
return res
end ;
delete_all(
elem : ETP
) : SAME
pre ~void(self)
post ~result.contains(elem)
is
-- This routine returns a new bag which is the same as self except that
-- there are no elements which equal the given one.
res : SAME := copy ;
res.delete_all(elem) ;
return res
end ;
-- Implementation note: For the following routines care must be taken
-- to ensure that the collection being iterated over is not being
-- modified at the same time. Thus it is best to always iterate over
-- 'arg', since self is being modified.
to_concat(
arg : $ELT{ETP}
)
pre ~void(self)
and ~void(arg)
post (self.size <= (initial(self.size) + arg.size))
is
-- This routine concatenates the elements of 'arg' to self.
loop
add(arg.elt!)
end
end ;
to_union(
arg : $RO_BAG{ETP}
)
pre ~void(self)
and ~void(arg)
post (self.size >= initial(self.size))
is
-- This routine turns self into a union of self and arg.
loop
arg_elt : ETP := arg.elt! ;
if ~contains(arg_elt) then
add(arg_elt)
else
if arg.count(arg_elt) > count(arg_elt) then
add(arg_elt)
end
end
end
end ;
to_intersection(
arg : $RO_BAG{ETP}
)
pre ~void(self)
and ~void(arg)
post true
is
-- This routine turns this bag into the intersection of self and arg.
list : ARRAY{ETP} := ARRAY{ETP}::create(n_unique) ;
loop -- copy to avoid concurrency snags
list.set!(unique!)
end ;
loop
elem : ETP := list.elt! ;
if ~arg.contains(elem) then
delete_all(elem)
end
end ;
-- For elements in the intersection, reduce the number of
-- repetitions to the min number of occurences
loop
elem : ETP := arg.unique! ;
if count(elem) > arg.count(elem) then
num_to_delete : CARD := count(elem) - arg.count(elem) ;
loop
num_to_delete.times! ;
delete(elem)
end
end
end
end ;
end ; -- BAG_INCL