source: trunk/gsdl/src/mgpp/lib/perf_hash.cpp@ 2377

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

replaced bcopy with memcpy

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 23.8 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.cpp 2377 2001-05-07 05:01:47Z 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/05/07 04:59:59 jrm21
33 replaced bcopy with memcpy
34
35 Revision 1.1 2000/01/14 02:17:13 sjboddie
36 Rodgers new C++ mg
37
38 Revision 1.1 1998/11/17 09:32:17 rjmcnab
39 *** empty log message ***
40
41 * Revision 1.2 1994/08/22 00:26:30 tes
42 * Made perf_hash take the ceiling of 1.23 * num
43 * in lieu of the floor.
44 * This was done so that perf_hash works ok on
45 * a small number of keys.
46 *
47 * Revision 1.1 1994/08/22 00:24:49 tes
48 * Initial placement under CVS.
49 *
50 */
51
52static char *RCSID = "$Id: perf_hash.cpp 2377 2001-05-07 05:01:47Z jrm21 $";
53
54
55#define STRUCT
56
57#include <time.h> /* for call to time () in SEED_RANDOM() */
58#include "sysfuncs.h"
59
60#include "local_strings.h"
61#include "memlib.h"
62#include "messages.h"
63#include "perf_hash.h"
64#include "netorder.h" /* [RPAP - Jan 97: Endian Ordering] */
65
66#define FALSE 0
67#define TRUE 1
68
69#define STATIC 0
70
71/* Random Number stuff */
72
73long irandm (long is[2]); /* from random.c */
74
75static long seed[] = {0, 0};
76#define RANDOM() irandm(seed)
77#define SEED_RANDOM(the_seed) do{ seed[0] = the_seed; }while(0)
78
79/* Max number of keys - must be a power of 2 minus 1 */
80static int MAX_M;
81
82
83static int MAX_CH;
84
85
86/* the width of the mapping tables */
87static int MAX_L;
88
89
90
91#define c 1.23
92static int MAX_N;
93
94
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
156_delete (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 = (struct 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 = (struct 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 *n = (int) (num * c + 1);
352 /* initialize tables of random integers */
353 for (i = 0; i < MAX_CH; i++)
354 for (j = 0; j < MAX_L; j++)
355 {
356#ifndef STRUCT
357 tb0[i][j] = RANDOM () % *n;
358 tb1[i][j] = RANDOM () % *n;
359 tb2[i][j] = RANDOM () % *n;
360#else
361 struct tb_entry *tbp = &tb[i][j];
362 tbp->tb0 = RANDOM () % *n;
363 tbp->tb1 = RANDOM () % *n;
364 tbp->tb2 = RANDOM () % *n;
365#endif
366 }
367
368 /* compute an edge (NODEa[e], NODEb[e], NODEc[e]) for each word */
369 for (e = 1; e <= num; e++)
370 {
371 /*generate an edge corresponding to the ith word */
372 int x = 0, y = 0, z = 0, l;
373 w = keys[e - 1];
374
375 l = *w++;
376 j = (l - 1) % MAX_L;
377
378 do
379 {
380#ifndef STRUCT
381 x += tb0[translate[*w]][j];
382 y += tb1[translate[*w]][j];
383 z += tb2[translate[*w]][j];
384#else
385 struct tb_entry *tbp = &tb[translate[*w]][j];
386 x += tbp->tb0;
387 y += tbp->tb1;
388 z += tbp->tb2;
389#endif
390 if (++j >= MAX_L)
391 j = 0;
392 w++;
393 }
394 while (--l);
395 x = (x % *n) + 1;
396 y = (y % *n) + 1;
397 z = (z % *n) + 1;
398 if (y == x && ++y > *n)
399 y = 1;
400 if (z == x && ++z > *n)
401 z = 1;
402 if (z == y)
403 {
404 if (++z > *n)
405 z = 1;
406 if (z == x && ++z > *n)
407 z = 1;
408 }
409
410 NODEa[e] = x;
411 NODEb[e] = y;
412 NODEc[e] = z;
413 }
414 if (++k > 50) /* make sure we will not wait for ever */
415 FatalError (1, "Unable to generate the perfect hash function. "
416 "This is probably because there aren't enough words");
417 }
418 while (!acyclic (num, *n));
419 return k;
420} /*tree_builder */
421
422
423
424
425
426
427
428
429
430/* calculates values of the g function/array so that i-th word is */
431/* placed at the (i-1)st position of a hash table. */
432static void
433assign (int n)
434{
435
436 int v, w = 0, e;
437
438 /* mark all the vertices of the 3-graph as unassigned */
439 for (v = 1; v <= n; mk[v++] = FALSE);
440
441 while (S.sp > 0)
442 {
443 int _xor = 0;
444 pop (S, e);
445 v = NODEa[e];
446 if (mk[v])
447 _xor ^= g[v];
448 else
449 {
450 g[w = v] = 0;
451 mk[v] = TRUE;
452 }
453 v = NODEb[e];
454 if (mk[v])
455 _xor ^= g[v];
456 else
457 {
458 g[w = v] = 0;
459 mk[v] = TRUE;
460 }
461 v = NODEc[e];
462 if (mk[v])
463 _xor ^= g[v];
464 else
465 {
466 g[w = v] = 0;
467 mk[v] = TRUE;
468 }
469 g[w] = (e - 1) ^ _xor;
470 }
471} /*assign */
472
473
474
475
476
477
478
479
480
481/*check returns 0 if no error in mphf is detected, else returns error code */
482static int
483check (int m)
484{
485
486 int e, err_code = 0;
487
488 /*for each word compute its place in hash table and check if correct */
489 for (e = 1; e <= m; e++)
490 {
491 if ((e - 1) != (g[NODEa[e]] ^ g[NODEb[e]] ^ g[NODEc[e]]))
492 {
493 (void) fprintf (stderr, "Error for %dth word detected.\n", e);
494 err_code = e;
495 }
496 }
497 return err_code;
498} /*check */
499
500
501
502
503
504
505
506#if 0
507void
508outputh (int m, int n)
509{
510
511 int i, j, w = (int) ceil (log10 ((double) n + 1.0)) + 1;
512
513#if 0
514 char *PRG =
515 "int h(char *s)\n"
516 "{\n"
517 " int u, v, w, i;\n"
518 "i = (strlen(s) - 1) % _HXL;\n"
519 " u = v = w = 0;\n"
520 " while(*s)\n"
521 " {\n"
522 " u += mt1[(*s) - _HFC][i];\n"
523 " v += mt2[(*s) - _HFC][i];\n"
524 " w += mt3[(*s++) - _HFC][i];\n"
525 " if(++i >= _HXL) i = 0;\n"
526 " }\n"
527 " u %= _HFN; v %= _HFN; w %= _HFN;\n"
528 " if(u == v && ++v >= _HFN) v = 0;\n"
529 " if(w == u && ++w >= _HFN) w = 0;\n"
530 " if(w == v && ++w >= _HFN) w = 0;\n"
531 " if(w == u && ++w >= _HFN) w = 0;\n"
532 " return (g[u] ^ g[v] ^ g[w]) % _HFM;\n"
533 "};\n\n";
534#endif
535
536 char *PRG =
537 "int h(char *s)\n"
538 "{\n"
539 " int u, v, w, i;\n"
540 " i = (strlen(s) - 1) % _HXL;\n"
541 " u = v = w = 0;\n"
542 " while(*s)\n"
543 " {\n"
544 " if((u += mt1[(*s) - _HFC][i]) >= _HFN) u -= _HFN;\n"
545 " if((v += mt2[(*s) - _HFC][i]) >= _HFN) v -= _HFN;\n"
546 " if((w += mt3[(*s++) - _HFC][i]) >= _HFN) w -= _HFN;\n"
547 " if(++i >= _HXL) i = 0;\n"
548 " }\n"
549 " if(u == v && ++v >= _HFN) v = 0;\n"
550 " if(w == v) \n"
551 " {\n"
552 " if(++w >= _HFN) w = 0;\n"
553 " if(w == u && ++w >= _HFN) w = 0;\n"
554 " }\n"
555 " else\n"
556 " if(w == u)\n"
557 " {\n"
558 " if(++w >= _HFN) w = 0;\n"
559 " if(w == v && ++w >= _HFN) w = 0;\n"
560 " }\n"
561 " return ((g[u] ^ g[v] ^ g[w]) > _HFM)? 0 : (g[u] ^ g[v] ^ g[w]);\n"
562 "}\n\n";
563
564 printf ("#define _HFN %d\n#define _HFC %d\n", n, fc);
565 printf ("#define _HFM %d\n#define _HXL %d\n", m, MAX_L);
566 printf ("#define _HFA %d\n\nstatic int g[_HFN] = {\n", lc - fc + 1);
567 for (i = 1; i < n; i++)
568 {
569 if (i % 8 == 0)
570 putchar ('\n');
571 printf ("%5d, ", g[i]);
572 }
573 printf ("%5d};\n\n", g[n]);
574
575 printf ("static int mt1[_HFA][_HXL] = {\n");
576 for (j = fc; j < lc; j++)
577 {
578 printf ("{");
579 for (i = 0; i < MAX_L - 1; i++)
580 printf ("%*d,", w, tb0[j][i]);
581 printf ("%*d},\n", w, tb0[j][MAX_L - 1]);
582 }
583 printf ("{");
584 for (i = 0; i < MAX_L - 1; i++)
585 printf ("%*d,", w, tb0[lc][i]);
586 printf ("%*d}\n", w, tb0[lc][MAX_L - 1]);
587 printf ("};\n\n");
588
589 printf ("static int mt2[_HFA][_HXL] = {\n");
590 for (j = fc; j < lc; j++)
591 {
592 printf ("{");
593 for (i = 0; i < MAX_L - 1; i++)
594 printf ("%*d,", w, tb1[j][i]);
595 printf ("%*d},\n", w, tb1[j][MAX_L - 1]);
596 }
597 printf ("{");
598 for (i = 0; i < MAX_L - 1; i++)
599 printf ("%*d,", w, tb1[lc][i]);
600 printf ("%*d}\n", w, tb1[lc][MAX_L - 1]);
601 printf ("};\n\n");
602
603 printf ("static int mt3[_HFA][_HXL] = {\n");
604 for (j = fc; j < lc; j++)
605 {
606 printf ("{");
607 for (i = 0; i < MAX_L - 1; i++)
608 printf ("%*d,", w, tb2[j][i]);
609 printf ("%*d},\n", w, tb2[j][MAX_L - 1]);
610 }
611 printf ("{");
612 for (i = 0; i < MAX_L - 1; i++)
613 printf ("%*d,", w, tb2[lc][i]);
614 printf ("%*d}\n", w, tb2[lc][MAX_L - 1]);
615 printf ("};\n\n");
616
617 printf ("%s", PRG);
618} /*outputh */
619#endif
620
621
622
623
624
625
626
627static void
628make_trans_func (int num, u_char ** keys)
629{
630 int i, j;
631
632 bzero ((char *) translate, sizeof (translate));
633
634 MAX_L = 1;
635 for (i = 0; i < num; i++)
636 {
637 unsigned len = keys[i][0];
638 u_char *s = keys[i] + 1;
639 for (; len; len--, s++)
640 translate[*s] = 1;
641 if (i)
642 {
643 int l;
644 l = prefixlen (keys[i - 1], keys[i]);
645 if (l + 1 > MAX_L)
646 MAX_L = l + 1;
647 }
648 }
649 j = 0;
650 for (i = 0; i < 256; i++)
651 if (translate[i])
652 translate[i] = j++;
653 MAX_CH = j;
654}
655
656
657static void
658temp_free (void)
659{
660 if (NODEa)
661 Xfree (NODEa);
662 if (NODEb)
663 Xfree (NODEb);
664 if (NODEc)
665 Xfree (NODEc);
666 if (FIRST)
667 Xfree (FIRST);
668 if (NEXT)
669 Xfree (NEXT);
670 if (S.st)
671 Xfree (S.st);
672 if (mk)
673 Xfree (mk);
674}
675
676static void
677all_free (void)
678{
679 int i;
680 temp_free ();
681 if (translate)
682 Xfree (translate);
683 if (g)
684 Xfree (g);
685#ifndef STRUCT
686 for (i = 0; i < MAX_CH; i++)
687 {
688 if (tb0 && tb0[i])
689 Xfree (tb0[i]);
690 if (tb1 && tb1[i])
691 Xfree (tb1[i]);
692 if (tb2 && tb2[i])
693 Xfree (tb2[i]);
694 }
695 if (tb0)
696 Xfree (tb0);
697 if (tb1)
698 Xfree (tb1);
699 if (tb2)
700 Xfree (tb2);
701#else
702 for (i = 0; i < MAX_CH; i++)
703 if (tb && tb[i])
704 Xfree (tb[i]);
705 if (tb)
706 Xfree (tb);
707#endif
708}
709
710static int
711allocate_memory (void)
712{
713 int i, ok = 1;
714 NODEa = (int *) Xmalloc (sizeof (int) * (MAX_M + 1));
715 NODEb = (int *)Xmalloc (sizeof (int) * (MAX_M + 1));
716 NODEc = (int *)Xmalloc (sizeof (int) * (MAX_M + 1));
717 FIRST = (int *)Xmalloc (sizeof (int) * (MAX_N + 1));
718 NEXT = (int *)Xmalloc (sizeof (int) * (MAX_M + 1) * 3);
719 S.st = (int *)Xmalloc (sizeof (int) * MAX_M);
720 mk = (char *)Xmalloc (sizeof (char) * (MAX_N + 1));
721 g = (int *)Xmalloc (sizeof (int) * (MAX_N + 1));
722#ifndef STRUCT
723 tb0 = Xmalloc (sizeof (int *) * MAX_CH);
724 tb1 = Xmalloc (sizeof (int *) * MAX_CH);
725 tb2 = Xmalloc (sizeof (int *) * MAX_CH);
726 for (i = 0; i < MAX_CH; i++)
727 {
728 if (tb0)
729 if (!(tb0[i] = Xmalloc (sizeof (long) * MAX_L)))
730 ok = 0;
731 if (tb1)
732 if (!(tb1[i] = Xmalloc (sizeof (long) * MAX_L)))
733 ok = 0;
734 if (tb2)
735 if (!(tb2[i] = Xmalloc (sizeof (long) * MAX_L)))
736 ok = 0;
737 }
738
739 if (!(NODEa && NODEb && NODEc && FIRST && NEXT && S.st && mk && g &&
740 tb0 && tb1 && tb2 && ok))
741 {
742 all_free ();
743 return (-1);
744 }
745#else
746 tb = (tb_entry **)Xmalloc (sizeof (struct tb_entry *) * MAX_CH);
747 for (i = 0; i < MAX_CH; i++)
748 if (tb)
749 if (!(tb[i] = (tb_entry *)Xmalloc (sizeof (struct tb_entry) * MAX_L)))
750 ok = 0;
751
752 if (!(NODEa && NODEb && NODEc && FIRST && NEXT && S.st && mk && g &&
753 tb && ok))
754 {
755 all_free ();
756 return (-1);
757 }
758#endif
759 return (0);
760}
761
762
763perf_hash_data *
764gen_hash_func (int num, u_char ** keys, int r)
765{
766 int n;
767 perf_hash_data *phd;
768 translate = (u_char *)Xmalloc (sizeof (u_char) * 256);
769 bzero ((char *) translate, sizeof (u_char) * 256); /* [RPAP - Feb 97: WIN32 Port] */
770 make_trans_func (num, keys);
771
772 if (r <= 0)
773 SEED_RANDOM ((long) time ((time_t *) NULL));
774 else
775 SEED_RANDOM (r);
776
777 MAX_M = num + 1;
778
779 MAX_N = MAX_M + MAX_M / 4;
780
781 if (allocate_memory () == -1)
782 return (NULL);
783
784 /* construct an "acyclic" hypergraph */
785 tree_builder (num, keys, &n);
786 /* compute function g */
787 assign (n);
788
789 if (check (num) != 0)
790 FatalError (1, "An error has been detected in the mphf.");
791 temp_free ();
792
793 if (!(phd = (perf_hash_data *)Xmalloc (sizeof (perf_hash_data))))
794 return (NULL);
795
796 memcpy ((void *) g, (const void *) &g[1], n * sizeof (int));
797
798 phd->MAX_L = MAX_L;
799 phd->MAX_N = n;
800 phd->MAX_M = num;
801 phd->MAX_CH = MAX_CH;
802 phd->translate = translate;
803 phd->g = g;
804#ifndef STRUCT
805 phd->tb0 = tb0;
806 phd->tb1 = tb1;
807 phd->tb2 = tb2;
808#else
809 phd->tb = tb;
810#endif
811 return (phd);
812}
813
814int
815write_perf_hash_data (FILE * f, perf_hash_data * phd)
816{
817 int tot, i;
818 /* [RPAP - Jan 97: Endian Ordering] */
819 HTONSI(phd->MAX_L);
820 HTONSI(phd->MAX_N);
821 HTONSI(phd->MAX_M);
822 HTONSI(phd->MAX_CH);
823
824 tot = fwrite ((char *) &phd->MAX_L, sizeof (int), 1, f) * sizeof (int);
825 tot += fwrite ((char *) &phd->MAX_N, sizeof (int), 1, f) * sizeof (int);
826 tot += fwrite ((char *) &phd->MAX_M, sizeof (int), 1, f) * sizeof (int);
827 tot += fwrite ((char *) &phd->MAX_CH, sizeof (int), 1, f) * sizeof (int);
828
829 /* [RPAP - Jan 97: Endian Ordering] */
830 NTOHSI(phd->MAX_L);
831 NTOHSI(phd->MAX_N);
832 NTOHSI(phd->MAX_M);
833 NTOHSI(phd->MAX_CH);
834
835 tot += fwrite ((char *) phd->translate, sizeof (u_char), 256, f);
836
837 /* [RPAP - Jan 97: Endian Ordering] */
838 for (i = 0; i < phd->MAX_N + 1; i++)
839 HTONSI(phd->g[i]);
840
841 tot += fwrite ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
842
843 /* [RPAP - Jan 97: Endian Ordering] */
844 for (i = 0; i < phd->MAX_N + 1; i++)
845 NTOHSI(phd->g[i]);
846
847#ifndef STRUCT
848 for (i = 0; i < phd->MAX_CH; i++)
849 {
850 /* [RPAP - Jan 97: Endian Ordering] */
851 int j;
852 for (j = 0; j < phd->MAX_L; j++)
853 {
854 HTONSI(phd->tb0[i][j]);
855 HTONSI(phd->tb1[i][j]);
856 HTONSI(phd->tb2[i][j]);
857 }
858
859 tot += fwrite ((char *) phd->tb0[i], sizeof (int), phd->MAX_L, f) *
860 sizeof (int);
861 tot += fwrite ((char *) phd->tb1[i], sizeof (int), phd->MAX_L, f) *
862 sizeof (int);
863 tot += fwrite ((char *) phd->tb2[i], sizeof (int), phd->MAX_L, f) *
864 sizeof (int);
865
866 /* [RPAP - Jan 97: Endian Ordering] */
867 for (j = 0; j < phd->MAX_L; j++)
868 {
869 NTOHSI(phd->tb0[i][j]);
870 NTOHSI(phd->tb1[i][j]);
871 NTOHSI(phd->tb2[i][j]);
872 }
873 }
874#else
875 for (i = 0; i < phd->MAX_CH; i++)
876 {
877 /* [RPAP - Jan 97: Endian Ordering] */
878 int j;
879 for (j = 0; j < phd->MAX_L; j++)
880 {
881 HTONSL(phd->tb[i][j].tb0);
882 HTONSL(phd->tb[i][j].tb1);
883 HTONSL(phd->tb[i][j].tb2);
884 }
885
886 tot += fwrite ((char *) phd->tb[i], sizeof (struct tb_entry), phd->MAX_L, f) *
887 sizeof (struct tb_entry);
888
889 /* [RPAP - Jan 97: Endian Ordering] */
890 for (j = 0; j < phd->MAX_L; j++)
891 {
892 NTOHSL(phd->tb[i][j].tb0);
893 NTOHSL(phd->tb[i][j].tb1);
894 NTOHSL(phd->tb[i][j].tb2);
895 }
896 }
897#endif
898 return (tot);
899}
900
901
902perf_hash_data *
903read_perf_hash_data (FILE * f)
904{
905 perf_hash_data *phd;
906 int i, tot, ok = 1;
907 if (!(phd = (perf_hash_data *)Xmalloc (sizeof (perf_hash_data))))
908 return (NULL);
909 tot = fread ((char *) &phd->MAX_L, sizeof (int), 1, f) * sizeof (int);
910 tot += fread ((char *) &phd->MAX_N, sizeof (int), 1, f) * sizeof (int);
911 tot += fread ((char *) &phd->MAX_M, sizeof (int), 1, f) * sizeof (int);
912 tot += fread ((char *) &phd->MAX_CH, sizeof (int), 1, f) * sizeof (int);
913
914 /* [RPAP - Jan 97: Endian Ordering] */
915 NTOHSI(phd->MAX_L);
916 NTOHSI(phd->MAX_N);
917 NTOHSI(phd->MAX_M);
918 NTOHSI(phd->MAX_CH);
919
920 if (tot != 4 * sizeof (int))
921 return (NULL);
922 phd->translate = (u_char *)Xmalloc (sizeof (u_char) * 256);
923 phd->g = (int *)Xmalloc (sizeof (int) * (phd->MAX_N + 1));
924#ifndef STRUCT
925 phd->tb0 = Xmalloc (sizeof (int *) * phd->MAX_CH);
926 phd->tb1 = Xmalloc (sizeof (int *) * phd->MAX_CH);
927 phd->tb2 = Xmalloc (sizeof (int *) * phd->MAX_CH);
928 for (i = 0; i < phd->MAX_CH; i++)
929 {
930 if (phd->tb0)
931 if (!(phd->tb0[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
932 ok = 0;
933 if (phd->tb1)
934 if (!(phd->tb1[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
935 ok = 0;
936 if (phd->tb2)
937 if (!(phd->tb2[i] = Xmalloc (sizeof (long) * phd->MAX_L)))
938 ok = 0;
939 }
940 if (!(phd->translate && phd->g && phd->tb0 && phd->tb1 && phd->tb2 && ok))
941 {
942 if (phd->translate)
943 Xfree (phd->translate);
944 if (phd->g)
945 Xfree (phd->g);
946 for (i = 0; i < MAX_CH; i++)
947 {
948 if (phd->tb0 && phd->tb0[i])
949 Xfree (phd->tb0[i]);
950 if (phd->tb1 && phd->tb1[i])
951 Xfree (phd->tb1[i]);
952 if (phd->tb2 && phd->tb2[i])
953 Xfree (phd->tb2[i]);
954 }
955 if (phd->tb0)
956 Xfree (phd->tb0);
957 if (phd->tb1)
958 Xfree (phd->tb1);
959 if (phd->tb2)
960 Xfree (phd->tb2);
961 Xfree (phd);
962 return (NULL);
963 }
964 tot += fread ((char *) phd->translate, sizeof (u_char), 256, f);
965 tot += fread ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
966
967 /* [RPAP - Jan 97: Endian Ordering] */
968 for (i = 0; i < phd->MAX_N + 1; i++)
969 NTOHSI(phd->g[i]);
970
971 for (i = 0; i < phd->MAX_CH; i++)
972 {
973 int j;
974
975 tot += fread ((char *) phd->tb0[i], sizeof (long), phd->MAX_L, f) *
976 sizeof (int);
977 tot += fread ((char *) phd->tb1[i], sizeof (long), phd->MAX_L, f) *
978 sizeof (int);
979 tot += fread ((char *) phd->tb2[i], sizeof (long), phd->MAX_L, f) *
980 sizeof (int);
981
982 /* [RPAP - Jan 97: Endian Ordering] */
983 for (j = 0; j < phd->MAX_L; j++)
984 {
985 NTOHSI(phd->tb0[i][j]);
986 NTOHSI(phd->tb1[i][j]);
987 NTOHSI(phd->tb2[i][j]);
988 }
989 }
990#else
991 phd->tb = (struct tb_entry **)Xmalloc (sizeof (struct tb_entry *) * phd->MAX_CH);
992 for (i = 0; i < phd->MAX_CH; i++)
993 if (phd->tb)
994 if (!(phd->tb[i] = (struct tb_entry *)Xmalloc (sizeof (struct tb_entry) * phd->MAX_L)))
995 ok = 0;
996 if (!(phd->translate && phd->g && phd->tb && ok))
997 {
998 if (phd->translate)
999 Xfree (phd->translate);
1000 if (phd->g)
1001 Xfree (phd->g);
1002 for (i = 0; i < MAX_CH; i++)
1003 if (phd->tb && phd->tb[i])
1004 Xfree (phd->tb[i]);
1005 if (phd->tb)
1006 Xfree (phd->tb);
1007 Xfree (phd);
1008 return (NULL);
1009 }
1010 tot += fread ((char *) phd->translate, sizeof (u_char), 256, f);
1011 tot += fread ((char *) phd->g, sizeof (int), phd->MAX_N + 1, f) * sizeof (int);
1012
1013 /* [RPAP - Jan 97: Endian Ordering] */
1014 for (i = 0; i < phd->MAX_N + 1; i++)
1015 NTOHSI(phd->g[i]);
1016
1017 for (i = 0; i < phd->MAX_CH; i++)
1018 {
1019 int j;
1020
1021 tot += fread ((char *) phd->tb[i], sizeof (struct tb_entry), phd->MAX_L, f) *
1022 sizeof (struct tb_entry);
1023
1024 /* [RPAP - Jan 97: Endian Ordering] */
1025 for (j = 0; j < phd->MAX_L; j++)
1026 {
1027 NTOHSL(phd->tb[i][j].tb0);
1028 NTOHSL(phd->tb[i][j].tb1);
1029 NTOHSL(phd->tb[i][j].tb2);
1030 }
1031 }
1032#endif
1033 return (phd);
1034}
1035
1036void
1037free_perf_hash (perf_hash_data * phd)
1038{
1039 int i;
1040 if (phd->translate)
1041 Xfree (phd->translate);
1042 if (phd->g)
1043 Xfree (phd->g);
1044 for (i = 0; i < phd->MAX_CH; i++)
1045 if (phd->tb && phd->tb[i])
1046 Xfree (phd->tb[i]);
1047 if (phd->tb)
1048 Xfree (phd->tb);
1049 Xfree (phd);
1050}
1051
1052
1053int
1054perf_hash (perf_hash_data * phd, u_char * s)
1055{
1056 int u, v, w, i, l;
1057 l = *s++;
1058 i = (l - 1) % phd->MAX_L;
1059 u = v = w = 0;
1060 while (l)
1061 {
1062#ifndef STRUCT
1063 if ((u += phd->tb0[phd->translate[*s]][i]) >= phd->MAX_N)
1064 u -= phd->MAX_N;
1065 if ((v += phd->tb1[phd->translate[*s]][i]) >= phd->MAX_N)
1066 v -= phd->MAX_N;
1067 if ((w += phd->tb2[phd->translate[*s]][i]) >= phd->MAX_N)
1068 w -= phd->MAX_N;
1069#else
1070 struct tb_entry *tbp = &phd->tb[phd->translate[*s]][i];
1071 if ((u += tbp->tb0) >= phd->MAX_N)
1072 u -= phd->MAX_N;
1073 if ((v += tbp->tb1) >= phd->MAX_N)
1074 v -= phd->MAX_N;
1075 if ((w += tbp->tb2) >= phd->MAX_N)
1076 w -= phd->MAX_N;
1077#endif
1078 if (++i >= phd->MAX_L)
1079 i = 0;
1080 l--;
1081 s++;
1082 }
1083 if (u == v && ++v >= phd->MAX_N)
1084 v = 0;
1085 if (w == v)
1086 {
1087 if (++w >= phd->MAX_N)
1088 w = 0;
1089 if (w == u && ++w >= phd->MAX_N)
1090 w = 0;
1091 }
1092 else if (w == u)
1093 {
1094 if (++w >= phd->MAX_N)
1095 w = 0;
1096 if (w == v && ++w >= phd->MAX_N)
1097 w = 0;
1098 }
1099 return ((phd->g[u] ^ phd->g[v] ^ phd->g[w]) > phd->MAX_M) ? 0 :
1100 (phd->g[u] ^ phd->g[v] ^ phd->g[w]);
1101}
Note: See TracBrowser for help on using the repository browser.