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