source: trunk/gsdl/packages/mg/lib/perf_hash.c@ 10853

Last change on this file since 10853 was 2046, checked in by jrm21, 23 years ago

Fixed bug that caused perf_hash to fail for lexicon of < 4 words.
Added a #define to increase size of n (for vertices in the graph) as we
need to allocate more memory somewhere else before calling tree_builder()

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