Skip to content

Commit 31987c5

Browse files
committed
---
yaml --- r: 12925 b: refs/heads/master c: 83ee4ac h: refs/heads/master i: 12923: 4f8bf0a v: v3
1 parent 91af4db commit 31987c5

File tree

2 files changed

+135
-147
lines changed

2 files changed

+135
-147
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 073f90cdc493d1ea9bf715f5cf8234ea320a5d4a
2+
refs/heads/master: 83ee4ac5ea5f121b3667ad552a5d8597aa8620c9
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
55
refs/heads/try: 2898dcc5d97da9427ac367542382b6239d9c0bbf

trunk/src/libstd/map.rs

Lines changed: 134 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ iface map<K: copy, V: copy> {
6969
// FIXME: package this up and export it as a datatype usable for
7070
// external code that doesn't want to pay the cost of a box. (#2344)
7171
mod chained {
72+
export t, mk, hashmap;
73+
7274
type entry<K, V> = {
7375
hash: uint,
7476
key: K,
@@ -94,186 +96,172 @@ mod chained {
9496
found_after(@entry<K,V>, @entry<K,V>)
9597
}
9698

97-
fn search_rem<K: copy, V: copy>(
98-
tbl: t<K,V>, k: K, h: uint, idx: uint,
99-
e_root: @entry<K,V>) -> search_result<K,V> {
100-
let mut e0 = e_root;
101-
let mut comp = 1u; // for logging
102-
loop {
103-
alt e0.next {
99+
impl private_methods<K: copy, V: copy> for t<K, V> {
100+
fn search_rem(k: K, h: uint, idx: uint,
101+
e_root: @entry<K,V>) -> search_result<K,V> {
102+
let mut e0 = e_root;
103+
let mut comp = 1u; // for logging
104+
loop {
105+
alt e0.next {
106+
absent {
107+
#debug("search_tbl: absent, comp %u, hash %u, idx %u",
108+
comp, h, idx);
109+
ret not_found;
110+
}
111+
present(e1) {
112+
comp += 1u;
113+
let e1_key = e1.key; // Satisfy alias checker.
114+
if e1.hash == h && self.eqer(e1_key, k) {
115+
#debug("search_tbl: present, comp %u, \
116+
hash %u, idx %u",
117+
comp, h, idx);
118+
ret found_after(e0, e1);
119+
} else {
120+
e0 = e1;
121+
}
122+
}
123+
}
124+
};
125+
}
126+
127+
fn search_tbl(k: K, h: uint) -> search_result<K,V> {
128+
let idx = h % vec::len(self.chains);
129+
alt self.chains[idx] {
104130
absent {
105131
#debug("search_tbl: absent, comp %u, hash %u, idx %u",
106-
comp, h, idx);
132+
0u, h, idx);
107133
ret not_found;
108134
}
109-
present(e1) {
110-
comp += 1u;
111-
let e1_key = e1.key; // Satisfy alias checker.
112-
if e1.hash == h && tbl.eqer(e1_key, k) {
135+
present(e) {
136+
// FIXME: This copy of the key is not good for perf
137+
if e.hash == h && self.eqer(copy e.key, k) {
113138
#debug("search_tbl: present, comp %u, hash %u, idx %u",
114-
comp, h, idx);
115-
ret found_after(e0, e1);
139+
1u, h, idx);
140+
ret found_first(idx, e);
116141
} else {
117-
e0 = e1;
142+
ret self.search_rem(k, h, idx, e);
118143
}
119144
}
120145
}
121-
};
122-
}
123-
124-
fn search_tbl<K: copy, V: copy>(
125-
tbl: t<K,V>, k: K, h: uint) -> search_result<K,V> {
126-
let idx = h % vec::len(tbl.chains);
127-
alt tbl.chains[idx] {
128-
absent {
129-
#debug("search_tbl: absent, comp %u, hash %u, idx %u",
130-
0u, h, idx);
131-
ret not_found;
132-
}
133-
present(e) {
134-
// FIXME: This copy of the key is not good for perf
135-
if e.hash == h && tbl.eqer(copy e.key, k) {
136-
#debug("search_tbl: present, comp %u, hash %u, idx %u",
137-
1u, h, idx);
138-
ret found_first(idx, e);
139-
} else {
140-
ret search_rem(tbl, k, h, idx, e);
141-
}
142-
}
143146
}
144-
}
145147

