h_multimap.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>  <--------------


class H_MULTIMAP_IMPL{KEY,ELT}

class H_MULTIMAP_IMPL{KEY,ELT} is -- This class implements the multimap based upon hash tables. -- Version 1.1 Apr 97. Copyright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 1 Mar 96 bv Original -- 3 Apr 97 kh Changed for CARD instead of INT private include DYNAMIC_DATABUCKET_TABLE{KEY,BAG{ELT}} create -> create, map_key! -> ind! ; readonly attr total_size : CARD ; copy : SAME pre ~void(self) post true -- (result = self) is -- This routine returns an identical copy of self. Note that this is -- not the same as for dynamic data buckets since each of the 'bags' has also -- to be copied! res : SAME := new ; res.store := store.create(store.asize) ; res.asize := asize ; res.n_inds := n_inds ; res.minsize := minsize ; res.bound := bound ; res.doubles := doubles ; res.split_pos := split_pos ; loop index : CARD := 0.upto!(asize-1) ; res.store[index] := store[index].copy_list ; loc_list : DATABUCKET{KEY,BAG{ELT}} := res.store[index] ; loop loc_item : DATABUCKET{KEY,BAG{ELT}} := loc_list.list! ; loc_item.data := loc_item.data.copy end end ; res.total_size := total_size ; return res end ; has( key : KEY, elem : ELT ) : BOOL pre ~void(self) post true is -- This predicate returns true if and only if there is an element elem -- in the map with the given key. loop bkt : DATABUCKET{KEY,BAG{ELT}} := bucket(hash(key)).list! ; if elt_key_eq(key,bkt.item) then return bkt.data.contains(elem) end end ; return false end ; contains( elem : TUP{KEY,ELT} ) : BOOL pre ~void(self) post true is -- This predicate returns true if and only if there is an element elem -- in the map with the given key. return has(elem.t1,elem.t2) end ; size : CARD is -- This routine returns the total size of the map. return total_size end ; n_targets( key : KEY ) : CARD pre ~void(self) post true is -- This routine returns the number of targets corresponding to the given -- key. loop bkt : DATABUCKET{KEY,BAG{ELT}} := bucket(hash(key)).list! ; if elt_key_eq(key,bkt.item) then return bkt.data.size end end ; return 0 end ; aset( key : KEY, elem : ELT ) pre ~void(self) post true -- ????? map_aget(key) = elem is -- This routine maps the given key to the given element. hash_num : CARD := hash(key) ; loop bkt : DATABUCKET{KEY,BAG{ELT}} := bucket(hash_num).list! ; if elt_key_eq(bkt.item,key) then ssize : CARD := bkt.data.size ; bkt.data.add(elem) ; if ssize < bkt.data.size then total_size := total_size + 1 end ; return end end ; newset : BAG{ELT} := BAG{ELT}::create ; newset.add(elem) ; set_bucket(hash_num,DATABUCKET{KEY,BAG{ELT}}::create( key,newset,bucket(hash_num))) ; total_size := total_size + 1 ; n_inds := n_inds + 1 ; update_insert end ; delete( key : KEY, elem : ELT ) pre ~void(self) post true -- and one less element contained! is -- This routine deletes a single occurrence of the key/value pair given. bkt, prev : DATABUCKET{KEY,BAG{ELT}} ; hash_num : CARD := hash(key) ; bkt := bucket(hash_num) ; loop until!(void(bkt)) ; if elt_key_eq(bkt.item,key) then if bkt.data.contains(elem) then total_size := total_size - 1 ; if bkt.data.size > 1 then bkt.data.delete(elem) else if void(prev) then set_bucket(hash_num,bkt.next) else prev.next(bkt.next) end ; n_inds := n_inds - 1 ; update_delete end end ; return end ; prev := bkt ; bkt := bkt.next end end ; delete( key : KEY ) pre ~void(self) post true is -- This routine deletes all of the map elements associated with the -- given key. dummy : BAG{ELT} := map_delete(key) ; total_size := total_size - dummy.size end ; delete_all( key : KEY, elem : ELT ) pre ~void(self) post true is -- This routine deletes all occurences of the key value pair(k,e) by -- iterating through 'delete' until convergence. old_n_targs : CARD := n_targets(key) ; loop delete(key,elem) ; new_n_targs : CARD := n_targets(key) ; until!(new_n_targs = old_n_targs) ; old_n_targs := new_n_targs end; end ; target!( once key : KEY ) : ELT pre ~void(self) post ~void(result) is -- This iter returns in sequence all of the data values associated with -- the given key. loop bkt : DATABUCKET{KEY,BAG{ELT}} := bucket(hash(key)).list! ; if elt_key_eq(key,bkt.item) then loop yield bkt.data.elt! end ; quit end end end ; elt! : TUP{KEY,ELT} pre ~void(self) post ~void(result) is -- This iter yields all of the mappings which are identified in this map -- in an arbitrary sequence. loop bkt : DATABUCKET{KEY,BAG{ELT}} := bucket(0.upto!(asize - 1)) ; loop bucket : DATABUCKET{KEY,BAG{ELT}} := bkt.list! ; loop yield TUP{KEY,ELT}::create(bkt.item,bucket.data.elt!) end end end end ; target! : ELT pre ~void(self) post ~void(result) is -- This iter uses the elt! iter to produce all pairs, returning only -- the target component! loop yield elt!.t2 end end ; unique! : TUP{KEY,ELT} pre ~void(self) post ~void(result) is -- This iter yields each of the unique tuples in self. This -- implementation first converts to a set and then yields the elements. -- A more efficient implementation is desirable. loc_set : VSET{TUP{KEY,ELT}} := VSET{TUP{KEY,ELT}}::create(self) ; loop yield loc_set.elt! end end ; pair! : TUP{KEY,ELT} pre ~void(self) is -- This iter yields all of the key value pairs in the multimap in -- an arbitrary order. loop bkt : DATABUCKET{KEY,BAG{ELT}} := bucket(0.upto!(asize - 1)) ; loop loc_bucket : DATABUCKET{KEY,BAG{ELT}} := bkt.list! ; loop yield TUP{KEY,ELT}::create(bkt.item,loc_bucket.data.elt!) end end end end ; end ; -- H_MULTIMAP_IMPL

