Mercurial > MadButterfly
diff tools/gen_precomputed_tabs.py @ 1129:eca737d33a18
Improve performance of function to compute center of an arc.
It is improved by using integer instead of floating point when
computing. Some complicate computations are replaced by pre-computed
table.
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Sat, 18 Dec 2010 15:41:45 +0800 |
parents | |
children | bd0cfb8666b8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/gen_precomputed_tabs.py Sat Dec 18 15:41:45 2010 +0800 @@ -0,0 +1,263 @@ +#!/usr/bin/env python +from math import pi, sin, cos, sqrt + +# #define FRACTION_SHIFT 10 +# +# #define REF_RADIUS_SHIFT 10 +# #define SLOPE_TAB_SZ 128 +# #define ARC_RADIUS_RATIO_TAB_SZ 128 +# #define ARC_RADIUS_FACTOR_TAB_SZ ARC_RADIUS_RATIO_TAB_SZ +# #define SIN_TAB_SZ 256 +# static int slope_tab[SLOPE_TAB_SZ]; +# static int center_shift_tab[SLOPE_TAB_SZ][2]; +# static int vector_len_factor_tab[SLOPE_TAB_SZ]; +# static int arc_radius_ratio_tab[ARC_RADIUS_RATIO_TAB_SZ]; +# static int arc_radius_factor_tab[ARC_RADIUS_FACTOR_TAB_SZ]; +# static int sin_tab[SIN_TAB_SZ]; + +class tabs_generator(object): + _fraction_shift = 10 + _ref_radius_shift = 10 + _slope_tab_sz = 128 + _arc_radius_ratio_tab_sz = 128 + _arc_radius_factor_tab_sz = 128 + _sin_tab_sz = 256 + + def gen_slope_tab(self): + lines = [] + line = '''\ +/*! \\brief The table used to map a slope to an index. + * + * The index is used to be a key in other tables. + * The table is an array of slope values for vectors in 0~(PI/4) + * direction. + */\ +''' + lines.append(line) + line = 'int slope_tab[SLOPE_TAB_SZ] = {' + lines.append(line) + + factor = 1 << self._fraction_shift + + for i in range(self._slope_tab_sz): + angle = pi / 4 * i / (self._slope_tab_sz - 1) + slope = int(sin(angle) / cos(angle) * factor) + line = ' %d,' % (slope) + lines.append(line) + pass + + line = ' };' + lines.append(line) + return lines + + def gen_center_shift_tab(self): + lines = [] + line = '''\ +/*! \\brief The table maps the slope of an arc to the factors of shifting. + * + * Every mapped slope is associated with two factors for x and y + * axis respective. The are multiplied with length of the arc to + * get shifting value in x and y axis direction. + */\ +''' + lines.append(line) + line = 'int center_shift_tab[SLOPE_TAB_SZ][2] = {' + lines.append(line) + + radius = 1 << (self._ref_radius_shift + self._fraction_shift) + + for i in range(self._slope_tab_sz): + angle = pi / 4 * i / (self._slope_tab_sz - 1) + x = -int(cos(angle) * radius) + y = -int(sin(angle) * radius) + line = ' {%d, %d},' % (x, y) + lines.append(line) + pass + + line = ' };' + lines.append(line) + return lines + + def gen_vector_len_factor_tab(self): + lines = [] + line = '''\ +/*! \\brief The table maps a slope to a lenght factor for a vector. + * + * The factor is used to multipled with one of axis values + * to get the lenght of the vector. + * The range of mapped slopes are 0~(PI/4). + */\ +''' + lines.append(line) + line = 'int vector_len_factor_tab[SLOPE_TAB_SZ] = {' + lines.append(line) + + frac_factor = 1 << self._fraction_shift + + for i in range(self._slope_tab_sz): + angle = pi / 4 * i / (self._slope_tab_sz - 1) + factor = int((1 / cos(angle)) * frac_factor) + line = ' %d,' % (factor) + lines.append(line) + pass + + line = ' };' + lines.append(line) + return lines + + def gen_arc_radius_ratio_tab(self): + lines = [] + line = '''\ +/*! \\brief A table of ratio from an arc to its radius. + * + * It is to find an index for a given ratio value. + */\ +''' + lines.append(line) + line = 'int arc_radius_ratio_tab[ARC_RADIUS_RATIO_TAB_SZ] = {' + lines.append(line) + + frac_factor = 1 << self._fraction_shift + + for i in range(self._arc_radius_ratio_tab_sz): + arc_ratio = 2.0 * i / (self._arc_radius_ratio_tab_sz - 1) + arc_ratio = int(arc_ratio * frac_factor) + line = ' %d,' % (arc_ratio) + lines.append(line) + pass + + line = ' };' + lines.append(line) + return lines + + def gen_arc_radius_factor_tab(self): + lines = [] + line = '''\ +/*! \\brief The table maps an arc-radius ratio to a distance factor. + * + * The factor is multiplied with radius to get distance of arc and + * center. It is in the order of arc_radius_ratio_tab. + */\ +''' + lines.append(line) + line = 'int arc_radius_factor_tab[ARC_RADIUS_FACTOR_TAB_SZ] = {' + lines.append(line) + + frac_factor = 1 << self._fraction_shift + + for i in range(self._arc_radius_factor_tab_sz): + arc = 2.0 * i / (self._arc_radius_factor_tab_sz - 1) + factor = int(sqrt(1 - (arc / 2) ** 2) * frac_factor) + line = ' %d,' % (factor) + lines.append(line) + pass + + line = ' };' + lines.append(line) + return lines + + def gen_sin_tab(self): + lines = [] + line = '/*! \\brief A table of sin() values */' + lines.append(line) + line = 'int sin_tab[SIN_TAB_SZ] = {' + lines.append(line) + + frac_factor = 1 << self._fraction_shift + + for i in range(self._sin_tab_sz): + angle = i * pi / 2 / (self._sin_tab_sz - 1) + _sin = int(sin(angle) * frac_factor) + line = ' %d,' % (_sin) + lines.append(line) + pass + + line = ' };' + lines.append(line) + return lines + + def gen_definition(self, out): + line = '/* This file is generated by tools/gen_precomputed_tabs.py */' + print >> out, line + print >> out + lines = self.gen_slope_tab() + print >> out, '\n'.join(lines) + print >> out + print >> out + lines = self.gen_center_shift_tab() + print >> out, '\n'.join(lines) + print >> out + print >> out + lines = self.gen_vector_len_factor_tab() + print >> out, '\n'.join(lines) + print >> out + print >> out + lines = self.gen_arc_radius_ratio_tab() + print >> out, '\n'.join(lines) + print >> out + print >> out + lines = self.gen_arc_radius_factor_tab() + print >> out, '\n'.join(lines) + print >> out + print >> out + lines = self.gen_sin_tab() + print >> out, '\n'.join(lines) + print >> out + pass + + def gen_declaration(self, out): + line = '''\ +#define FRACTION_SHIFT %d + +#define REF_RADIUS_SHIFT %d +#define SLOPE_TAB_SZ %d +#define ARC_RADIUS_RATIO_TAB_SZ %d +#define ARC_RADIUS_FACTOR_TAB_SZ %d +#define SIN_TAB_SZ %d + +extern int slope_tab[SLOPE_TAB_SZ]; +extern int center_shift_tab[SLOPE_TAB_SZ][2]; +extern int vector_len_factor_tab[SLOPE_TAB_SZ]; +extern int arc_radius_ratio_tab[ARC_RADIUS_RATIO_TAB_SZ]; +extern int arc_radius_factor_tab[ARC_RADIUS_FACTOR_TAB_SZ]; +extern int sin_tab[SIN_TAB_SZ]; +''' + line = line % (self._fraction_shift, self._ref_radius_shift, + self._slope_tab_sz, self._arc_radius_ratio_tab_sz, + self._arc_radius_factor_tab_sz, self._sin_tab_sz) + print >> out, line + pass + pass + +if __name__ == '__main__': + import sys + + def usage(progname): + print >> sys.stderr, 'Usage: %s <C file> <header file>' % (progname) + sys.exit(255) + pass + + if len(sys.argv) != 3: + usage(sys.argv[0]) + pass + + cfile = sys.argv[1] + hfile = sys.argv[2] + + gen = tabs_generator() + + cout = file(cfile, 'w+') + print >> cout, '#include "%s"' % (hfile) + print >> cout + gen.gen_definition(cout) + cout.close() + + hout = file(hfile, 'w+') + sentinel = '__' + hfile.upper().replace('.', '_') + '_' + print >> hout, '#ifndef %s' % (sentinel) + print >> hout, '#define %s' % (sentinel) + print >> hout + gen.gen_declaration(hout) + print >> hout, '#endif /* %s */' % (sentinel) + hout.close() + pass