Annotation of embedaddon/strongswan/src/libstrongswan/plugins/bliss/bliss_huffman.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2014 Tobias Brunner
3: * Copyright (C) 2014 Andreas Steffen
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: #include "bliss_param_set.h"
18:
19: #include <library.h>
20:
21: #include <stdio.h>
22: #include <math.h>
23:
24: typedef struct tuple_t tuple_t;
25:
26: struct tuple_t {
27: int8_t z1;
28: int8_t z2;
29: uint16_t index;
30: uint16_t bits;
31: uint32_t code;
32: };
33:
34: typedef struct node_t node_t;
35:
36: struct node_t {
37: node_t *next;
38: node_t *l;
39: node_t *r;
40: tuple_t *tuple;
41: double p;
42: uint16_t depth;
43: uint16_t index;
44: };
45:
46: static void print_node(node_t *node)
47: {
48: if (node->tuple)
49: {
50: fprintf(stderr, "(%1d,%2d)", node->tuple->z1, node->tuple->z2);
51: }
52: else
53: {
54: fprintf(stderr, " ");
55: }
56: fprintf(stderr, " %18.16f\n", node->p);
57: }
58:
59: static double code_node(node_t *node, int *index, uint8_t bits, uint32_t code)
60: {
61: double code_length = 0;
62:
63: node->index = (*index)++;
64:
65: if (node->tuple)
66: {
67: node->tuple->code = code;
68: node->tuple->bits = bits;
69: code_length += node->p * bits;
70: }
71: if (node->l)
72: {
73: code_length += code_node(node->l, index, bits + 1, (code << 1));
74: }
75: if (node->r)
76: {
77: code_length += code_node(node->r, index, bits + 1, (code << 1) + 1);
78: }
79:
80: return code_length;
81:
82: }
83:
84: static void write_node(node_t *node)
85: {
86: int16_t node_0, node_1, tuple;
87:
88: node_0 = node->l ? node->l->index : BLISS_HUFFMAN_CODE_NO_NODE;
89: node_1 = node->r ? node->r->index : BLISS_HUFFMAN_CODE_NO_NODE;
90: tuple = node->tuple ? node->tuple->index : BLISS_HUFFMAN_CODE_NO_TUPLE;
91:
92: printf("\t{ %3d, %3d, %3d }, /* %3d: ", node_0, node_1, tuple, node->index);
93:
94: if (node->tuple)
95: {
96: printf("(%d,%2d) %2u bit%s ", node->tuple->z1, node->tuple->z2,
97: node->tuple->bits, (node->tuple->bits == 1) ? " " : "s");
98: }
99: printf("*/\n");
100:
101: if (node->l)
102: {
103: write_node(node->l);
104: }
105: if (node->r)
106: {
107: write_node(node->r);
108: }
109: }
110:
111: static void write_header(void)
112: {
113: printf("/*\n");
114: printf(" * Copyright (C) 2014 Andreas Steffen\n");
115: printf(" * HSR Hochschule fuer Technik Rapperswil\n");
116: printf(" *\n");
117: printf(" * Optimum Huffman code for BLISS-X signatures\n");
118: printf(" *\n");
119: printf(" * This file has been automatically generated by the"
120: " bliss_huffman utility\n");
121: printf(" * Do not edit manually!\n");
122: printf(" */\n\n");
123: };
124:
125: static void write_code_tables(int bliss_type, int n_z1, int n_z2, node_t *nodes,
126: tuple_t **tuples)
127: {
128: int index, i, k;
129: uint32_t bit;
130: double code_length;
131:
132: printf("#include \"bliss_huffman_code.h\"\n\n");
133:
134: printf("static bliss_huffman_code_node_t nodes[] = {\n");
135: index = 0;
136: code_length = code_node(nodes, &index, 0, 0);
137: write_node(nodes);
138: printf("};\n\n");
139:
140: printf("static bliss_huffman_code_tuple_t tuples[] = {\n");
141: index = 0;
142: for (i = 0; i < n_z1; i++)
143: {
144: if (i > 0)
145: {
146: printf("\n");
147: }
148: for (k = 1 - n_z2; k < n_z2; k++)
149: {
150: printf("\t{ %5u, %2u }, /* %3d: (%1d,%2d) ",
151: tuples[index]->code, tuples[index]->bits, index, i, k);
152: bit = 1 << (tuples[index]->bits - 1);
153: while (bit)
154: {
155: printf("%s", (tuples[index]->code & bit) ? "1" : "0");
156: bit >>= 1;
157: }
158: printf(" */\n");
159: index++;
160: }
161: }
162: printf("};\n\n");
163: printf("/* code_length = %6.4f bits/tuple (%d bits) */\n\n",
164: code_length, (int)(512 * code_length + 1));
165:
166: printf("bliss_huffman_code_t bliss_huffman_code_%d = {\n", bliss_type);
167: printf("\t.n_z1 = %d,\n", n_z1);
168: printf("\t.n_z2 = %d,\n", n_z2);
169: printf("\t.tuples = tuples,\n");
170: printf("\t.nodes = nodes\n");
171: printf("};\n");
172: }
173:
174: static void destroy_node(node_t *node)
175: {
176: if (node->l)
177: {
178: destroy_node(node->l);
179: }
180: if (node->r)
181: {
182: destroy_node(node->r);
183: }
184: free(node->tuple);
185: free(node);
186: }
187:
188: static void remove_node(node_t *list, node_t **last, node_t *node)
189: {
190: node_t *current, *prev;
191:
192: for (current = list->next, prev = list; current;
193: prev = current, current = current->next)
194: {
195: if (current == node)
196: {
197: prev->next = current->next;
198: if (*last == current)
199: {
200: *last = prev->next ?: prev;
201: }
202: break;
203: }
204: }
205: }
206:
207: /**
208: * Generate a Huffman code for the optimum encoding of BLISS signatures
209: */
210: int main(int argc, char *argv[])
211: {
212: const bliss_param_set_t *set;
213: int dx, bliss_type, depth = 1, groups, groups_left, pairs = 1;
214: int i_max = 9, k_max = 8, index_max = (2*k_max - 1) * i_max;
215: int i, i_top, k, k_top;
216: uint16_t index;
217: double p, p_z1[i_max], p_z2[k_max], x_z1[i_max], x_z2[k_max];
218: double t, x, x0, p_sum, entropy = 0, erf_i, erf_k, erf_0 = 0;
219: tuple_t *tuple, *tuples[index_max];
220: node_t *node, *node_l, *node_r, *nodes = NULL;
221: node_t *node_list, *node_last;
222:
223: if (argc < 2)
224: {
225: fprintf(stderr, "usage: bliss_huffman <bliss type> [<pairs>]\n");
226: exit(1);
227: }
228: if (argc > 2)
229: {
230: pairs = atoi(argv[2]);
231: }
232: fprintf(stderr, "%d code pairs with constant length\n\n", pairs);
233: groups_left = groups = pairs >> 1;
234:
235: bliss_type = atoi(argv[1]);
236: set = bliss_param_set_get_by_id(bliss_type);
237: if (!set)
238: {
239: fprintf(stderr, "bliss type %d unsupported\n", bliss_type);
240: exit(1);
241: }
242: write_header();
243: printf("/*\n");
244: printf(" * Design: sigma = %u\n", set->sigma);
245: printf(" *\n");
246:
247: t = 1/(sqrt(2) * set->sigma);
248:
249: /* Probability distribution for z1 */
250: i_top = (set->B_inf + 255) / 256;
251: p_sum = 0;
252: x = 0;
253:
254: for (i = 0; i < i_top; i++)
255: {
256: x = min(x + 256, set->B_inf);
257: erf_i = erf(t*x);
258: p_z1[i] = erf_i - erf_0;
259: p_sum += p_z1[i];
260: erf_0 = erf_i;
261: x_z1[i] = x;
262: }
263:
264: /* Normalize and print the probability distribution for z1 */
265: printf(" * i p_z1[i]\n");
266: x0 = 0;
267:
268: for (i = 0; i < i_top; i++)
269: {
270: p_z1[i] /= p_sum;
271: printf(" * %2d %18.16f %4.0f .. %4.0f\n", i, p_z1[i], x0, x_z1[i]);
272: x0 = x_z1[i];
273: }
274: printf(" *\n");
275:
276: /* Probability distribution for z2 */
277: dx = 1 << set->d;
278: k_top = 1 + set->B_inf / dx;
279: x = (dx >> 1) - 0.5;
280: p_sum = 0;
281:
282: for (k = 0; k < k_top; k++)
283: {
284:
285: erf_k = erf(t*x) / 2;
286: p_z2[k] = (k == 0) ? 2*erf_k : erf_k - erf_0;
287: p_sum += (k == 0) ? p_z2[k] : 2*p_z2[k];
288: erf_0 = erf_k;
289: x_z2[k] = x;
290: x += dx;
291: }
292:
293: /* Normalize the probability distribution for z2 */
294: for (k = 0; k < k_top; k++)
295: {
296: p_z2[k] /= p_sum;
297: }
298:
299: /* Print the probability distribution for z2 */
300: printf(" * k p_z2[k] dx = %d\n", dx);
301:
302: for (k = 1 - k_top; k < k_top; k++)
303: {
304:
305: printf(" * %2d %18.16f ",k, p_z2[abs(k)]);
306: if (k < 0)
307: {
308: printf(" %7.1f ..%7.1f\n", -x_z2[-k], -x_z2[-k-1]);
309: }
310: else if (k == 0)
311: {
312: printf(" %7.1f ..%7.1f\n", -x_z2[k], x_z2[k]);
313: }
314: else
315: {
316: printf(" %7.1f ..%7.1f\n", x_z2[k-1], x_z2[k]);
317: }
318: }
319: printf(" *\n");
320:
321: /* Compute probabilities of tuples (z1, z2) */
322: INIT(node_list);
323: node_last = node_list;
324: printf(" * (i, k) p\n");
325: p_sum =0;
326: index = 0;
327:
328: for (i = 0; i < i_top; i++)
329: {
330: for (k = 1 - k_top; k < k_top; k++)
331: {
332: p = p_z1[i] * p_z2[abs(k)];
333: printf(" * (%1d,%2d) %18.16f\n", i, k, p);
334: p_sum += p;
335: entropy += -log(p) * p;
336:
337: INIT(tuple,
338: .z1 = i,
339: .z2 = k,
340: .index = index,
341: );
342: tuples[index++] = tuple;
343:
344: INIT(node,
345: .p = p,
346: .tuple = tuple,
347: );
348: node_last->next = node;
349: node_last = node;
350: }
351: printf(" *\n");
352: }
353: entropy /= log(2);
354: printf(" * p_sum %18.16f\n", p_sum);
355: printf(" *\n");
356: printf(" * entropy = %6.4f bits/tuple (%d bits)\n",
357: entropy, (int)(512 * entropy));
358: printf(" */\n\n");
359:
360: /* Build Huffman tree */
361: while (node_list->next != node_last)
362: {
363: node_r = node_l = NULL;
364:
365: for (node = node_list->next; node; node = node->next)
366: {
367: if (pairs > 0)
368: {
369: if (!node->tuple)
370: {
371: continue;
372: }
373: }
374: else if (groups_left > 0)
375: {
376: if (node->tuple || node->depth != depth)
377: {
378: continue;
379: }
380: }
381: if (node_r == NULL || node->p < node_r->p)
382: {
383: node_l = node_r;
384: node_r = node;
385: }
386: else if (node_l == NULL || node->p < node_l->p)
387: {
388: node_l = node;
389: }
390: }
391:
392: INIT(node,
393: .l = node_l,
394: .r = node_r,
395: .p = node_l->p + node_r->p,
396: .depth = 1 + max(node_l->depth, node_r->depth),
397: .tuple = NULL,
398: );
399: print_node(node_r);
400: print_node(node_l);
401: fprintf(stderr, " %18.16f", node->p);
402:
403: remove_node(node_list, &node_last, node_l);
404: remove_node(node_list, &node_last, node_r);
405: node_last->next = node;
406: node_last = node;
407:
408: if (pairs > 0)
409: {
410: pairs--;
411: }
412: else if (groups > 0)
413: {
414: if (--groups_left == 0)
415: {
416: groups >>= 1;
417: groups_left = groups;
418: depth++;
419: }
420: }
421: fprintf(stderr, "\n\n");
422: }
423:
424:
425: nodes = node_list->next;
426:
427: write_code_tables(bliss_type, i_top, k_top, nodes, tuples);
428:
429: destroy_node(nodes);
430: destroy_node(node_list);
431: exit(0);
432: }
433:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>