LAL  7.5.0.1-ec27e42
LALHashTblTest.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016 Karl Wette
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with with program; see the file COPYING. If not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17  * MA 02110-1301 USA
18  */
19 
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <gsl/gsl_rng.h>
23 #include <gsl/gsl_randist.h>
24 #include <gsl/gsl_permutation.h>
25 #include <lal/LALHashTbl.h>
26 
27 typedef struct {
28  int key;
29  int value;
30 } elem;
31 
32 static void *new_elem( int key, int value )
33 {
34  elem e = { .key = key, .value = value };
35  return memcpy( XLALMalloc( sizeof( e ) ), &e, sizeof( e ) );
36 }
37 
38 static UINT8 hash_elem( const void *x )
39 {
40  const elem *ex = ( const elem * ) x;
41  UINT2 hval = 0;
42  XLALPearsonHash( &hval, sizeof( hval ), &ex->key, sizeof( ex->key ) );
43  return hval;
44 }
45 
46 static int cmp_elem( const void *x, const void *y )
47 {
48  const elem *ex = ( const elem * ) x;
49  const elem *ey = ( const elem * ) y;
50  return ex->key - ey->key;
51 }
52 
53 int main( void )
54 {
55 
56  /* Create hash table */
57  LALHashTbl *ht = XLALHashTblCreate( XLALFree, hash_elem, cmp_elem );
58  XLAL_CHECK_MAIN( ht != NULL, XLAL_EFUNC );
60 
61  /* Repeat hash table test a few times */
62  gsl_rng *r = gsl_rng_alloc( gsl_rng_mt19937 );
63  int clear_tested = 0;
64  for ( int n = 0; n < 4; ++n ) {
65 
66  /* Add 100 elements with keys in 100*n + [0,99] to table in a random order */
67  {
68  XLAL_CHECK_MAIN( r != NULL, XLAL_ESYS );
69  gsl_permutation *p = gsl_permutation_calloc( 100 );
70  XLAL_CHECK_MAIN( p != NULL, XLAL_ESYS );
71  gsl_ran_shuffle( r, p->data, 100, sizeof( size_t ) );
72  for ( int i = 0; i < 100; ++i ) {
73  int key = 100*n + gsl_permutation_get( p, i );
74  XLAL_CHECK_MAIN( XLALHashTblAdd( ht, new_elem( key, 3*key - n ) ) == XLAL_SUCCESS, XLAL_EFUNC );
75  XLAL_CHECK_MAIN( XLALHashTblSize( ht ) == 100*n + i + 1, XLAL_EFAILED );
76  }
77  gsl_permutation_free( p );
78  }
79 
80  /* Try finding all 100 elements by key */
81  for ( int i = 0; i < 100; ++i ) {
82  elem x = { .key = 100*n + i };
83  const elem *y;
84  XLAL_CHECK_MAIN( XLALHashTblFind( ht, &x, ( const void ** ) &y ) == XLAL_SUCCESS, XLAL_EFUNC );
85  XLAL_CHECK_MAIN( y != NULL, XLAL_EFAILED );
86  XLAL_CHECK_MAIN( y->value == 3*y->key - n, XLAL_EFAILED );
87  }
88 
89  /* Try extracting all 100 elements, then adding them back */
90  for ( int i = 0; i < 100; ++i ) {
91  elem x = { .key = 100*n + i };
92  elem *y;
93  XLAL_CHECK_MAIN( XLALHashTblExtract( ht, &x, ( void ** ) &y ) == XLAL_SUCCESS, XLAL_EFUNC );
94  XLAL_CHECK_MAIN( y != NULL, XLAL_EFAILED );
95  XLAL_CHECK_MAIN( y->value == 3*y->key - n, XLAL_EFAILED );
96  const elem *z;
97  XLAL_CHECK_MAIN( XLALHashTblFind( ht, &x, ( const void ** ) &z ) == XLAL_SUCCESS, XLAL_EFUNC );
98  XLAL_CHECK_MAIN( z == NULL, XLAL_EFAILED );
100  XLAL_CHECK_MAIN( XLALHashTblFind( ht, &x, ( const void ** ) &z ) == XLAL_SUCCESS, XLAL_EFUNC );
101  XLAL_CHECK_MAIN( z != NULL, XLAL_EFAILED );
102  XLAL_CHECK_MAIN( z->value == 3*z->key - n, XLAL_EFAILED );
103  }
104 
105  /* Try clearing hash table */
106  if ( !clear_tested && n == 0 ) {
108  clear_tested = 1;
109  n = -1;
110  }
111 
112  }
114 
115  /* Try removing some elements */
116  for ( int i = 0; i < 250; ++i ) {
117  elem x = { .key = i };
119  XLAL_CHECK_MAIN( XLALHashTblSize( ht ) == 400 - i - 1, XLAL_EFAILED );
120  }
121 
122  /* Try finding the rest of the elements */
123  for ( int i = 250; i < 400; ++i ) {
124  elem x = { .key = i };
125  const elem *y;
126  XLAL_CHECK_MAIN( XLALHashTblFind( ht, &x, ( const void ** ) &y ) == XLAL_SUCCESS, XLAL_EFUNC );
127  XLAL_CHECK_MAIN( y != NULL, XLAL_EFAILED );
128  XLAL_CHECK_MAIN( y->value == 3*y->key - ( i / 100 ), XLAL_EFAILED );
129  }
130 
131  /* Cleanup */
132  gsl_rng_free( r );
133  XLALHashTblDestroy( ht );
134 
135  /* Check for memory leaks */
137 
138  return EXIT_SUCCESS;
139 
140 }
static void * new_elem(int key, int value)
int main(void)
static UINT8 hash_elem(const void *x)
static int cmp_elem(const void *x, const void *y)
void LALCheckMemoryLeaks(void)
Definition: LALMalloc.c:784
uint64_t UINT8
Eight-byte unsigned integer; on some platforms this is equivalent to unsigned long int instead.
uint16_t UINT2
Two-byte unsigned integer.
int XLALPearsonHash(void *hval, const size_t hval_len, const void *data, const size_t data_len)
Compute a arbitrary-sized Pearson hash value for the given arbitrary data.
int XLALHashTblFind(const LALHashTbl *ht, const void *x, const void **y)
Find the element matching x in a hash table; if found, return in *y
Definition: LALHashTbl.c:185
LALHashTbl * XLALHashTblCreate(LALHashTblDtorFcn dtor, LALHashTblHashFcn hash, LALHashTblCmpFcn cmp)
Create a hash table.
Definition: LALHashTbl.c:86
int XLALHashTblSize(const LALHashTbl *ht)
Return the size of a hash table.
Definition: LALHashTbl.c:177
int XLALHashTblAdd(LALHashTbl *ht, void *x)
Add an element to a hash table.
Definition: LALHashTbl.c:215
int XLALHashTblExtract(LALHashTbl *ht, const void *x, void **y)
Find the element matching x in a hash table; if found, remove it and return in *y
Definition: LALHashTbl.c:252
int XLALHashTblRemove(LALHashTbl *ht, const void *x)
Find the element matching x in a hash table; if found, remove and destroy it.
Definition: LALHashTbl.c:287
void XLALHashTblDestroy(LALHashTbl *ht)
Destroy a hash table and its elements.
Definition: LALHashTbl.c:129
int XLALHashTblClear(LALHashTbl *ht)
Clear a hash table.
Definition: LALHashTbl.c:148
#define XLALMalloc(n)
Definition: LALMalloc.h:44
#define XLALFree(p)
Definition: LALMalloc.h:47
static const INT4 r
Definition: Random.c:82
#define XLAL_CHECK_MAIN(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a C main() routine.
Definition: XLALError.h:885
@ XLAL_SUCCESS
Success return value (not an error number)
Definition: XLALError.h:401
@ XLAL_EFUNC
Internal function call failed bit: "or" this with existing error number.
Definition: XLALError.h:462
@ XLAL_ESYS
System error.
Definition: XLALError.h:442
@ XLAL_EFAILED
Generic failure.
Definition: XLALError.h:418
Definition: LALBitset.c:31
int value
UINT8 key
Definition: LALBitset.c:32
int key