comparison 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
comparison
equal deleted inserted replaced
1128:b65ac686a7c5 1129:eca737d33a18
1 #!/usr/bin/env python
2 from math import pi, sin, cos, sqrt
3
4 # #define FRACTION_SHIFT 10
5 #
6 # #define REF_RADIUS_SHIFT 10
7 # #define SLOPE_TAB_SZ 128
8 # #define ARC_RADIUS_RATIO_TAB_SZ 128
9 # #define ARC_RADIUS_FACTOR_TAB_SZ ARC_RADIUS_RATIO_TAB_SZ
10 # #define SIN_TAB_SZ 256
11 # static int slope_tab[SLOPE_TAB_SZ];
12 # static int center_shift_tab[SLOPE_TAB_SZ][2];
13 # static int vector_len_factor_tab[SLOPE_TAB_SZ];
14 # static int arc_radius_ratio_tab[ARC_RADIUS_RATIO_TAB_SZ];
15 # static int arc_radius_factor_tab[ARC_RADIUS_FACTOR_TAB_SZ];
16 # static int sin_tab[SIN_TAB_SZ];
17
18 class tabs_generator(object):
19 _fraction_shift = 10
20 _ref_radius_shift = 10
21 _slope_tab_sz = 128
22 _arc_radius_ratio_tab_sz = 128
23 _arc_radius_factor_tab_sz = 128
24 _sin_tab_sz = 256
25
26 def gen_slope_tab(self):
27 lines = []
28 line = '''\
29 /*! \\brief The table used to map a slope to an index.
30 *
31 * The index is used to be a key in other tables.
32 * The table is an array of slope values for vectors in 0~(PI/4)
33 * direction.
34 */\
35 '''
36 lines.append(line)
37 line = 'int slope_tab[SLOPE_TAB_SZ] = {'
38 lines.append(line)
39
40 factor = 1 << self._fraction_shift
41
42 for i in range(self._slope_tab_sz):
43 angle = pi / 4 * i / (self._slope_tab_sz - 1)
44 slope = int(sin(angle) / cos(angle) * factor)
45 line = ' %d,' % (slope)
46 lines.append(line)
47 pass
48
49 line = ' };'
50 lines.append(line)
51 return lines
52
53 def gen_center_shift_tab(self):
54 lines = []
55 line = '''\
56 /*! \\brief The table maps the slope of an arc to the factors of shifting.
57 *
58 * Every mapped slope is associated with two factors for x and y
59 * axis respective. The are multiplied with length of the arc to
60 * get shifting value in x and y axis direction.
61 */\
62 '''
63 lines.append(line)
64 line = 'int center_shift_tab[SLOPE_TAB_SZ][2] = {'
65 lines.append(line)
66
67 radius = 1 << (self._ref_radius_shift + self._fraction_shift)
68
69 for i in range(self._slope_tab_sz):
70 angle = pi / 4 * i / (self._slope_tab_sz - 1)
71 x = -int(cos(angle) * radius)
72 y = -int(sin(angle) * radius)
73 line = ' {%d, %d},' % (x, y)
74 lines.append(line)
75 pass
76
77 line = ' };'
78 lines.append(line)
79 return lines
80
81 def gen_vector_len_factor_tab(self):
82 lines = []
83 line = '''\
84 /*! \\brief The table maps a slope to a lenght factor for a vector.
85 *
86 * The factor is used to multipled with one of axis values
87 * to get the lenght of the vector.
88 * The range of mapped slopes are 0~(PI/4).
89 */\
90 '''
91 lines.append(line)
92 line = 'int vector_len_factor_tab[SLOPE_TAB_SZ] = {'
93 lines.append(line)
94
95 frac_factor = 1 << self._fraction_shift
96
97 for i in range(self._slope_tab_sz):
98 angle = pi / 4 * i / (self._slope_tab_sz - 1)
99 factor = int((1 / cos(angle)) * frac_factor)
100 line = ' %d,' % (factor)
101 lines.append(line)
102 pass
103
104 line = ' };'
105 lines.append(line)
106 return lines
107
108 def gen_arc_radius_ratio_tab(self):
109 lines = []
110 line = '''\
111 /*! \\brief A table of ratio from an arc to its radius.
112 *
113 * It is to find an index for a given ratio value.
114 */\
115 '''
116 lines.append(line)
117 line = 'int arc_radius_ratio_tab[ARC_RADIUS_RATIO_TAB_SZ] = {'
118 lines.append(line)
119
120 frac_factor = 1 << self._fraction_shift
121
122 for i in range(self._arc_radius_ratio_tab_sz):
123 arc_ratio = 2.0 * i / (self._arc_radius_ratio_tab_sz - 1)
124 arc_ratio = int(arc_ratio * frac_factor)
125 line = ' %d,' % (arc_ratio)
126 lines.append(line)
127 pass
128
129 line = ' };'
130 lines.append(line)
131 return lines
132
133 def gen_arc_radius_factor_tab(self):
134 lines = []
135 line = '''\
136 /*! \\brief The table maps an arc-radius ratio to a distance factor.
137 *
138 * The factor is multiplied with radius to get distance of arc and
139 * center. It is in the order of arc_radius_ratio_tab.
140 */\
141 '''
142 lines.append(line)
143 line = 'int arc_radius_factor_tab[ARC_RADIUS_FACTOR_TAB_SZ] = {'
144 lines.append(line)
145
146 frac_factor = 1 << self._fraction_shift
147
148 for i in range(self._arc_radius_factor_tab_sz):
149 arc = 2.0 * i / (self._arc_radius_factor_tab_sz - 1)
150 factor = int(sqrt(1 - (arc / 2) ** 2) * frac_factor)
151 line = ' %d,' % (factor)
152 lines.append(line)
153 pass
154
155 line = ' };'
156 lines.append(line)
157 return lines
158
159 def gen_sin_tab(self):
160 lines = []
161 line = '/*! \\brief A table of sin() values */'
162 lines.append(line)
163 line = 'int sin_tab[SIN_TAB_SZ] = {'
164 lines.append(line)
165
166 frac_factor = 1 << self._fraction_shift
167
168 for i in range(self._sin_tab_sz):
169 angle = i * pi / 2 / (self._sin_tab_sz - 1)
170 _sin = int(sin(angle) * frac_factor)
171 line = ' %d,' % (_sin)
172 lines.append(line)
173 pass
174
175 line = ' };'
176 lines.append(line)
177 return lines
178
179 def gen_definition(self, out):
180 line = '/* This file is generated by tools/gen_precomputed_tabs.py */'
181 print >> out, line
182 print >> out
183 lines = self.gen_slope_tab()
184 print >> out, '\n'.join(lines)
185 print >> out
186 print >> out
187 lines = self.gen_center_shift_tab()
188 print >> out, '\n'.join(lines)
189 print >> out
190 print >> out
191 lines = self.gen_vector_len_factor_tab()
192 print >> out, '\n'.join(lines)
193 print >> out
194 print >> out
195 lines = self.gen_arc_radius_ratio_tab()
196 print >> out, '\n'.join(lines)
197 print >> out
198 print >> out
199 lines = self.gen_arc_radius_factor_tab()
200 print >> out, '\n'.join(lines)
201 print >> out
202 print >> out
203 lines = self.gen_sin_tab()
204 print >> out, '\n'.join(lines)
205 print >> out
206 pass
207
208 def gen_declaration(self, out):
209 line = '''\
210 #define FRACTION_SHIFT %d
211
212 #define REF_RADIUS_SHIFT %d
213 #define SLOPE_TAB_SZ %d
214 #define ARC_RADIUS_RATIO_TAB_SZ %d
215 #define ARC_RADIUS_FACTOR_TAB_SZ %d
216 #define SIN_TAB_SZ %d
217
218 extern int slope_tab[SLOPE_TAB_SZ];
219 extern int center_shift_tab[SLOPE_TAB_SZ][2];
220 extern int vector_len_factor_tab[SLOPE_TAB_SZ];
221 extern int arc_radius_ratio_tab[ARC_RADIUS_RATIO_TAB_SZ];
222 extern int arc_radius_factor_tab[ARC_RADIUS_FACTOR_TAB_SZ];
223 extern int sin_tab[SIN_TAB_SZ];
224 '''
225 line = line % (self._fraction_shift, self._ref_radius_shift,
226 self._slope_tab_sz, self._arc_radius_ratio_tab_sz,
227 self._arc_radius_factor_tab_sz, self._sin_tab_sz)
228 print >> out, line
229 pass
230 pass
231
232 if __name__ == '__main__':
233 import sys
234
235 def usage(progname):
236 print >> sys.stderr, 'Usage: %s <C file> <header file>' % (progname)
237 sys.exit(255)
238 pass
239
240 if len(sys.argv) != 3:
241 usage(sys.argv[0])
242 pass
243
244 cfile = sys.argv[1]
245 hfile = sys.argv[2]
246
247 gen = tabs_generator()
248
249 cout = file(cfile, 'w+')
250 print >> cout, '#include "%s"' % (hfile)
251 print >> cout
252 gen.gen_definition(cout)
253 cout.close()
254
255 hout = file(hfile, 'w+')
256 sentinel = '__' + hfile.upper().replace('.', '_') + '_'
257 print >> hout, '#ifndef %s' % (sentinel)
258 print >> hout, '#define %s' % (sentinel)
259 print >> hout
260 gen.gen_declaration(hout)
261 print >> hout, '#endif /* %s */' % (sentinel)
262 hout.close()
263 pass