1 /* PackTab - Pack a static table
2 * Copyright (C) 2001 Behdad Esfahbod.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library, in a file named COPYING; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307, USA
19 * For licensing issues, contact <fwpg@sharif.edu>.
34 typedef signed int uni_table
[1024 * 1024 * 2];
35 static int n
, a
, max_depth
, digits
, tab_width
, per_row
;
38 static uni_table temp
, x
, perm
, *tab
;
39 static long pow
[22], cluster
, cmpcluster
;
40 static const char *const *name
, *key_type_name
, *table_name
, *macro_name
;
49 /* min should be less than max */
55 for (i
= 21; max
< pow
[i
]; i
--)
58 while (i
&& !((min
^ max
) & pow
[i
]))
63 /* min is less than half of max */
64 for (i
= 21 - 1; min
< pow
[i
]; i
--)
70 return max
& (pow
[i
] - 1);
75 const signed int *table
80 /* initialize powers of two */
82 for (i
= 1; i
<= 21; i
++)
83 pow
[i
] = pow
[i
- 1] << 1;
85 /* reduce number of elements to get a more binary number */
89 /* find number of essential items */
91 while (essen
&& table
[essen
] == def_key
)
95 N
= most_binary (essen
, N
);
98 for (n
= 21; N
% pow
[n
]; n
--)
100 digits
= (n
+ 3) / 4;
102 if (pow
[i
] * (tab_width
+ 1) < 80)
114 for (i
= 0; i
< cmpcluster
; i
++)
115 if (((int *) r
)[i
] != ((int *) s
)[i
])
116 return ((int *) r
)[i
] - ((int *) s
)[i
];
120 static int lev
, best_lev
, p
[22], best_p
[22], nn
;
121 static long c
[22], best_c
[22], s
, best_s
;
122 static long t
[22], best_t
[22], clusters
[22], best_cluster
[22];
135 for (i
= 0; i
<= lev
; i
++)
140 best_cluster
[i
] = clusters
[i
];
150 long i
, j
, k
, y
, sbak
;
158 if (lev
== max_depth
)
161 for (i
= 1 - t
[lev
] % 2; i
<= nn
+ (t
[lev
] >> nn
) % 2; i
++)
164 clusters
[lev
] = cluster
= (i
&& nn
>= 0) ? pow
[i
] : t
[lev
];
165 cmpcluster
= cluster
+ 1;
167 t
[lev
+ 1] = (t
[lev
] - 1) / cluster
+ 1;
168 for (j
= 0; j
< t
[lev
+ 1]; j
++)
170 memmove (temp
+ j
* cmpcluster
, tab
[lev
] + j
* cluster
,
171 cluster
* sizeof (tab
[lev
][0]));
172 temp
[j
* cmpcluster
+ cluster
] = j
;
174 qsort (temp
, t
[lev
+ 1], cmpcluster
* sizeof (temp
[0]), compare
);
175 for (j
= 0; j
< t
[lev
+ 1]; j
++)
177 perm
[j
] = temp
[j
* cmpcluster
+ cluster
];
178 temp
[j
* cmpcluster
+ cluster
] = 0;
182 tab
[lev
+ 1][perm
[0]] = perm
[0];
183 for (j
= 1; j
< t
[lev
+ 1]; j
++)
185 if (compare (temp
+ y
, temp
+ y
+ cmpcluster
))
188 tab
[lev
+ 1][perm
[j
]] = perm
[j
];
191 tab
[lev
+ 1][perm
[j
]] = tab
[lev
+ 1][perm
[j
- 1]];
195 s
+= k
* node_size
* cluster
;
205 key_bytes
= k
* cluster
;
206 key_bytes
= key_bytes
< 0xff ? 1 : key_bytes
< 0xffff ? 2 : 4;
221 best_lev
= max_depth
+ 2;
235 int i
, j
, k
, y
, ii
, ofs
;
236 const char *key_type
;
238 if (best_t
[lev
] == 1)
241 nn
-= (i
= best_p
[lev
]);
242 cluster
= best_cluster
[lev
];
243 cmpcluster
= cluster
+ 1;
245 t
[lev
+ 1] = best_t
[lev
+ 1];
246 for (j
= 0; j
< t
[lev
+ 1]; j
++)
248 memmove (temp
+ j
* cmpcluster
, tab
[lev
] + j
* cluster
,
249 cluster
* sizeof (tab
[lev
][0]));
250 temp
[j
* cmpcluster
+ cluster
] = j
;
252 qsort (temp
, t
[lev
+ 1], cmpcluster
* sizeof (temp
[0]), compare
);
253 for (j
= 0; j
< t
[lev
+ 1]; j
++)
255 perm
[j
] = temp
[j
* cmpcluster
+ cluster
];
256 temp
[j
* cmpcluster
+ cluster
] = 0;
260 tab
[lev
+ 1][perm
[0]] = x
[0] = perm
[0];
261 for (j
= 1; j
< t
[lev
+ 1]; j
++)
263 if (compare (temp
+ y
, temp
+ y
+ cmpcluster
))
266 tab
[lev
+ 1][perm
[j
]] = x
[k
];
270 tab
[lev
+ 1][perm
[j
]] = tab
[lev
+ 1][perm
[j
- 1]];
275 for (ii
= 1; ii
< k
; ii
++)
279 key_type
= !lev
? key_type_name
:
280 max_key
<= 0xff ? "PACKTAB_UINT8" :
281 max_key
<= 0xffff ? "PACKTAB_UINT16" : "PACKTAB_UINT32";
282 fprintf (f
, "static const %s %sLev%d[%ld*%d] = {", key_type
, table_name
,
283 best_lev
- lev
- 1, cluster
, k
);
285 for (ii
= 0; ii
< k
; ii
++)
288 fprintf (f
, "\n#define %sLev%d_%0*lX 0x%0X", table_name
,
289 best_lev
- lev
- 1, digits
, x
[i
] * pow
[n
- nn
], ofs
);
293 for (j
= 0; j
< cluster
; j
++)
295 if (!(j
% per_row
) && j
!= cluster
- 1)
297 fprintf (f
, "%*s,", tab_width
, name
[tab
[lev
][kk
++]]);
300 for (j
= 0; j
< cluster
; j
++)
302 if (!(j
% per_row
) && j
!= cluster
- 1)
304 fprintf (f
, "%*d,", tab_width
, tab
[lev
][kk
++]);
307 for (j
= 0; j
< cluster
; j
++, kk
++)
308 fprintf (f
, "\n %sLev%d_%0*lX, /* %0*lX..%0*lX */", table_name
,
309 best_lev
- lev
, digits
,
310 tab
[lev
][kk
] * pow
[n
- nn
- best_p
[lev
]], digits
,
311 x
[i
] * pow
[n
- nn
] + j
* pow
[n
- nn
- best_p
[lev
]], digits
,
312 x
[i
] * pow
[n
- nn
] + (j
+ 1) * pow
[n
- nn
- best_p
[lev
]] -
316 for (j
= 0; j
< k
; j
++)
317 if (x
[j
] > x
[i
] && (x
[j
] < x
[jj
] || jj
== i
))
321 fprintf (f
, "\n};\n\n");
323 write_array (cluster
* k
);
338 fprintf (f
, "\n" "/* *IND" "ENT-OFF* */\n\n");
340 fprintf (f
, "/* *IND" "ENT-ON* */\n\n");
342 fprintf (f
, "#define %s(x) \\\n", macro_name
);
343 fprintf (f
, "\t((x) >= 0x%lx ? ", N
);
345 fprintf (f
, "%s", name
[def_key
]);
347 fprintf (f
, "%d", def_key
);
350 for (i
= best_lev
- 1; i
>= 0; i
--)
352 fprintf (f
, " \\\n\t%sLev%d[((x)", table_name
, i
);
354 fprintf (f
, " >> %d", j
);
356 fprintf (f
, " & 0x%02lx) +", pow
[best_p
[best_lev
- 1 - i
]] - 1);
357 j
+= best_p
[best_lev
- 1 - i
];
360 for (i
= 0; i
< best_lev
; i
++)
362 fprintf (f
, ")\n\n");
372 " generated by packtab.c version %d\n\n"
373 " use %s(key) to access your table\n\n"
374 " assumed sizeof(%s): %d\n"
375 " required memory: %ld\n"
377 " partition shape: %s",
378 packtab_version
, macro_name
, key_type_name
, a
, best_s
, best_lev
,
380 for (i
= best_lev
- 1; i
>= 0; i
--)
381 fprintf (f
, "[%ld]", best_cluster
[i
]);
382 fprintf (f
, "\n" " different table entries:");
383 for (i
= best_lev
- 1; i
>= 0; i
--)
384 fprintf (f
, " %ld", best_c
[i
]);
385 fprintf (f
, "\n*/\n");
391 const signed int *base
,
394 signed int default_key
,
397 const char *const *p_name
,
398 const char *p_key_type_name
,
399 const char *p_table_name
,
400 const char *p_macro_name
,
406 def_key
= default_key
;
407 max_depth
= p_max_depth
;
408 tab_width
= p_tab_width
;
410 key_type_name
= p_key_type_name
;
411 table_name
= p_table_name
;
412 macro_name
= p_macro_name
;
415 if (!(tab
= malloc ((n
+ 1) * sizeof (tab
[0]))))
417 memmove (tab
[0], base
, N
* sizeof (base
[0]));
424 /* End of packtab.c */