2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * $XConsortium: imp_die.C /main/5 1996/08/21 15:52:00 drk $
26 * Copyright (c) 1993 HAL Computer Systems International, Ltd.
27 * All rights reserved. Unpublished -- rights reserved under
28 * the Copyright Laws of the United States. USE OF A COPYRIGHT
29 * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
32 * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
33 * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
34 * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
35 * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
38 * RESTRICTED RIGHTS LEGEND
39 * Use, duplication, or disclosure by the Government is subject
40 * to the restrictions as set forth in subparagraph (c)(l)(ii)
41 * of the Rights in Technical Data and Computer Software clause
42 * at DFARS 252.227-7013.
44 * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
51 #include "dynhash/imp_die.h"
54 #include "utility/c_iostream.h"
59 int steps[] = { 2, 3, 5, 7, 11, 13, 17, 21, 23, 29, 31, 37, 41, 43, 47, 51 };
62 #define PRIME_LEVLE_2 2147483647
64 imp_die::imp_die(int prime, int expected_n) :
65 p(prime), H(0), B(0), n(0), bucket_array(0), hash_table(0),
66 free_list_head(0), collected_records(0)
68 alloc_table(int(2.5*expected_n));
71 rand_generator.seed();
72 k = rand_generator.rand();
74 no_steps = sizeof(steps) / sizeof(int);
83 for ( int i = 0; i<B; i++ ) {
84 delete bucket_array[i];
87 bucket_holder* x = free_list_head;
89 bucket_holder* y = x -> next;
94 x = collected_records;
96 bucket_holder* y = x -> next;
103 delete bucket_array ;
106 //**********************************************************
107 // allocate new memory for the bucket table and hash table.
108 // H is the size of the bucket table before
109 // expansion. new\_H is the new size.
110 //**********************************************************
111 void imp_die::alloc_table(int new_H)
113 if ( bucket_array ) {
114 for ( int i = 0; i<B; delete bucket_array[i++] );
115 delete bucket_array ;
119 bucket_array = new imp_bucketPtr[B];
125 hash_table = new data_tPtr[new_H];
130 void imp_die::init_table()
132 for ( int i = 0; i < B; i++ ) {
133 bucket_array[i] = 0 ;
135 for ( i = 0; i < H; i++ ) {
140 void imp_die::clean()
145 for ( int i=0; i<B; i++ ) {
146 if ( bucket_array[i] ) {
147 delete bucket_array[i];
148 bucket_array[i] = 0 ;
152 for ( i=0; i<H; i++ )
156 /*****************************/
157 // collect all keys into
159 /*****************************/
160 void imp_die::collect_all_keys()
162 for ( int i = 0; i < B; i++ )
163 if ( bucket_array[i] ) {
166 if ( free_list_head ) {
168 //debug(cerr, "get from free list");
169 free_list_head = free_list_head -> next;
171 //debug(cerr, "get from new");
172 x = new bucket_holder;
174 //debug(cerr, int(x));
176 x -> data_ptr = bucket_array[i] -> remove_all();
178 delete bucket_array[i];
181 x -> next = collected_records;
182 collected_records = x;
186 /*****************************/
188 /*****************************/
189 Boolean imp_die::rehash()
195 if ( 2*n > H ) alloc_table(2*H);
199 k = rand_generator.rand();
201 bucket_holder *x = collected_records;
204 data_t* y = x -> data_ptr;
208 data_t *z = (data_t*)(y -> v_succ);
213 int hash = y -> bucket_num(k, p, B);
215 if ( bucket_array[hash] == 0 )
216 bucket_array[hash] = new imp_bucket;
218 bucket_array[hash] -> insert(y);
226 free_list_head = collected_records;
227 collected_records = 0;
229 Boolean rehash_done = true;
231 for ( int i = 0; i < B; i++ )
232 if ( bucket_array[i] ) {
233 if ( bucket_rehash(i) == false ) {
235 debug(cerr, *bucket_array[i]);
238 //throw(stringException("rehash() failed"));
242 if ( rehash_done == true )
247 /************************************/
249 /************************************/
250 Boolean imp_die::insert(data_t& v)
254 int hash = v.bucket_num(k, p, B);
256 if ( bucket_insert(hash, v) == false )
262 /******************************************/
264 /******************************************/
265 Boolean imp_die::remove(data_t& v)
267 MESSAGE(cerr, "imp_die::remove(data_t& v)");
268 int hash = v.bucket_num(k, p, B);
270 /*********************************/
271 // assure the bucket is not empty
272 /*********************************/
273 if ( bucket_remove(hash, v) == false )
278 /*********************************/
279 // delete the bucket if it becomes
281 /*********************************/
282 if ( bucket_array[hash] -> empty() == true ) {
283 delete bucket_array[hash];
284 bucket_array[hash] = 0;
290 /*******************************************************/
291 // first level hash function
292 /*******************************************************/
293 int imp_die::h(int key) const
295 return abs( k * key ) % p % B;
298 //static to_print = false;
299 /****************************************/
300 // select a proper value for parameter k
301 /****************************************/
302 Boolean imp_die::bucket_fix_k(int bucket_num)
306 Boolean injective = false;
308 imp_bucket& x = *bucket_array[bucket_num];
311 MESSAGE(cerr, "bucket_fix_k()");
314 if ( bucket_num == 412 )
320 while ( injective == false && loops < H ) {
322 injective = test_injective(x);
323 if ( injective == false ) {
325 x.k = abs(rand_generator.rand()) % ( p - 1 ) + 1;
332 Boolean imp_die::test_injective(imp_bucket& x)
334 //MESSAGE(cerr, "test_injective()");
335 long ind_out = x.first();
336 while ( ind_out != 0 ) {
338 data_t* out = x(ind_out);
341 if ( to_print == true ) {
343 debug(cerr, x.rotate);
348 int hash_out = out -> slot_num(x.k, x.rotate, PRIME_LEVLE_2, H);
350 long ind_in = ind_out;
353 while ( ind_in != 0 ) {
355 data_t* in = x(ind_in);
357 int hash_in = in -> slot_num(x.k, x.rotate, PRIME_LEVLE_2, H);
359 if ( hash_out == hash_in ) {
362 if ( to_print == true )
366 debug(cerr, ind_out);
367 debug(cerr, hash_in);
368 debug(cerr, hash_out);
384 Boolean imp_die::bucket_rotate(int bucket_num)
386 imp_bucket& x = *bucket_array[bucket_num];
390 int z = rand_generator.rand();
392 x.rotate = z % (H - 1) + 1;
393 int step = steps[z % no_steps];
395 Boolean all_fit = false;
398 while ( all_fit == false && loops < H ) {
400 long ind = x.first();
403 data_t* data_ptr = x(ind);
404 hash = data_ptr -> slot_num(x.k, x.rotate, PRIME_LEVLE_2, H);
406 if ( hash_table[hash] != 0 ) {
407 long ind1 = x.first();
408 while ( ind1 != ind ) {
410 hash = x(ind1) -> slot_num(x.k, x.rotate, PRIME_LEVLE_2, H);
412 hash_table[hash] = 0;
420 hash_table[hash] = data_ptr;
423 all_fit = ( ind == 0 ) ? true : false;
429 Boolean imp_die::bucket_insert(int bucket_num, data_t& v)
431 if ( bucket_array[bucket_num] == 0 ) {
432 bucket_array[bucket_num] = new imp_bucket();
435 imp_bucketPtr x = bucket_array[bucket_num];
439 if ( collected_records ) {
440 bucket_holder* first_list = collected_records;
441 y = first_list -> data_ptr;
443 first_list -> data_ptr = (data_t*)(y -> v_succ);
445 if ( first_list -> data_ptr == 0 ) {
446 collected_records = collected_records -> next;
456 int hash = y -> slot_num(x->k, x->rotate, PRIME_LEVLE_2, H);
458 if ( hash_table[hash] == 0 ) {
459 hash_table[hash] = y;
463 //*******************************
464 // clear the hash table entries
465 //*******************************
466 long ind = x -> first();
468 int hash = (*x)(ind) -> slot_num(x->k, x->rotate, PRIME_LEVLE_2, H);
470 if ( hash_table[hash] && *hash_table[hash] == *(*x)(ind) )
471 hash_table[hash] = 0;
475 return bucket_rehash(bucket_num);
477 debug(cerr, bucket_num);
479 debug(cerr, int(bucket_array));
480 debug(cerr, int(bucket_array[bucket_num]));
486 //*******************************
487 // rehash keys in the bucket
488 //*******************************
489 Boolean imp_die::bucket_rehash(int bucket_num)
491 bucket_fix_k(bucket_num);
492 return bucket_rotate(bucket_num);
495 Boolean imp_die::bucket_remove(int bucket_num, data_t& v)
497 imp_bucketPtr x = bucket_array[bucket_num];
499 if ( x == 0 ) return false;
501 int hash = v.slot_num(x->k, x->rotate, PRIME_LEVLE_2, H);
503 if ( hash_table[hash] && *hash_table[hash] == v ) {
505 x -> delete_cell(hash_table[hash]);
506 delete hash_table[hash];
507 hash_table[hash] = 0;
509 //MESSAGE(cerr, "afterremove the entry");
517 Boolean imp_die::bucket_member(int bucket_num, data_t& v) const
520 debug(cerr, bucket_num);
524 imp_bucketPtr x = bucket_array[bucket_num];
527 //MESSAGE(cerr, "empty bucket");
528 //debug(cerr, int(bucket_array));
532 int hash = v.slot_num(x->k, x->rotate, PRIME_LEVLE_2, H);
534 if ( hash_table[hash] ) {
535 v.dt = hash_table[hash] -> dt;
536 if ( *hash_table[hash] == v ) {
538 MESSAGE(cerr, "hash table entry match");
539 debug(cerr, int(this));
541 debug(cerr, *hash_table[hash]);
553 int imp_die::first_bucket()
561 void imp_die::next_bucket(int& ind)
569 imp_bucket* imp_die::get_bucket(int& ind)
571 while ( ind < B && bucket_array[ind] == 0 )
577 return bucket_array[ind];
580 /*******************************************************/
582 /*******************************************************/
583 ostream& imp_die::asciiOut(ostream& out)
585 int ind = first_bucket();
587 while ( ind != -1 ) {
589 imp_bucket* bucket = get_bucket(ind);
600 istream& imp_die::asciiIn(istream& in)
604 while ( in >> actor ) {
611 ostream& imp_die::asciiOut(ostream& out, print_func_ptr_t print_f)
614 int ind = first_bucket();
616 while ( ind != -1 ) {
618 imp_bucket* bucket = get_bucket(ind);
621 bucket -> asciiOut(out, print_f);