source: main/trunk/greenstone2/common-src/indexers/mg/lib/perf_hash.c@ 37351

Last change on this file since 37351 was 37351, checked in by davidb, 14 months ago

More careful definition of function externs. Macs now treat an implicit declaration of a function as an error, not a warning, and so the mg source code needs to be tightened up on its include headers

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