source: trunk/gsdl3/packages/mg/lib/perf_hash.c@ 3745

Last change on this file since 3745 was 3745, checked in by mdewsnip, 21 years ago

Addition of MG package for search and retrieval

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 24.3 KB
Line 
1/**************************************************************************
2 *
3 * perf_hash.c -- Perfect hashing functions
4 * Copyright (C) 1992 Bohdan S. Majewski
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id: perf_hash.c 3745 2003-02-20 21:20:24Z mdewsnip $
21 *
22 **************************************************************************
23 *
24 * 1994 Neil Sharman
25 * Small modifications were made to the interface so that it fitted in
26 * with mg.
27 *
28 **************************************************************************/
29
30/*
31 $Log$
32 Revision 1.1 2003/02/20 21:14:16 mdewsnip
33 Addition of MG package for search and retrieval
34
35 Revision 1.2 2001/02/22 01:35:03 jrm21
36 Fixed bug that caused perf_hash to fail for lexicon of < 4 words.
37 Added a #define to increase size of n (for vertices in the graph) as we
38 need to allocate more memory somewhere else before calling tree_builder()
39
40 Revision 1.1 1999/08/10 21:16:57 sjboddie
41 renamed mg-1.3d directory mg
42
43 Revision 1.1 1998/11/17 09:32:17 rjmcnab
44 *** empty log message ***
45
46 * Revision 1.2 1994/08/22 00:26:30 tes
47 * Made perf_hash take the ceiling of 1.23 * num
48 * in lieu of the floor.
49 * This was done so that perf_hash works ok on
50 * a small number of keys.
51 *
52 * Revision 1.1 1994/08/22 00:24:49 tes
53 * Initial placement under CVS.
54 *
55 */
56
57static char *RCSID = "$Id: perf_hash.c 3745 2003-02-20 21:20:24Z mdewsnip $";
58
59
60#define STRUCT
61
62#include "sysfuncs.h"
63
64#include "local_strings.h"
65#include "memlib.h"
66#include "messages.h"
67#include "perf_hash.h"
68#include "netorder.h" /* [RPAP - Jan 97: Endian Ordering] */
69
70#define FALSE 0
71#define TRUE 1
72
73#define STATIC 0
74
75/* Random Number stuff */
76static long seed[] = {0, 0};
77#define RANDOM() irandm(seed)
78#define SEED_RANDOM(the_seed) do{ seed[0] = the_seed; }while(0)
79
80/* Max number of keys - must be a power of 2 minus 1 */
81static int MAX_M;
82
83
84static int MAX_CH;
85
86
87/* the width of the mapping tables */
88static int MAX_L;
89
90
91
92#define c 1.23
93static int MAX_N;
94
95/* An arbitrary amount to add to both MAX_N and n for building tree/acyclic
96 graph -- John McPherson - jrm21 (22-02-2001) */
97#define MAX_N_HEADROOM 100
98
99
100static u_char *translate;
101
102#define MEMBER 0
103#define ERASED 1
104
105
106
107/* direction constants for the edge oriented 3-graph representation */
108#define A 0
109#define B (MAX_M)
110#define C (2*B)
111
112/* NODEa, NODEb, NODEc, FIRST and NEXT are used to represent a 3-graph */
113static int *NODEa, *NODEb, *NODEc;
114static int *FIRST;
115static int *NEXT;
116
117
118#define norm(e) ((e) % MAX_M)
119/* in general should be ((e) % MAX_M) but MAX_M = 2^k - 1 */
120
121
122static char *mk; /* for marking edges/vertices as removed */
123static int *g; /* array g defines a minimal perfect hash function */
124
125
126
127/* stack of edges, created during the independency */
128/* test, used in the assignment step */
129static struct
130 {
131 int sp;
132 int *st;
133 }
134S;
135#define push(s, e) s.st[s.sp++] = (e)
136#define pop(s, e) e = s.st[--s.sp]
137
138#ifndef STRUCT
139static long **tb0, **tb1, **tb2;
140#else
141struct tb_entry **tb;
142#endif
143
144
145static int
146unique (int v)
147{ /* checks if vertex v belongs to only one edge */
148 return (FIRST[v] != 0 && NEXT[FIRST[v]] == 0) ? FIRST[v] : 0;
149} /*unique */
150
151
152
153
154
155
156
157
158static void
159delete (int v, int e)
160{ /* deletes edge e from list of v */
161
162 int b;
163
164 b = FIRST[v];
165 assert (norm (b) != 0);
166 if (norm (b) == e)
167 FIRST[v] = NEXT[FIRST[v]];
168 else
169 {
170 while (norm (NEXT[b]) != e)
171 {
172 b = NEXT[b];
173 assert (norm (b) != 0);
174 }
175 NEXT[b] = NEXT[NEXT[b]];
176 }
177} /*delete */
178
179
180
181
182
183
184#if 0
185/* recursively removes the edges of a 3-graph which have at least */
186/* one unique vertex. The removed edges are placed on stack S */
187static void
188ph_remove (int e, int v)
189{
190 int b;
191 mk[e] = ERASED;
192 push (S, e);
193
194 if (NODEa[e] != v)
195 delete (NODEa[e], e);
196 if (NODEb[e] != v)
197 delete (NODEb[e], e);
198 if (NODEc[e] != v)
199 delete (NODEc[e], e);
200
201 if (NODEa[e] != v && mk[b = norm (unique (NODEa[e]))] == MEMBER)
202 ph_remove (b, NODEa[e]);
203 if (NODEb[e] != v && mk[b = norm (unique (NODEb[e]))] == MEMBER)
204 ph_remove (b, NODEb[e]);
205 if (NODEc[e] != v && mk[b = norm (unique (NODEc[e]))] == MEMBER)
206 ph_remove (b, NODEc[e]);
207}
208#else
209
210
211static int StackPos, StackMax;
212static struct Stack
213 {
214 int e, v, m;
215 }
216 *Stack = NULL;
217
218#define StackAdd(_e, _v, _m) \
219 do { \
220 if (StackPos == StackMax) \
221 { \
222 StackMax <<= 1; \
223 if (!(Stack = Xrealloc(Stack, sizeof(*Stack) * StackMax))) \
224 return(-1); \
225 } \
226 Stack[StackPos].e = (_e); \
227 Stack[StackPos].v = (_v); \
228 Stack[StackPos++].m = (_m); \
229 } while(0)
230
231
232static int
233ph_remove (int e, int v)
234{
235 if (!Stack)
236 {
237 StackMax = 256;
238 if (!(Stack = Xmalloc (sizeof (*Stack) * StackMax)))
239 return (-1);
240 StackPos = 0;
241 }
242 Stack[StackPos].e = e;
243 Stack[StackPos].v = v;
244 Stack[StackPos].m = 0;
245 StackPos++;
246 while (StackPos)
247 {
248 int m, b;
249 StackPos--;
250 e = Stack[StackPos].e;
251 v = Stack[StackPos].v;
252 m = Stack[StackPos].m;
253
254
255 switch (m)
256 {
257 case 0:
258 {
259 mk[e] = ERASED;
260 push (S, e);
261
262 if (NODEa[e] != v)
263 delete (NODEa[e], e);
264 if (NODEb[e] != v)
265 delete (NODEb[e], e);
266 if (NODEc[e] != v)
267 delete (NODEc[e], e);
268
269 if (NODEa[e] != v && mk[b = norm (unique (NODEa[e]))] == MEMBER)
270 {
271 Stack[StackPos++].m = 1;
272 StackAdd (b, NODEa[e], 0);
273 break;
274 }
275 }
276 case 1:
277 {
278 if (NODEb[e] != v && mk[b = norm (unique (NODEb[e]))] == MEMBER)
279 {
280 Stack[StackPos++].m = 2;
281 StackAdd (b, NODEb[e], 0);
282 break;
283 }
284 }
285 case 2:
286 if (NODEc[e] != v && mk[b = norm (unique (NODEc[e]))] == MEMBER)
287 StackAdd (b, NODEc[e], 0);
288 }
289 }
290 return (0);
291}
292#endif
293
294
295
296
297
298/* returns TRUE if and only if set of edges created in the tree_builder */
299/* procedure form a 3-graph with independent edges. Edges of a 3-graph */
300/* are independent iff repeated deletion of edges containing vertices */
301/* of degree 1 results in a graph with no edges in it. */
302static int
303acyclic (int m, int n)
304{
305
306 int v, e;
307 /* build list of edges for each node */
308 for (v = 1; v <= n; FIRST[v++] = 0);
309 for (e = 1; e <= m; e++)
310 {
311 NEXT[A + e] = FIRST[NODEa[e]];
312 FIRST[NODEa[e]] = A + e;
313 NEXT[B + e] = FIRST[NODEb[e]];
314 FIRST[NODEb[e]] = B + e;
315 NEXT[C + e] = FIRST[NODEc[e]];
316 FIRST[NODEc[e]] = C + e;
317
318 /* mark edge e as belonging to the hypergraph */
319 mk[e] = MEMBER;
320 }
321
322
323 S.sp = 0; /* empty the stack */
324 mk[0] = ERASED; /* a sentinel for the test below */
325 for (v = 1; v <= n; v++)
326 {
327 if (mk[e = norm (unique (v))] == MEMBER)
328 ph_remove (e, v);
329 }
330
331 /* check if any edges were left in the graph */
332 return S.sp == m;
333} /*acyclic */
334
335
336
337
338
339
340
341
342/* repeatedly maps words into edges of a 3-graph until the edges */
343/* are independent. */
344static int
345tree_builder (int num, u_char ** keys, int *n)
346{
347
348 int e, k = 0;
349 int i, j;
350 u_char *w;
351
352 do
353 {
354 /* Added variable - need to increase MAX_N on allocate as well */
355 *n = (int) (num * c + MAX_N_HEADROOM); /* john mcpherson 22-02-2001 */
356
357 /* initialize tables of random integers */
358 for (i = 0; i < MAX_CH; i++)
359 for (j = 0; j < MAX_L; j++)
360 {
361#ifndef STRUCT
362 tb0[i][j] = RANDOM () % *n;
363 tb1[i][j] = RANDOM () % *n;
364 tb2[i][j] = RANDOM () % *n;
365#else
366 struct tb_entry *tbp = &tb[i][j];
367 tbp->tb0 = RANDOM () % *n;
368 tbp->tb1 = RANDOM () % *n;
369 tbp->tb2 = RANDOM () % *n;
370#endif
371 }
372
373 /* compute an edge (NODEa[e], NODEb[e], NODEc[e]) for each word */
374 for (e = 1; e <= num; e++)
375 {
376 /*generate an edge corresponding to the ith word */
377 int x = 0, y = 0, z = 0, l;
378 w = keys[e - 1];
379
380 l = *w++;
381 j = (l - 1) % MAX_L;
382
383 do
384 {
385#ifndef STRUCT
386 x += tb0[translate[*w]][j];
387 y += tb1[translate[*w]][j];
388 z += tb2[translate[*w]][j];
389#else
390 struct tb_entry *tbp = &tb[translate[*w]][j];
391 x += tbp->tb0;
392 y += tbp->tb1;
393 z += tbp->tb2;
394#endif
395 if (++j >= MAX_L)
396 j = 0;
397 w++;
398 }
399 while (--l);
400 x = (x % *n) + 1;
401 y = (y % *n) + 1;
402 z = (z % *n) + 1;
403 if (y == x && ++y > *n)
404 y = 1;
405 if (z == x && ++z > *n)
406 z = 1;
407 if (z == y)
408 {
409 if (++z > *n)
410 z = 1;
411 if (z == x && ++z > *n)
412 z = 1;
413 }
414
415 NODEa[e] = x;
416 NODEb[e] = y;
417 NODEc[e] = z;
418 }
419 if (++k > 50) /* make sure we will not wait for ever */
420 FatalError (1, "Unable to generate the perfect hash function. "
421 "This is probably because there aren't enough words");
422 }
423 while (!acyclic (num, *n));
424 return k;
425} /*tree_builder */
426
427
428
429
430
431
432
433
434
435/* calculates values of the g function/array so that i-th word is */
436/* placed at the (i-1)st position of a hash table. */
437static void
438assign (int n)
439{
440
441 int v, w = 0, e;
442
443 /* mark all the vertices of the 3-graph as unassigned */
444 for (v = 1; v <= n; mk[v++] = FALSE);
445
446 while (S.sp > 0)
447 {
448 int xor = 0;
449 pop (S, e);
450 v = NODEa[e];
451 if (mk[v])
452 xor ^= g[v];
453 else
454 {
455 g[w = v] = 0;
456 mk[v] = TRUE;
457 }
458 v = NODEb[e];
459 if (mk[v])
460 xor ^= g[v];
461 else
462 {
463 g[w = v] = 0;
464 mk[v] = TRUE;
465 }
466 v = NODEc[e];
467 if (mk[v])
468 xor ^= g[v];
469 else
470 {
471 g[w = v] = 0;
472 mk[v] = TRUE;
473 }
474 g[w] = (e - 1) ^ xor;
475 }
476} /*assign */
477
478
479
480
481
482
483
484
485
486/*check returns 0 if no error in mphf is detected, else returns error code */
487static int
488check (int m)
489{
490
491 int e, err_code = 0;
492
493 /*for each word compute its place in hash table and check if correct */
494 for (e = 1; e <= m; e++)
495 {
496 if ((e - 1) != (g[NODEa[e]] ^ g[NODEb[e]] ^ g[NODEc[e]]))
497 {
498 (void) fprintf (stderr, "Error for %dth word detected.\n", e);
499 err_code = e;
500 }
501 }
502 return err_code;
503} /*check */
504
505
506
507
508
509
510
511#if 0
512void
513outputh (int m, int n)
514{
515
516 int i, j, w = (int) ceil (log10 ((double) n + 1.0)) + 1;
517
518#if 0
519 char *PRG =
520 "int h(char *s)\n"
521 "{\n"
522 " int u, v, w, i;\n"
523 "i = (strlen(s) - 1) % _HXL;\n"
524 " u = v = w = 0;\n"
525 " while(*s)\n"
526 " {\n"
527 " u += mt1[(*s) - _HFC][i];\n"
528 " v += mt2[(*s) - _HFC][i];\n"
529 " w += mt3[(*s++) - _HFC][i];\n"
530 " if(++i >= _HXL) i = 0;\n"
531 " }\n"
532 " u %= _HFN; v %= _HFN; w %= _HFN;\n"
533 " if(u == v && ++v >= _HFN) v = 0;\n"
534 " if(w == u && ++w >= _HFN) w = 0;\n"
535 " if(w == v && ++w >= _HFN) w = 0;\n"
536 " if(w == u && ++w >= _HFN) w = 0;\n"
537 " return (g[u] ^ g[v] ^ g[w]) % _HFM;\n"
538 "};\n\n";
539#endif
540
541 char *PRG =
542 "int h(char *s)\n"
543 "{\n"
544 " int u, v, w, i;\n"
545 " i = (strlen(s) - 1) % _HXL;\n"
546 " u = v = w = 0;\n"
547 " while(*s)\n"
548 " {\n"
549 " if((u += mt1[(*s) - _HFC][i]) >= _HFN) u -= _HFN;\n"
550 " if((v += mt2[(*s) - _HFC][i]) >= _HFN) v -= _HFN;\n"
551 " if((w += mt3[(*s++) - _HFC][i]) >= _HFN) w -= _HFN;\n"
552 " if(++i >= _HXL) i = 0;\n"
553 " }\n"
554 " if(u == v && ++v >= _HFN) v = 0;\n"
555 " if(w == v) \n"
556 " {\n"
557 " if(++w >= _HFN) w = 0;\n"
558 " if(w == u && ++w >= _HFN) w = 0;\n"
559 " }\n"
560 " else\n"
561 " if(w == u)\n"
562 " {\n"
563 " if(++w >= _HFN) w = 0;\n"
564 " if(w == v && ++w >= _HFN) w = 0;\n"
565 " }\n"
566 " return ((g[u] ^ g[v] ^ g[w]) > _HFM)? 0 : (g[u] ^ g[v] ^ g[w]);\n"
567 "}\n\n";
568
569 printf ("#define _HFN %d\n#define _HFC %d\n", n, fc);
570 printf ("#define _HFM %d\n#define _HXL %d\n", m, MAX_L);
571 printf ("#define _HFA %d\n\nstatic int g[_HFN] = {\n", lc - fc + 1);
572 for (i = 1; i < n; i++)
573 {
574 if (i % 8 == 0)
575 putchar ('\n');
576 printf ("%5d, ", g[i]);
577 }
578 printf ("%5d};\n\n", g[n]);
579
580 printf ("static int mt1[_HFA][_HXL] = {\n");
581 for (j = fc; j < lc; j++)
582 {
583 printf ("{");
584 for (i = 0; i < MAX_L - 1; i++)
585 printf ("%*d,", w, tb0[j][i]);
586 printf ("%*d},\n", w, tb0[j][MAX_L - 1]);
587 }
588 printf ("{");
589 for (i = 0; i < MAX_L - 1; i++)
590 printf ("%*d,", w, tb0[lc][i]);
591 printf ("%*d}\n", w, tb0[lc][MAX_L - 1]);
592 printf ("};\n\n");
593
594 printf ("static int mt2[_HFA][_HXL] = {\n");
595 for (j = fc; j < lc; j++)
596 {
597 printf ("{");
598 for (i = 0; i < MAX_L - 1; i++)
599 printf ("%*d,", w, tb1[j][i]);
600 printf ("%*d},\n", w, tb1[j][MAX_L - 1]);
601 }
602 printf ("{");
603 for (i = 0; i < MAX_L - 1; i++)
604 printf ("%*d,", w, tb1[lc][i]);
605 printf ("%*d}\n", w, tb1[lc][MAX_L - 1]);
606 printf ("};\n\n");
607
608 printf ("static int mt3[_HFA][_HXL] = {\n");
609 for (j = fc; j < lc; j++)
610 {
611 printf ("{");
612 for (i = 0; i < MAX_L - 1; i++)
613 printf ("%*d,", w, tb2[j][i]);
614 printf ("%*d},\n", w, tb2[j][MAX_L - 1]);
615 }
616 printf ("{");
617 for (i = 0; i < MAX_L - 1; i++)
618 printf ("%*d,", w, tb2[lc][i]);
619 printf ("%*d}\n", w, tb2[lc][MAX_L - 1]);
620 printf ("};\n\n");
621
622 printf ("%s", PRG);
623} /*outputh */
624#endif
625
626
627
628
629
630
631
632static void
633make_trans_func (int num, u_char ** keys)
634{
635 int i, j;
636
637 bzero ((char *) translate, sizeof (translate));
638
639 MAX_L = 1;
640 for (i = 0; i < num; i++)
641 {
642 unsigned len = keys[i][0];
643 u_char *s = keys[i] + 1;
644 for (; len; len--, s++)
645 translate[*s] = 1;
646 if (i)
647 {
648 int l;
649 l = prefixlen (keys[i - 1], keys[i]);
650 if (l + 1 > MAX_L)
651 MAX_L = l + 1;
652 }
653 }
654 j = 0;
655 for (i = 0; i < 256; i++)
656 if (translate[i])
657 translate[i] = j++;
658 MAX_CH = j;
659}
660
661
662static void
663temp_free (void)
664{
665 if (NODEa)
666 Xfree (NODEa);
667 if (NODEb)
668 Xfree (NODEb);
669 if (NODEc)
670 Xfree (NODEc);
671 if (FIRST)
672 Xfree (FIRST);
673 if (NEXT)
674 Xfree (NEXT);
675 if (S.st)
676 Xfree (S.st);
677 if (mk)
678 Xfree (mk);
679}
680
681static void
682all_free (void)
683{
684 int i;
685 temp_free ();
686 if (translate)
687 Xfree (translate);
688 if (g)
689 Xfree (g);
690#ifndef STRUCT
691 for (i = 0; i < MAX_CH; i++)
692 {
693 if (tb0 && tb0[i])
694 Xfree (tb0[i]);
695 if (tb1 && tb1[i])
696 Xfree (tb1[i]);
697 if (tb2 && tb2[i])
698 Xfree (tb2[i]);
699 }
700 if (tb0)
701 Xfree (tb0);
702 if (tb1)
703 Xfree (tb1);
704 if (tb2)
705 Xfree (tb2);
706#else
707 for (i = 0; i < MAX_CH; i++)
708 if (tb && tb[i])
709 Xfree (tb[i]);
710 if (tb)
711 Xfree (tb);
712#endif
713}
714
715static int
716allocate_memory (void)
717{
718 int i, ok = 1;
719 NODEa = Xmalloc (sizeof (int) * (MAX_M + 1));
720 NODEb = Xmalloc (sizeof (int) * (MAX_M + 1));
721 NODEc = Xmalloc (sizeof (int) * (MAX_M + 1));
722 FIRST = Xmalloc (sizeof (int) * (MAX_N + 1));
723 NEXT = Xmalloc (sizeof (int) * (MAX_M + 1) * 3);
724 S.st = Xmalloc (sizeof (int) * MAX_M);
725 mk = Xmalloc (sizeof (char) * (MAX_N + 1));
726 g = Xmalloc (sizeof (int) * (MAX_N + 1));
727#ifndef STRUCT
728 tb0 = Xmalloc (sizeof (int *) * MAX_CH);
729 tb1 = Xmalloc (sizeof (int *) * MAX_CH);
730 tb2 = Xmalloc (sizeof (int *) * MAX_CH);
731 for (i = 0; i < MAX_CH; i++)
732 {
733 if (tb0)
734 if (!(tb0[i] = Xmalloc (sizeof (long) * MAX_L)))
735 ok = 0;
736 if (tb1)
737 if (!(tb1[i] = Xmalloc (sizeof (long) * MAX_L)))
738 ok = 0;
739 if (tb2)
740 if (!(tb2[i] = Xmalloc (sizeof (long) * MAX_L)))
741 ok = 0;
742 }
743
744 if (!(NODEa && NODEb && NODEc && FIRST && NEXT && S.st && mk && g &&
745 tb0 && tb1 && tb2 && ok))
746 {
747 all_free ();
748 return (-1);
749 }
750#else
751 tb = Xmalloc (sizeof (struct tb_entry *) * MAX_CH);
752 for (i = 0; i < MAX_CH; i++)
753 if (tb)
754 if (!(tb[i] = Xmalloc (sizeof (struct tb_entry) * MAX_L)))
755 ok = 0;
756
757 if (!(NODEa && NODEb && NODEc && FIRST && NEXT && S.st && mk && g &&
758 tb && ok))
759 {
760 all_free ();
761 return (-1);
762 }
763#endif
764 return (0);
765}
766
767
768perf_hash_data *
769gen_hash_func (int num, u_char ** keys, int r)
770{
771 int n;
772 perf_hash_data *phd;
773 translate = Xmalloc (sizeof (u_char) * 256);
774 bzero ((char *) translate, sizeof (u_char) * 256); /* [RPAP - Feb 97: WIN32 Port] */
775 make_trans_func (num, keys);
776
777 if (r <= 0)
778 SEED_RANDOM ((long) time ((time_t *) NULL));
779 else
780 SEED_RANDOM (r);
781
782 MAX_M = num + 1;
783
784 /* For extremely small lexicons (<4 words), this isn't good enough!
785 -- John McPherson jrm21 22-02-2001 */
786 /* MAX_N = MAX_M + MAX_M / 4; */
787 MAX_N = (int)(ceil (1.25 * MAX_M));
788 /* Add some space for "experimentation" of n in tree_builder() */
789 MAX_N += MAX_N_HEADROOM;
790
791 if (allocate_memory () == -1)
792 return (NULL);
793
794 /* construct an "acyclic" hypergraph */
795 tree_builder (num, keys, &n);
796 /* compute function g */
797 assign (n);
798
799 if (check (num) != 0)
800 FatalError (1, "An error has been detected in the mphf.");
801 temp_free ();
802
803 if (!(phd = Xmalloc (sizeof (perf_hash_data))))
804 return (NULL);
805
806 bcopy ((char *) &g[1], (char *) g, n * sizeof (int));
807
808 phd->MAX_L = MAX_L;
809 phd->MAX_N = n;
810 phd->MAX_M = num;
811 phd->MAX_CH = MAX_CH;
812 phd->translate = translate;
813 phd->g = g;
814#ifndef STRUCT
815 phd->tb0 = tb0;
816 phd->tb1 = tb1;
817 phd->tb2 = tb2;
818#else
819 phd->tb = tb;
820#endif
821 return (phd);
822}
823
824int
825write_perf_hash_data (FILE * f, perf_hash_data * phd)
826{
827 int tot, i;
828 /* [RPAP - Jan 97: Endian Ordering] */
829 HTONSI(phd->MAX_L);
830 HTONSI(phd->MAX_N);
831 HTONSI(phd->MAX_M);
832 HTONSI(phd->MAX_CH);
833
834 tot = fwrite ((char *) &phd->MAX_L, sizeof (int), 1, f) * sizeof (int);
835 tot += fwrite ((char *) &phd->MAX_N, sizeof (int), 1, f) * sizeof (int);
836 tot += fwrite ((char *) &phd->MAX_M, sizeof (int), 1, f) * sizeof (int);
837 tot += fwrite ((char *) &phd->MAX_CH, sizeof (int), 1, f) * sizeof (int);
838
839 /* [RPAP - Jan 97: Endian Ordering] */
840 NTOHSI(phd->MAX_L);
841 NTOHSI(phd->MAX_N);
842 NTOHSI(phd->MAX_M);
843 NTOHSI(phd->MAX_CH);
844
845 tot += fwrite ((char *) phd->translate, sizeof (u_char), 256, f);
846
847 /* [RPAP - Jan 97: Endian Ordering] */
848 for (i = 0; i < phd->MAX_N + 1; i++)
849 HTONSI(phd->g[i]);
850
851 tot += fwrite ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
852
853 /* [RPAP - Jan 97: Endian Ordering] */
854 for (i = 0; i < phd->MAX_N + 1; i++)
855 NTOHSI(phd->g[i]);
856
857#ifndef STRUCT
858 for (i = 0; i < phd->MAX_CH; i++)
859 {
860 /* [RPAP - Jan 97: Endian Ordering] */
861 int j;
862 for (j = 0; j < phd->MAX_L; j++)
863 {
864 HTONSI(phd->tb0[i][j]);
865 HTONSI(phd->tb1[i][j]);
866 HTONSI(phd->tb2[i][j]);
867 }
868
869 tot += fwrite ((char *) phd->tb0[i], sizeof (int), phd->MAX_L, f) *
870 sizeof (int);
871 tot += fwrite ((char *) phd->tb1[i], sizeof (int), phd->MAX_L, f) *
872 sizeof (int);
873 tot += fwrite ((char *) phd->tb2[i], sizeof (int), phd->MAX_L, f) *
874 sizeof (int);
875
876 /* [RPAP - Jan 97: Endian Ordering] */
877 for (j = 0; j < phd->MAX_L; j++)
878 {
879 NTOHSI(phd->tb0[i][j]);
880 NTOHSI(phd->tb1[i][j]);
881 NTOHSI(phd->tb2[i][j]);
882 }
883 }
884#else
885 for (i = 0; i < phd->MAX_CH; i++)
886 {
887 /* [RPAP - Jan 97: Endian Ordering] */
888 int j;
889 for (j = 0; j < phd->MAX_L; j++)
890 {
891 HTONSL(phd->tb[i][j].tb0);
892 HTONSL(phd->tb[i][j].tb1);
893 HTONSL(phd->tb[i][j].tb2);
894 }
895
896 tot += fwrite ((char *) phd->tb[i], sizeof (struct tb_entry), phd->MAX_L, f) *
897 sizeof (struct tb_entry);
898
899 /* [RPAP - Jan 97: Endian Ordering] */
900 for (j = 0; j < phd->MAX_L; j++)
901 {
902 NTOHSL(phd->tb[i][j].tb0);
903 NTOHSL(phd->tb[i][j].tb1);
904 NTOHSL(phd->tb[i][j].tb2);
905 }
906 }
907#endif
908 return (tot);
909}
910
911
912perf_hash_data *
913read_perf_hash_data (FILE * f)
914{
915 perf_hash_data *phd;
916 int i, tot, ok = 1;
917 if (!(phd = Xmalloc (sizeof (perf_hash_data))))
918 return (NULL);
919 tot = fread ((char *) &phd->MAX_L, sizeof (int), 1, f) * sizeof (int);
920 tot += fread ((char *) &phd->MAX_N, sizeof (int), 1, f) * sizeof (int);
921 tot += fread ((char *) &phd->MAX_M, sizeof (int), 1, f) * sizeof (int);
922 tot += fread ((char *) &phd->MAX_CH, sizeof (int), 1, f) * sizeof (int);
923
924 /* [RPAP - Jan 97: Endian Ordering] */
925 NTOHSI(phd->MAX_L);
926 NTOHSI(phd->MAX_N);
927 NTOHSI(phd->MAX_M);
928 NTOHSI(phd->MAX_CH);
929
930 if (tot != 4 * sizeof (int))
931 return (NULL);
932 phd->translate = Xmalloc (sizeof (u_char) * 256);
933 phd->g = Xmalloc (sizeof (int) * (phd->MAX_N + 1));
934#ifndef STRUCT
935 phd->tb0 = Xmalloc (sizeof (int *) * phd->MAX_CH);
936 phd->tb1 = Xmalloc (sizeof (int *) * phd->MAX_CH);
937 phd->tb2 = Xmalloc (sizeof (int *) * phd->MAX_CH);
938 for (i = 0; i < phd->MAX_CH; i++)
939 {
940 if (phd->tb0)
941 if (!(phd->tb0[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
942 ok = 0;
943 if (phd->tb1)
944 if (!(phd->tb1[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
945 ok = 0;
946 if (phd->tb2)
947 if (!(phd->tb2[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
948 ok = 0;
949 }
950 if (!(phd->translate && phd->g && phd->tb0 && phd->tb1 && phd->tb2 && ok))
951 {
952 if (phd->translate)
953 Xfree (phd->translate);
954 if (phd->g)
955 Xfree (phd->g);
956 for (i = 0; i < MAX_CH; i++)
957 {
958 if (phd->tb0 && phd->tb0[i])
959 Xfree (phd->tb0[i]);
960 if (phd->tb1 && phd->tb1[i])
961 Xfree (phd->tb1[i]);
962 if (phd->tb2 && phd->tb2[i])
963 Xfree (phd->tb2[i]);
964 }
965 if (phd->tb0)
966 Xfree (phd->tb0);
967 if (phd->tb1)
968 Xfree (phd->tb1);
969 if (phd->tb2)
970 Xfree (phd->tb2);
971 Xfree (phd);
972 return (NULL);
973 }
974 tot += fread ((char *) phd->translate, sizeof (u_char), 256, f);
975 tot += fread ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
976
977 /* [RPAP - Jan 97: Endian Ordering] */
978 for (i = 0; i < phd->MAX_N + 1; i++)
979 NTOHSI(phd->g[i]);
980
981 for (i = 0; i < phd->MAX_CH; i++)
982 {
983 int j;
984
985 tot += fread ((char *) phd->tb0[i], sizeof (long), phd->MAX_L, f) *
986 sizeof (int);
987 tot += fread ((char *) phd->tb1[i], sizeof (long), phd->MAX_L, f) *
988 sizeof (int);
989 tot += fread ((char *) phd->tb2[i], sizeof (long), phd->MAX_L, f) *
990 sizeof (int);
991
992 /* [RPAP - Jan 97: Endian Ordering] */
993 for (j = 0; j < phd->MAX_L; j++)
994 {
995 NTOHSI(phd->tb0[i][j]);
996 NTOHSI(phd->tb1[i][j]);
997 NTOHSI(phd->tb2[i][j]);
998 }
999 }
1000#else
1001 phd->tb = Xmalloc (sizeof (struct tb_entry *) * phd->MAX_CH);
1002 for (i = 0; i < phd->MAX_CH; i++)
1003 if (phd->tb)
1004 if (!(phd->tb[i] = Xmalloc (sizeof (struct tb_entry) * phd->MAX_L)))
1005 ok = 0;
1006 if (!(phd->translate && phd->g && phd->tb && ok))
1007 {
1008 if (phd->translate)
1009 Xfree (phd->translate);
1010 if (phd->g)
1011 Xfree (phd->g);
1012 for (i = 0; i < MAX_CH; i++)
1013 if (phd->tb && phd->tb[i])
1014 Xfree (phd->tb[i]);
1015 if (phd->tb)
1016 Xfree (phd->tb);
1017 Xfree (phd);
1018 return (NULL);
1019 }
1020 tot += fread ((char *) phd->translate, sizeof (u_char), 256, f);
1021 tot += fread ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
1022
1023 /* [RPAP - Jan 97: Endian Ordering] */
1024 for (i = 0; i < phd->MAX_N + 1; i++)
1025 NTOHSI(phd->g[i]);
1026
1027 for (i = 0; i < phd->MAX_CH; i++)
1028 {
1029 int j;
1030
1031 tot += fread ((char *) phd->tb[i], sizeof (struct tb_entry), phd->MAX_L, f) *
1032 sizeof (struct tb_entry);
1033
1034 /* [RPAP - Jan 97: Endian Ordering] */
1035 for (j = 0; j < phd->MAX_L; j++)
1036 {
1037 NTOHSL(phd->tb[i][j].tb0);
1038 NTOHSL(phd->tb[i][j].tb1);
1039 NTOHSL(phd->tb[i][j].tb2);
1040 }
1041 }
1042#endif
1043 return (phd);
1044}
1045
1046void
1047free_perf_hash (perf_hash_data * phd)
1048{
1049 int i;
1050 if (phd->translate)
1051 Xfree (phd->translate);
1052 if (phd->g)
1053 Xfree (phd->g);
1054 for (i = 0; i < phd->MAX_CH; i++)
1055 if (phd->tb && phd->tb[i])
1056 Xfree (phd->tb[i]);
1057 if (phd->tb)
1058 Xfree (phd->tb);
1059 Xfree (phd);
1060}
1061
1062
1063int
1064perf_hash (perf_hash_data * phd, u_char * s)
1065{
1066 int u, v, w, i, l;
1067 l = *s++;
1068 i = (l - 1) % phd->MAX_L;
1069 u = v = w = 0;
1070 while (l)
1071 {
1072#ifndef STRUCT
1073 if ((u += phd->tb0[phd->translate[*s]][i]) >= phd->MAX_N)
1074 u -= phd->MAX_N;
1075 if ((v += phd->tb1[phd->translate[*s]][i]) >= phd->MAX_N)
1076 v -= phd->MAX_N;
1077 if ((w += phd->tb2[phd->translate[*s]][i]) >= phd->MAX_N)
1078 w -= phd->MAX_N;
1079#else
1080 struct tb_entry *tbp = &phd->tb[phd->translate[*s]][i];
1081 if ((u += tbp->tb0) >= phd->MAX_N)
1082 u -= phd->MAX_N;
1083 if ((v += tbp->tb1) >= phd->MAX_N)
1084 v -= phd->MAX_N;
1085 if ((w += tbp->tb2) >= phd->MAX_N)
1086 w -= phd->MAX_N;
1087#endif
1088 if (++i >= phd->MAX_L)
1089 i = 0;
1090 l--;
1091 s++;
1092 }
1093 if (u == v && ++v >= phd->MAX_N)
1094 v = 0;
1095 if (w == v)
1096 {
1097 if (++w >= phd->MAX_N)
1098 w = 0;
1099 if (w == u && ++w >= phd->MAX_N)
1100 w = 0;
1101 }
1102 else if (w == u)
1103 {
1104 if (++w >= phd->MAX_N)
1105 w = 0;
1106 if (w == v && ++w >= phd->MAX_N)
1107 w = 0;
1108 }
1109 return ((phd->g[u] ^ phd->g[v] ^ phd->g[w]) > phd->MAX_M) ? 0 :
1110 (phd->g[u] ^ phd->g[v] ^ phd->g[w]);
1111}
Note: See TracBrowser for help on using the repository browser.