146-
fn insert<K: copy, V: copy>(tbl: t<K,V>, k: K, v: V) -> bool {
147-
let hash = tbl.hasher(k);
148-
alt search_tbl(tbl, k, hash) {
149-
not_found {
150-
tbl.count += 1u;
151-
let idx = hash % vec::len(tbl.chains);
152-
let old_chain = tbl.chains[idx];
153-
tbl.chains[idx] = present(@{
154-
hash: hash,
155-
key: k,
156-
mut value: v,
157-
mut next: old_chain});
158-
ret true;
159-
}
160-
found_first(_, entry) {
161-
entry.value = v;
162-
ret false;
163-
}
164-
found_after(_, entry) {
165-
entry.value = v;
166-
ret false
167-
}
168-
}
169-
}
170-
171-
fn get<K: copy, V: copy>(tbl: t<K,V>, k: K) -> core::option<V> {
172-
alt search_tbl(tbl, k, tbl.hasher(k)) {
173-
not_found {
174-
ret core::option::none;
175-
}
176-
177-
found_first(_, entry) {
178-
ret core::option::some(entry.value);
179-
}
180-
181-
found_after(_, entry) {
182-
ret core::option::some(entry.value);
183-
}
184-
}
185-
}
186-
187-
fn remove<K: copy, V: copy>(tbl: t<K,V>, k: K) -> core::option<V> {
188-
alt search_tbl(tbl, k, tbl.hasher(k)) {
189-
not_found {
190-
ret core::option::none;
191-
}
192-
193-
found_first(idx, entry) {
194-
tbl.count -= 1u;
195-
tbl.chains[idx] = entry.next;
196-
ret core::option::some(entry.value);
197-
}
198-
199-
found_after(eprev, entry) {
200-
tbl.count -= 1u;
201-
eprev.next = entry.next;
202-
ret core::option::some(entry.value);
203-
}
148+
fn rehash() {
149+
let n_old_chains = vec::len(self.chains);
150+
let n_new_chains: uint = uint::next_power_of_two(n_old_chains+1u);
151+
let new_chains = chains(n_new_chains);
152+
for self.each_entry {|entry|
153+
let idx = entry.hash % n_new_chains;
154+
entry.next = new_chains[idx];
155+
new_chains[idx] = present(entry);
156+
}
157+
self.chains = new_chains;
204158
}
205-
}
206-
207-
fn chains<K: copy, V: copy>(nchains: uint) -> [mut chain<K,V>] {
208-
ret vec::to_mut(vec::from_elem(nchains, absent));
209-
}
210159

211-
fn each_entry<K: copy, V: copy>(tbl: t<K, V>,
212-
blk: fn(@entry<K,V>) -> bool) {
213-
let mut i = 0u, n = vec::len(tbl.chains);
214-
while i < n {
215-
let mut chain = tbl.chains[i];
216-
loop {
217-
chain = alt chain {
218-
absent { break; }
219-
present(entry) {
220-
let next = entry.next;
221-
if !blk(entry) { ret; }
222-
next
223-
}
160+
fn each_entry(blk: fn(@entry<K,V>) -> bool) {
161+
let mut i = 0u, n = vec::len(self.chains);
162+
while i < n {
163+
let mut chain = self.chains[i];
164+
loop {
165+
chain = alt chain {
166+
absent { break; }
167+
present(entry) {
168+
let next = entry.next;
169+
if !blk(entry) { ret; }
170+
next
171+
}
172+
}
224173
}
174+
i += 1u;
225175
}
226-
i += 1u;
227-
}
228-
}
229-
230-
fn rehash<K: copy, V: copy>(tbl: t<K,V>) {
231-
let n_old_chains = vec::len(tbl.chains);
232-
let n_new_chains: uint = uint::next_power_of_two(n_old_chains + 1u);
233-
let new_chains = chains(n_new_chains);
234-
for each_entry(tbl) {|entry|
235-
let idx = entry.hash % n_new_chains;
236-
entry.next = new_chains[idx];
237-
new_chains[idx] = present(entry);
238-
}
239-
tbl.chains = new_chains;
240-
}
241-
242-
fn each<K: copy, V: copy>(tbl: t<K,V>, blk: fn(K,V) -> bool) {
243-
for each_entry(tbl) {|entry|
244-
if !blk(copy entry.key, copy entry.value) { break; }
245176
}
246177
}
247178

248179
impl hashmap<K: copy, V: copy> of map<K, V> for t<K, V> {
249180
fn size() -> uint { self.count }
250181

182+
fn contains_key(k: K) -> bool {
183+
let hash = self.hasher(k);
184+
alt self.search_tbl(k, hash) {
185+
not_found {false}
186+
found_first(*) | found_after(*) {true}
187+
}
188+
}
189+
251190
fn insert(k: K, v: V) -> bool {
252-
let grew = insert(self, k, v);
253-
if grew {
191+
let hash = self.hasher(k);
192+
alt self.search_tbl(k, hash) {
193+
not_found {
194+
self.count += 1u;
195+
let idx = hash % vec::len(self.chains);
196+
let old_chain = self.chains[idx];
197+
self.chains[idx] = present(@{
198+
hash: hash,
199+
key: k,
200+
mut value: v,
201+
mut next: old_chain});
202+
203+
// consider rehashing if more 3/4 full
254204
let nchains = vec::len(self.chains);
255205
let load = {num: (self.count + 1u) as int,
256206
den: nchains as int};
257-
// Structural consts would be nice. This is a const 3/4
258-
// load factor that we compare against.
259-
if !util::rational_leq(load, {num:3, den:4}) { rehash(self); }
207+
if !util::rational_leq(load, {num:3, den:4}) {
208+
self.rehash();
209+
}
210+
211+
ret true;
212+
}
213+
found_first(_, entry) {
214+
entry.value = v;
215+
ret false;
216+
}
217+
found_after(_, entry) {
218+
entry.value = v;
219+
ret false
220+
}
260221
}
261-
grew
262222
}
263223

264-
fn contains_key(k: K) -> bool { option::is_some(get(self, k)) }
224+
fn find(k: K) -> option<V> {
225+
alt self.search_tbl(k, self.hasher(k)) {
226+
not_found {none}
227+
found_first(_, entry) {some(entry.value)}
228+
found_after(_, entry) {some(entry.value)}
229+
}
230+
}
265231

266-
fn get(k: K) -> V { option::get(get(self, k)) }
232+
fn get(k: K) -> V {
233+
option::get(self.find(k))
234+
}
267235

268-
fn find(k: K) -> option<V> { get(self, k) }
236+
fn remove(k: K) -> option<V> {
237+
alt self.search_tbl(k, self.hasher(k)) {
238+
not_found {none}
239+
found_first(idx, entry) {
240+
self.count -= 1u;
241+
self.chains[idx] = entry.next;
242+
some(entry.value)
243+
}
244+
found_after(eprev, entry) {
245+
self.count -= 1u;
246+
eprev.next = entry.next;
247+
some(entry.value)
248+
}
249+
}
250+
}
269251

270-
fn remove(k: K) -> option<V> { remove(self, k) }
252+
fn each(blk: fn(K,V) -> bool) {
253+
for self.each_entry { |entry|
254+
if !blk(copy entry.key, copy entry.value) { break; }
255+
}
256+
}
271257

272-
fn each(blk: fn(K, V) -> bool) { each(self, blk); }
258+
fn each_key(blk: fn(K) -> bool) { self.each { |k, _v| blk(k)} }
273259

274-
fn each_key(blk: fn(K) -> bool) { each(self) { |k, _v| blk(k)} }
260+
fn each_value(blk: fn(V) -> bool) { self.each { |_k, v| blk(v)} }
261+
}
275262

276-
fn each_value(blk: fn(V) -> bool) { each(self) { |_k, v| blk(v)} }
263+
fn chains<K,V>(nchains: uint) -> [mut chain<K,V>] {
264+
ret vec::to_mut(vec::from_elem(nchains, absent));
277265
}
278266

279267
fn mk<K: copy, V: copy>(hasher: hashfn<K>, eqer: eqfn<K>) -> t<K,V> {

0 commit comments

Comments
 (0)