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}