class VMULTIMAP{ITP,TTP} < $VMULTIMAP{ITP,TTP}

class VMULTIMAP{ITP,TTP} < $VMULTIMAP{ITP,TTP} is -- This class provides an implementation of a multimap with value -- semantics using a hash table based on data buckets. -- Version 1.1 Apr 97. Copyright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 1 Mar 96 bv Original -- 3 Apr 97 kh Changed for CARD instead of INT include RO_MULTIMAP_INCL{ITP,TTP} size -> ; include H_MULTIMAP_IMPL{ITP,TTP} aset -> aset, delete -> delete ; is_eq( other : $OB ) : BOOL is -- This predicate returns true if and only if self is equal to other. -- Note that this definition of equality has been broadened to include read- -- only bags of the correct tuple! typecase other when $RO_BAG{TUP{ITP,TTP}} then if size /= other.size then return false end ; loop elem : TUP{ITP,TTP} := other.unique! ; if count(elem) /= other.count(elem) then return false end end ; return true else return false end end ; add( elem : TUP{ITP,TTP} ) : SAME pre ~void(self) post result.contains(elem) is -- This routine returns a new copy of self to which the given element -- has been added. res : SAME := copy ; res[elem.t1] := elem.t2 ; return res end ; delete( elem : TUP{ITP,TTP} ) : SAME pre ~void(self) post ~result.contains(elem) or (result.count(elem) = (count(elem) - 1)) is -- This routine returns a copy of self from which one element elt_eq -- to elem has been deleted (if present!). res : SAME := copy ; res.delete(elem.t1,elem.t2) ; return res end ; delete_all( elem : TUP{ITP,TTP} ) : SAME pre ~void(self) post ~result.contains(elem) is -- This routine returns a copy of self from which all elements which are -- elt_eq to elem have been deleted (if any are present!). res : SAME := copy ; res.delete_all(elem.t1,elem.t2) ; return res end ; hash : CARD pre true -- irrespective of value post true -- irrespective of result is -- This routine computes and returns a hash value for the map based on -- all of its elements. res : NUM_BITS := NUM_BITS::create ; loop loc_hash : CARD := elt_hash(elt!) ; if res.card = 0 then res := NUM_BITS::create(loc_hash) else res := res.convolve(NUM_BITS::create(loc_hash)) end end ; return res.card end ; end ; -- VMULTIMAP

class MULTIMAP{KEY,ETP} < $MULTIMAP{KEY,ETP}

class MULTIMAP{KEY,ETP} < $MULTIMAP{KEY,ETP} is -- This class implements the multimap abstraction using both readonly -- and modifying operations. -- Version 1.1 Nov 98. Copyright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 1 Mar 96 bv Original -- 21 Nov 98 kh Revised for 1.2 include MULTIMAP_INCL{KEY,ETP} size -> ; include H_MULTIMAP_IMPL{KEY,ETP} aset -> aset, delete -> delete ; end ; -- MULTIMAP{KEY,ETP}