3 * File name: ir/tv/strcalc.c
9 * Copyright: (c) 2003 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
23 #include <assert.h> /* assertions */
24 #include <string.h> /* memset/memcmp */
25 #include <stdio.h> /* output for error messages */
26 #include <limits.h> /* definition of LONG_MIN, used in sc_get_val_from_long */
29 * local definitions and macros
31 #define CLEAR_BUFFER(b) assert(b); memset(b, SC_0, CALC_BUFFER_SIZE)
32 #define _val(a) ((a)-SC_0)
33 #define _digit(a) ((a)+SC_0)
34 #define _bitisset(digit, pos) (and_table[_val(digit)][_val(shift_table[pos])] != SC_0)
36 #define fail_char(a, b, c, d) _fail_char((a), (b), (c), (d), __FILE__, __LINE__)
38 /* shortcut output for debugging */
39 # define sc_print_hex(a) sc_print((a), 0, SC_HEX)
40 # define sc_print_dec(a) sc_print((a), 0, SC_DEC)
41 # define sc_print_oct(a) sc_print((a), 0, SC_OCT)
42 # define sc_print_bin(a) sc_print((a), 0, SC_BIN)
44 #ifdef STRCALC_DEBUG_PRINTCOMP
45 # define DEBUGPRINTF_COMPUTATION(x) printf x
47 # define DEBUGPRINTF_COMPUTATION(x) ((void)0)
50 # define DEBUGPRINTF(x) printf x
52 # define DEBUGPRINTF(x) ((void)0)
60 static char *calc_buffer = NULL; /* buffer holding all results */
61 static char *output_buffer = NULL; /* buffer for output */
62 static int BIT_PATTERN_SIZE; /* maximum number of bits */
63 static int CALC_BUFFER_SIZE; /* size of internally stored values */
64 static int MAX_VALUE_SIZE; /* maximum size of values */
66 static int carry_flag; /* some computation set carry_flag: */
67 /* rightshift if bits were lost due to shifting */
68 /* division if there was a remainder */
70 static const char max_digit[4] = { SC_0, SC_1, SC_3, SC_7 };
71 static const char min_digit[4] = { SC_F, SC_E, SC_C, SC_8 };
73 static const char not_table[16] = { SC_F, SC_E, SC_D, SC_C, SC_B, SC_A, SC_9, SC_8,
74 SC_7, SC_6, SC_5, SC_4, SC_3, SC_2, SC_1, SC_0 };
76 static const char shift_table[4] = { SC_1, SC_2, SC_4, SC_8 };
78 static const char and_table[16][16] = {
79 { SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0,
80 SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0 },
82 { SC_0, SC_1, SC_0, SC_1, SC_0, SC_1, SC_0, SC_1,
83 SC_0, SC_1, SC_0, SC_1, SC_0, SC_1, SC_0, SC_1 },
85 { SC_0, SC_0, SC_2, SC_2, SC_0, SC_0, SC_2, SC_2,
86 SC_0, SC_0, SC_2, SC_2, SC_0, SC_0, SC_2, SC_2 },
88 { SC_0, SC_1, SC_2, SC_3, SC_0, SC_1, SC_2, SC_3,
89 SC_0, SC_1, SC_2, SC_3, SC_0, SC_1, SC_2, SC_3 },
91 { SC_0, SC_0, SC_0, SC_0, SC_4, SC_4, SC_4, SC_4,
92 SC_0, SC_0, SC_0, SC_0, SC_4, SC_4, SC_4, SC_4 },
94 { SC_0, SC_1, SC_0, SC_1, SC_4, SC_5, SC_4, SC_5,
95 SC_0, SC_1, SC_0, SC_1, SC_4, SC_5, SC_4, SC_5 },
97 { SC_0, SC_0, SC_2, SC_2, SC_4, SC_4, SC_6, SC_6,
98 SC_0, SC_0, SC_2, SC_2, SC_4, SC_4, SC_6, SC_6 },
100 { SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7,
101 SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7 },
103 { SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0,
104 SC_8, SC_8, SC_8, SC_8, SC_8, SC_8, SC_8, SC_8 },
106 { SC_0, SC_1, SC_0, SC_1, SC_0, SC_1, SC_0, SC_1,
107 SC_8, SC_9, SC_8, SC_9, SC_8, SC_9, SC_8, SC_9 },
109 { SC_0, SC_0, SC_2, SC_2, SC_0, SC_0, SC_2, SC_2,
110 SC_8, SC_8, SC_A, SC_A, SC_8, SC_8, SC_A, SC_A },
112 { SC_0, SC_1, SC_2, SC_3, SC_0, SC_1, SC_2, SC_3,
113 SC_8, SC_9, SC_A, SC_B, SC_8, SC_9, SC_A, SC_B },
115 { SC_0, SC_0, SC_0, SC_0, SC_4, SC_4, SC_4, SC_4,
116 SC_8, SC_8, SC_8, SC_8, SC_C, SC_C, SC_C, SC_C },
118 { SC_0, SC_1, SC_0, SC_1, SC_4, SC_5, SC_4, SC_5,
119 SC_8, SC_9, SC_8, SC_9, SC_C, SC_D, SC_C, SC_D },
121 { SC_0, SC_0, SC_2, SC_2, SC_4, SC_4, SC_6, SC_6,
122 SC_8, SC_8, SC_A, SC_A, SC_C, SC_C, SC_E, SC_E },
124 { SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7,
125 SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F } };
127 static const char or_table[16][16] = {
128 { SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7,
129 SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F },
131 { SC_1, SC_1, SC_3, SC_3, SC_5, SC_5, SC_7, SC_7,
132 SC_9, SC_9, SC_B, SC_B, SC_D, SC_D, SC_F, SC_F },
134 { SC_2, SC_3, SC_2, SC_3, SC_6, SC_7, SC_6, SC_7,
135 SC_A, SC_B, SC_A, SC_B, SC_E, SC_F, SC_E, SC_F },
137 { SC_3, SC_3, SC_3, SC_3, SC_7, SC_7, SC_7, SC_7,
138 SC_B, SC_B, SC_B, SC_B, SC_F, SC_F, SC_F, SC_F },
140 { SC_4, SC_5, SC_6, SC_7, SC_4, SC_5, SC_6, SC_7,
141 SC_C, SC_D, SC_E, SC_F, SC_C, SC_D, SC_E, SC_F },
143 { SC_5, SC_5, SC_7, SC_7, SC_5, SC_5, SC_7, SC_7,
144 SC_D, SC_D, SC_F, SC_F, SC_D, SC_D, SC_F, SC_F },
146 { SC_6, SC_7, SC_6, SC_7, SC_6, SC_7, SC_6, SC_7,
147 SC_E, SC_F, SC_E, SC_F, SC_E, SC_F, SC_E, SC_F },
149 { SC_7, SC_7, SC_7, SC_7, SC_7, SC_7, SC_7, SC_7,
150 SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F },
152 { SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F,
153 SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F },
155 { SC_9, SC_9, SC_B, SC_B, SC_D, SC_D, SC_F, SC_F,
156 SC_9, SC_9, SC_B, SC_B, SC_D, SC_D, SC_F, SC_F },
158 { SC_A, SC_B, SC_A, SC_B, SC_E, SC_F, SC_E, SC_F,
159 SC_A, SC_B, SC_A, SC_B, SC_E, SC_F, SC_E, SC_F },
161 { SC_B, SC_B, SC_B, SC_B, SC_F, SC_F, SC_F, SC_F,
162 SC_B, SC_B, SC_B, SC_B, SC_F, SC_F, SC_F, SC_F },
164 { SC_C, SC_D, SC_E, SC_F, SC_C, SC_D, SC_E, SC_F,
165 SC_C, SC_D, SC_E, SC_F, SC_C, SC_D, SC_E, SC_F },
167 { SC_D, SC_D, SC_F, SC_F, SC_D, SC_D, SC_F, SC_F,
168 SC_D, SC_D, SC_F, SC_F, SC_D, SC_D, SC_F, SC_F },
170 { SC_E, SC_F, SC_E, SC_F, SC_E, SC_F, SC_E, SC_F,
171 SC_E, SC_F, SC_E, SC_F, SC_E, SC_F, SC_E, SC_F },
173 { SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F,
174 SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F } };
176 static char const xor_table[16][16] = {
177 { SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7,
178 SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F },
180 { SC_1, SC_0, SC_3, SC_2, SC_5, SC_4, SC_7, SC_6,
181 SC_9, SC_8, SC_B, SC_A, SC_D, SC_C, SC_F, SC_E },
183 { SC_2, SC_3, SC_0, SC_1, SC_6, SC_7, SC_4, SC_5,
184 SC_A, SC_B, SC_8, SC_9, SC_E, SC_F, SC_C, SC_D },
186 { SC_3, SC_2, SC_1, SC_0, SC_7, SC_6, SC_5, SC_4,
187 SC_B, SC_A, SC_9, SC_8, SC_F, SC_E, SC_D, SC_C },
189 { SC_4, SC_5, SC_6, SC_7, SC_0, SC_1, SC_2, SC_3,
190 SC_C, SC_D, SC_E, SC_F, SC_8, SC_9, SC_A, SC_B },
192 { SC_5, SC_4, SC_7, SC_6, SC_1, SC_0, SC_3, SC_2,
193 SC_D, SC_C, SC_F, SC_E, SC_9, SC_8, SC_B, SC_A },
195 { SC_6, SC_7, SC_4, SC_5, SC_2, SC_3, SC_0, SC_1,
196 SC_E, SC_F, SC_C, SC_D, SC_A, SC_B, SC_8, SC_9 },
198 { SC_7, SC_6, SC_5, SC_4, SC_3, SC_2, SC_1, SC_0,
199 SC_F, SC_E, SC_D, SC_C, SC_B, SC_A, SC_9, SC_8 },
201 { SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F,
202 SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7 },
204 { SC_9, SC_8, SC_B, SC_A, SC_D, SC_C, SC_F, SC_E,
205 SC_1, SC_0, SC_3, SC_2, SC_5, SC_4, SC_7, SC_6 },
207 { SC_A, SC_B, SC_8, SC_9, SC_E, SC_F, SC_C, SC_D,
208 SC_2, SC_3, SC_0, SC_1, SC_6, SC_7, SC_4, SC_5 },
210 { SC_B, SC_A, SC_9, SC_8, SC_F, SC_E, SC_D, SC_C,
211 SC_3, SC_2, SC_1, SC_0, SC_7, SC_6, SC_5, SC_4 },
213 { SC_C, SC_D, SC_E, SC_F, SC_8, SC_9, SC_A, SC_B,
214 SC_4, SC_5, SC_6, SC_7, SC_0, SC_1, SC_2, SC_3 },
216 { SC_D, SC_C, SC_F, SC_E, SC_9, SC_8, SC_B, SC_A,
217 SC_5, SC_4, SC_7, SC_6, SC_1, SC_0, SC_3, SC_2 },
219 { SC_E, SC_F, SC_C, SC_D, SC_A, SC_B, SC_8, SC_9,
220 SC_6, SC_7, SC_4, SC_5, SC_2, SC_3, SC_0, SC_1 },
222 { SC_F, SC_E, SC_D, SC_C, SC_B, SC_A, SC_9, SC_8,
223 SC_7, SC_6, SC_5, SC_4, SC_3, SC_2, SC_1, SC_0 }
226 static char const add_table[16][16][2] = {
227 { {SC_0, SC_0}, {SC_1, SC_0}, {SC_2, SC_0}, {SC_3, SC_0},
228 {SC_4, SC_0}, {SC_5, SC_0}, {SC_6, SC_0}, {SC_7, SC_0},
229 {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0},
230 {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0} },
232 { {SC_1, SC_0}, {SC_2, SC_0}, {SC_3, SC_0}, {SC_4, SC_0},
233 {SC_5, SC_0}, {SC_6, SC_0}, {SC_7, SC_0}, {SC_8, SC_0},
234 {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0},
235 {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1} },
237 { {SC_2, SC_0}, {SC_3, SC_0}, {SC_4, SC_0}, {SC_5, SC_0},
238 {SC_6, SC_0}, {SC_7, SC_0}, {SC_8, SC_0}, {SC_9, SC_0},
239 {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0},
240 {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1} },
242 { {SC_3, SC_0}, {SC_4, SC_0}, {SC_5, SC_0}, {SC_6, SC_0},
243 {SC_7, SC_0}, {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0},
244 {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0},
245 {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1} },
247 { {SC_4, SC_0}, {SC_5, SC_0}, {SC_6, SC_0}, {SC_7, SC_0},
248 {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0},
249 {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0},
250 {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1} },
252 { {SC_5, SC_0}, {SC_6, SC_0}, {SC_7, SC_0}, {SC_8, SC_0},
253 {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0},
254 {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1},
255 {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1} },
257 { {SC_6, SC_0}, {SC_7, SC_0}, {SC_8, SC_0}, {SC_9, SC_0},
258 {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0},
259 {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1},
260 {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1} },
262 { {SC_7, SC_0}, {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0},
263 {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0},
264 {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1},
265 {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1}, {SC_6, SC_1} },
267 { {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0},
268 {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0},
269 {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1},
270 {SC_4, SC_1}, {SC_5, SC_1}, {SC_6, SC_1}, {SC_7, SC_1} },
272 { {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0},
273 {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1},
274 {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1},
275 {SC_5, SC_1}, {SC_6, SC_1}, {SC_7, SC_1}, {SC_8, SC_1} },
277 { {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0},
278 {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1},
279 {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1},
280 {SC_6, SC_1}, {SC_7, SC_1}, {SC_8, SC_1}, {SC_9, SC_1} },
282 { {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0},
283 {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1},
284 {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1}, {SC_6, SC_1},
285 {SC_7, SC_1}, {SC_8, SC_1}, {SC_9, SC_1}, {SC_A, SC_1} },
287 { {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0},
288 {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1},
289 {SC_4, SC_1}, {SC_5, SC_1}, {SC_6, SC_1}, {SC_7, SC_1},
290 {SC_8, SC_1}, {SC_9, SC_1}, {SC_A, SC_1}, {SC_B, SC_1} },
292 { {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1},
293 {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1},
294 {SC_5, SC_1}, {SC_6, SC_1}, {SC_7, SC_1}, {SC_8, SC_1},
295 {SC_9, SC_1}, {SC_A, SC_1}, {SC_B, SC_1}, {SC_C, SC_1} },
297 { {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1},
298 {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1},
299 {SC_6, SC_1}, {SC_7, SC_1}, {SC_8, SC_1}, {SC_9, SC_1},
300 {SC_A, SC_1}, {SC_B, SC_1}, {SC_C, SC_1}, {SC_D, SC_1} },
302 { {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1},
303 {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1}, {SC_6, SC_1},
304 {SC_7, SC_1}, {SC_8, SC_1}, {SC_9, SC_1}, {SC_A, SC_1},
305 {SC_B, SC_1}, {SC_C, SC_1}, {SC_D, SC_1}, {SC_E, SC_1} }
308 static char const mul_table[16][16][2] = {
309 { {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0},
310 {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0},
311 {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0},
312 {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0} },
314 { {SC_0, SC_0}, {SC_1, SC_0}, {SC_2, SC_0}, {SC_3, SC_0},
315 {SC_4, SC_0}, {SC_5, SC_0}, {SC_6, SC_0}, {SC_7, SC_0},
316 {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0},
317 {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0} },
319 { {SC_0, SC_0}, {SC_2, SC_0}, {SC_4, SC_0}, {SC_6, SC_0},
320 {SC_8, SC_0}, {SC_A, SC_0}, {SC_C, SC_0}, {SC_E, SC_0},
321 {SC_0, SC_1}, {SC_2, SC_1}, {SC_4, SC_1}, {SC_6, SC_1},
322 {SC_8, SC_1}, {SC_A, SC_1}, {SC_C, SC_1}, {SC_E, SC_1} },
324 { {SC_0, SC_0}, {SC_3, SC_0}, {SC_6, SC_0}, {SC_9, SC_0},
325 {SC_C, SC_0}, {SC_F, SC_0}, {SC_2, SC_1}, {SC_5, SC_1},
326 {SC_8, SC_1}, {SC_B, SC_1}, {SC_E, SC_1}, {SC_1, SC_2},
327 {SC_4, SC_2}, {SC_7, SC_2}, {SC_A, SC_2}, {SC_D, SC_2} },
329 { {SC_0, SC_0}, {SC_4, SC_0}, {SC_8, SC_0}, {SC_C, SC_0},
330 {SC_0, SC_1}, {SC_4, SC_1}, {SC_8, SC_1}, {SC_C, SC_1},
331 {SC_0, SC_2}, {SC_4, SC_2}, {SC_8, SC_2}, {SC_C, SC_2},
332 {SC_0, SC_3}, {SC_4, SC_3}, {SC_8, SC_3}, {SC_C, SC_3} },
334 { {SC_0, SC_0}, {SC_5, SC_0}, {SC_A, SC_0}, {SC_F, SC_0},
335 {SC_4, SC_1}, {SC_9, SC_1}, {SC_E, SC_1}, {SC_3, SC_2},
336 {SC_8, SC_2}, {SC_D, SC_2}, {SC_2, SC_3}, {SC_7, SC_3},
337 {SC_C, SC_3}, {SC_1, SC_4}, {SC_6, SC_4}, {SC_B, SC_4} },
339 { {SC_0, SC_0}, {SC_6, SC_0}, {SC_C, SC_0}, {SC_2, SC_1},
340 {SC_8, SC_1}, {SC_E, SC_1}, {SC_4, SC_2}, {SC_A, SC_2},
341 {SC_0, SC_3}, {SC_6, SC_3}, {SC_C, SC_3}, {SC_2, SC_4},
342 {SC_8, SC_4}, {SC_E, SC_4}, {SC_4, SC_5}, {SC_A, SC_5} },
344 { {SC_0, SC_0}, {SC_7, SC_0}, {SC_E, SC_0}, {SC_5, SC_1},
345 {SC_C, SC_1}, {SC_3, SC_2}, {SC_A, SC_2}, {SC_1, SC_3},
346 {SC_8, SC_3}, {SC_F, SC_3}, {SC_6, SC_4}, {SC_D, SC_4},
347 {SC_4, SC_5}, {SC_B, SC_5}, {SC_2, SC_6}, {SC_9, SC_6} },
349 { {SC_0, SC_0}, {SC_8, SC_0}, {SC_0, SC_1}, {SC_8, SC_1},
350 {SC_0, SC_2}, {SC_8, SC_2}, {SC_0, SC_3}, {SC_8, SC_3},
351 {SC_0, SC_4}, {SC_8, SC_4}, {SC_0, SC_5}, {SC_8, SC_5},
352 {SC_0, SC_6}, {SC_8, SC_6}, {SC_0, SC_7}, {SC_8, SC_7} },
354 { {SC_0, SC_0}, {SC_9, SC_0}, {SC_2, SC_1}, {SC_B, SC_1},
355 {SC_4, SC_2}, {SC_D, SC_2}, {SC_6, SC_3}, {SC_F, SC_3},
356 {SC_8, SC_4}, {SC_1, SC_5}, {SC_A, SC_5}, {SC_3, SC_6},
357 {SC_C, SC_6}, {SC_5, SC_7}, {SC_E, SC_7}, {SC_7, SC_8} },
359 { {SC_0, SC_0}, {SC_A, SC_0}, {SC_4, SC_1}, {SC_E, SC_1},
360 {SC_8, SC_2}, {SC_2, SC_3}, {SC_C, SC_3}, {SC_6, SC_4},
361 {SC_0, SC_5}, {SC_A, SC_5}, {SC_4, SC_6}, {SC_E, SC_6},
362 {SC_8, SC_7}, {SC_2, SC_8}, {SC_C, SC_8}, {SC_6, SC_9} },
364 { {SC_0, SC_0}, {SC_B, SC_0}, {SC_6, SC_1}, {SC_1, SC_2},
365 {SC_C, SC_2}, {SC_7, SC_3}, {SC_2, SC_4}, {SC_D, SC_4},
366 {SC_8, SC_5}, {SC_3, SC_6}, {SC_E, SC_6}, {SC_9, SC_7},
367 {SC_4, SC_8}, {SC_F, SC_8}, {SC_A, SC_9}, {SC_5, SC_A} },
369 { {SC_0, SC_0}, {SC_C, SC_0}, {SC_8, SC_1}, {SC_4, SC_2},
370 {SC_0, SC_3}, {SC_C, SC_3}, {SC_8, SC_4}, {SC_4, SC_5},
371 {SC_0, SC_6}, {SC_C, SC_6}, {SC_8, SC_7}, {SC_4, SC_8},
372 {SC_0, SC_9}, {SC_C, SC_9}, {SC_8, SC_A}, {SC_4, SC_B} },
374 { {SC_0, SC_0}, {SC_D, SC_0}, {SC_A, SC_1}, {SC_7, SC_2},
375 {SC_4, SC_3}, {SC_1, SC_4}, {SC_E, SC_4}, {SC_B, SC_5},
376 {SC_8, SC_6}, {SC_5, SC_7}, {SC_2, SC_8}, {SC_F, SC_8},
377 {SC_C, SC_9}, {SC_9, SC_A}, {SC_6, SC_B}, {SC_3, SC_C} },
379 { {SC_0, SC_0}, {SC_E, SC_0}, {SC_C, SC_1}, {SC_A, SC_2},
380 {SC_8, SC_3}, {SC_6, SC_4}, {SC_4, SC_5}, {SC_2, SC_6},
381 {SC_0, SC_7}, {SC_E, SC_7}, {SC_C, SC_8}, {SC_A, SC_9},
382 {SC_8, SC_A}, {SC_6, SC_B}, {SC_4, SC_C}, {SC_2, SC_D} },
384 { {SC_0, SC_0}, {SC_F, SC_0}, {SC_E, SC_1}, {SC_D, SC_2},
385 {SC_C, SC_3}, {SC_B, SC_4}, {SC_A, SC_5}, {SC_9, SC_6},
386 {SC_8, SC_7}, {SC_7, SC_8}, {SC_6, SC_9}, {SC_5, SC_A},
387 {SC_4, SC_B}, {SC_3, SC_C}, {SC_2, SC_D}, {SC_1, SC_E} }
390 static char const shrs_table[16][4][2] = {
391 { {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0} },
392 { {SC_1, SC_0}, {SC_0, SC_8}, {SC_0, SC_4}, {SC_0, SC_2} },
393 { {SC_2, SC_0}, {SC_1, SC_0}, {SC_0, SC_8}, {SC_0, SC_4} },
394 { {SC_3, SC_0}, {SC_1, SC_8}, {SC_0, SC_C}, {SC_0, SC_6} },
395 { {SC_4, SC_0}, {SC_2, SC_0}, {SC_1, SC_0}, {SC_0, SC_8} },
396 { {SC_5, SC_0}, {SC_2, SC_8}, {SC_1, SC_4}, {SC_0, SC_A} },
397 { {SC_6, SC_0}, {SC_3, SC_0}, {SC_1, SC_8}, {SC_0, SC_C} },
398 { {SC_7, SC_0}, {SC_3, SC_8}, {SC_1, SC_C}, {SC_0, SC_E} },
399 { {SC_8, SC_0}, {SC_4, SC_0}, {SC_2, SC_0}, {SC_1, SC_0} },
400 { {SC_9, SC_0}, {SC_4, SC_8}, {SC_2, SC_4}, {SC_1, SC_2} },
401 { {SC_A, SC_0}, {SC_5, SC_0}, {SC_2, SC_8}, {SC_1, SC_4} },
402 { {SC_B, SC_0}, {SC_5, SC_8}, {SC_2, SC_C}, {SC_1, SC_6} },
403 { {SC_C, SC_0}, {SC_6, SC_0}, {SC_3, SC_0}, {SC_1, SC_8} },
404 { {SC_D, SC_0}, {SC_6, SC_8}, {SC_3, SC_4}, {SC_1, SC_A} },
405 { {SC_E, SC_0}, {SC_7, SC_0}, {SC_3, SC_8}, {SC_1, SC_C} },
406 { {SC_F, SC_0}, {SC_7, SC_8}, {SC_3, SC_C}, {SC_1, SC_E} }
409 /* for converting to binary string */
410 static const char *binary_table[16] = {
411 "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
412 "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
415 /*****************************************************************************
417 *****************************************************************************/
418 static void _fail_char(const char *str, size_t len, const char fchar, int pos,
419 const char *file, int line)
422 printf("Unexpected character '%c' in %s:%d\n", fchar, file, line);
423 while (len-- && *str) printf("%c", *str++); printf("\n");
424 while (--pos) printf(" "); printf("^\n");
428 static void _bitnot(const char *val, char *buffer)
432 for (counter = 0; counter<CALC_BUFFER_SIZE; counter++)
433 buffer[counter] = not_table[_val(val[counter])];
436 static void _bitor(const char *val1, const char *val2, char *buffer)
440 for (counter = 0; counter<CALC_BUFFER_SIZE; counter++)
441 buffer[counter] = or_table[_val(val1[counter])][_val(val2[counter])];
444 static void _bitxor(const char *val1, const char *val2, char *buffer)
448 for (counter = 0; counter<CALC_BUFFER_SIZE; counter++)
449 buffer[counter] = xor_table[_val(val1[counter])][_val(val2[counter])];
452 static void _bitand(const char *val1, const char *val2, char *buffer)
456 for (counter = 0; counter<CALC_BUFFER_SIZE; counter++)
457 buffer[counter] = and_table[_val(val1[counter])][_val(val2[counter])];
460 static int _sign(const char *val)
462 return (val[CALC_BUFFER_SIZE-1] <= SC_7) ? (1) : (-1);
466 * returns non-zero if bit at position pos is set
468 static int _bit(const char *val, int pos)
471 int nibble = pos >> 2;
473 return _bitisset(val[nibble], bit);
476 static void _inc(char *val, char *buffer)
480 while (counter++ < CALC_BUFFER_SIZE)
489 /* No carry here, *val != SC_F */
490 *buffer = add_table[_val(*val)][SC_1][0];
494 /* here a carry could be lost, this is intended because this should
495 * happen only when a value changes sign. */
498 static void _negate(const char *val, char *buffer)
500 _bitnot(val, buffer);
501 _inc(buffer, buffer);
504 static void _add(const char *val1, const char *val2, char *buffer)
507 const char *add1, *add2;
510 for (counter = 0; counter < CALC_BUFFER_SIZE; counter++)
512 add1 = add_table[_val(val1[counter])][_val(val2[counter])];
513 add2 = add_table[_val(add1[0])][_val(carry)];
514 /* carry might be zero */
515 buffer[counter] = add2[0];
516 carry = add_table[_val(add1[1])][_val(add2[1])][0];
520 static void _mul(const char *val1, const char *val2, char *buffer)
522 char* temp_buffer; /* result buffer */
523 char* neg_val1; /* abs of val1 */
524 char* neg_val2; /* abs of val2 */
526 const char *mul, *add1, *add2; /* intermediate result containers */
527 char carry = SC_0; /* container for carries */
528 char sign = 0; /* marks result sign */
529 int c_inner, c_outer; /* loop counters */
531 temp_buffer = alloca(CALC_BUFFER_SIZE);
532 neg_val1 = alloca(CALC_BUFFER_SIZE);
533 neg_val2 = alloca(CALC_BUFFER_SIZE);
535 /* init result buffer to zeroes */
536 memset(temp_buffer, SC_0, CALC_BUFFER_SIZE);
538 /* the multiplication works only for positive values, for negative values *
539 * it is necessary to negate them and adjust the result accordingly */
540 if (_sign(val1) == -1) {
541 _negate(val1, neg_val1);
545 if (_sign(val2) == -1) {
546 _negate(val2, neg_val2);
551 for (c_outer = 0; c_outer < MAX_VALUE_SIZE; c_outer++)
553 if (val2[c_outer] != SC_0)
555 for (c_inner = 0; c_inner < MAX_VALUE_SIZE; c_inner++)
557 /* do the following calculation: *
558 * Add the current carry, the value at position c_outer+c_inner *
559 * and the result of the multiplication of val1[c_inner] and *
560 * val2[c_outer]. This is the usual pen-and-paper multiplication. */
562 /* multiplicate the two digits */
563 mul = mul_table[_val(val1[c_inner])][_val(val2[c_outer])];
564 /* add old value to result of multiplication */
565 add1 = add_table[_val(temp_buffer[c_inner + c_outer])][_val(mul[0])];
566 /* add carry to the sum */
567 add2 = add_table[_val(add1[0])][_val(carry)];
569 /* all carries together result in new carry. This is always smaller *
571 * Both multiplicands, the carry and the value already in the temp *
572 * buffer are single digits and their value is therefore at most *
575 * (b-1)(b-1)+(b-1)+(b-1) = b*b-1 *
576 * The tables list all operations rem b, so the carry is at most *
577 * (b*b-1)rem b = -1rem b = b-1 */
578 carry = add_table[_val(mul[1])][_val(add1[1])][0];
579 carry = add_table[_val(carry)][_val(add2[1])][0];
581 temp_buffer[c_inner + c_outer] = add2[0];
584 /* A carry may hang over */
585 /* c_outer is always smaller than MAX_VALUE_SIZE! */
586 temp_buffer[MAX_VALUE_SIZE + c_outer] = carry;
592 _negate(temp_buffer, buffer);
594 memcpy(buffer, temp_buffer, CALC_BUFFER_SIZE);
597 static void _sub(const char *val1, const char *val2, char *buffer)
599 char *temp_buffer; /* intermediate buffer to hold -val2 */
600 temp_buffer = alloca(CALC_BUFFER_SIZE);
602 _negate(val2, temp_buffer);
603 _add(val1, temp_buffer, buffer);
606 static void _push(const char digit, char *buffer)
610 for (counter = CALC_BUFFER_SIZE - 2; counter >= 0; counter--)
612 buffer[counter+1] = buffer[counter];
617 /* XXX: This is MOST slow */
618 static void _divmod(const char *dividend, const char *divisor, char *quot, char *rem)
620 const char *minus_divisor;
624 char sign = 0; /* remember result sign */
626 int c_dividend; /* loop counters */
628 neg_val1 = alloca(CALC_BUFFER_SIZE);
629 neg_val2 = alloca(CALC_BUFFER_SIZE);
631 /* clear result buffer */
632 memset(quot, SC_0, CALC_BUFFER_SIZE);
633 memset(rem, SC_0, CALC_BUFFER_SIZE);
635 /* if the divisor is zero this won't work (quot is zero) */
636 if (sc_comp(divisor, quot) == 0) assert(0 && "division by zero!");
638 /* if the dividend is zero result is zero (quot is zero)*/
639 if (sc_comp(dividend, quot) == 0)
642 if (_sign(dividend) == -1)
644 _negate(dividend, neg_val1);
649 _negate(divisor, neg_val2);
650 if (_sign(divisor) == -1)
653 minus_divisor = divisor;
658 minus_divisor = neg_val2;
661 /* if divisor >= dividend division is easy
662 * (remember these are absolute values) */
663 switch (sc_comp(dividend, divisor))
665 case 0: /* dividend == divisor */
669 case -1: /* dividend < divisor */
670 memcpy(rem, dividend, CALC_BUFFER_SIZE);
673 default: /* unluckily division is necessary :( */
677 for (c_dividend = CALC_BUFFER_SIZE - 1; c_dividend >= 0; c_dividend--)
679 _push(dividend[c_dividend], rem);
682 if (sc_comp(rem, divisor) != -1) /* remainder >= divisor */
684 /* subtract until the remainder becomes negative, this should
685 * be faster than comparing remainder with divisor */
686 _add(rem, minus_divisor, rem);
688 while (_sign(rem) == 1)
690 quot[0] = add_table[_val(quot[0])][SC_1][0];
691 _add(rem, minus_divisor, rem);
694 /* subtracted one too much */
695 _add(rem, divisor, rem);
699 carry_flag = !sc_is_zero(rem);
708 static void _shl(const char *val1, char *buffer, long offset, int radius, unsigned is_signed)
717 assert((offset >= 0) || (0 && "negative leftshift"));
718 assert(((_sign(val1) != -1) || is_signed) || (0 && "unsigned mode and negative value"));
719 assert(((!_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == -1)) || (0 && "value is positive, should be negative"));
720 assert(((_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == 1)) || (0 && "value is negative, should be positive"));
722 /* if shifting far enough the result is zero */
723 if (offset >= radius)
725 memset(buffer, SC_0, CALC_BUFFER_SIZE);
729 shift = shift_table[_val(offset%4)]; /* this is 2 ** (offset % 4) */
732 /* shift the single digits some bytes (offset) and some bits (table)
734 for (counter = 0; counter < radius/4 - offset; counter++)
736 shl = mul_table[_val(val1[counter])][_val(shift)];
737 buffer[counter + offset] = or_table[_val(shl[0])][_val(carry)];
742 shl = mul_table[_val(val1[counter])][_val(shift)];
743 buffer[counter + offset] = or_table[_val(shl[0])][_val(carry)];
746 bitoffset = counter - 1;
749 /* fill with zeroes */
750 for (counter = 0; counter < offset; counter++) buffer[counter] = SC_0;
752 /* if the mode was signed, change sign when the mode's msb is now 1 */
753 offset = bitoffset + offset;
754 bitoffset = (radius-1) % 4;
755 if (is_signed && _bitisset(buffer[offset], bitoffset))
757 /* this sets the upper bits of the leftmost digit */
758 buffer[offset] = or_table[_val(buffer[offset])][_val(min_digit[bitoffset])];
759 for (counter = offset+1; counter < CALC_BUFFER_SIZE; counter++)
761 buffer[counter] = SC_F;
764 else if (is_signed && !_bitisset(buffer[offset], bitoffset))
766 /* this unsets the upper bits of the leftmost digit */
767 buffer[offset] = and_table[_val(buffer[offset])][_val(max_digit[bitoffset])];
768 for (counter = offset+1; counter < CALC_BUFFER_SIZE; counter++)
770 buffer[counter] = SC_0;
775 static void _shr(const char *val1, char *buffer, long offset, int radius, unsigned is_signed, int signed_shift)
786 assert((offset >= 0) || (0 && "negative rightshift"));
787 assert(((_sign(val1) != -1) || is_signed) || (0 && "unsigned mode and negative value"));
788 assert(((!_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == -1)) || (0 && "value is positive, should be negative"));
789 assert(((_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == 1)) || (0 && "value is negative, should be positive"));
791 sign = ((signed_shift) && (_sign(val1) == -1))?(SC_F):(SC_0);
793 /* if shifting far enough the result is either 0 or -1 */
794 if (offset >= radius)
796 if (!sc_is_zero(val1)) {
799 memset(buffer, sign, CALC_BUFFER_SIZE);
806 /* check if any bits are lost, and set carry_flag if so */
807 for (counter = 0; counter < offset; counter++)
809 if (val1[counter] != 0)
815 if ((_val(val1[counter]) & ((1<<shift)-1)) != 0)
819 /* shift digits to the right with offset, carry and all */
821 if (radius/4 - offset > 0) {
822 buffer[counter] = shrs_table[_val(val1[offset])][shift][0];
825 for (; counter < radius/4 - offset; counter++)
827 shrs = shrs_table[_val(val1[counter + offset])][shift];
828 buffer[counter] = shrs[0];
829 buffer[counter-1] = or_table[_val(buffer[counter-1])][_val(shrs[1])];
832 /* the last digit is special in regard of signed/unsigned shift */
833 bitoffset = radius%4;
834 msd = (radius/4<CALC_BUFFER_SIZE)?(val1[radius/4]):(sign); /* most significant digit */
836 /* remove sign bits if mode was signed and this is an unsigned shift */
837 if (!signed_shift && is_signed) {
838 msd = and_table[_val(msd)][_val(max_digit[bitoffset])];
841 shrs = shrs_table[_val(msd)][shift];
843 /* signed shift and signed mode and negative value means all bits to the left are set */
844 if (signed_shift && is_signed && (_sign(val1) == -1)) {
845 buffer[counter] = or_table[_val(shrs[0])][_val(min_digit[bitoffset])];
847 buffer[counter] = shrs[0];
850 if (counter > 0) buffer[counter - 1] = or_table[_val(buffer[counter-1])][_val(shrs[1])];
852 /* fill with SC_F or SC_0 depending on sign */
853 for (counter++; counter < CALC_BUFFER_SIZE; counter++)
855 buffer[counter] = sign;
859 /* positive: low-order -> high order, negative other direction */
860 static void _rot(const char *val1, char *buffer, long offset, int radius, unsigned is_signed)
863 temp1 = alloca(CALC_BUFFER_SIZE);
864 temp2 = alloca(CALC_BUFFER_SIZE);
866 offset = offset % radius;
868 /* rotation by multiples of the typelength is identity */
870 memmove(buffer, val1, CALC_BUFFER_SIZE);
874 _shl(val1, temp1, offset, radius, is_signed);
875 _shr(val1, temp2, radius - offset, radius, is_signed, 0);
876 _bitor(temp1, temp2, buffer);
877 carry_flag = 0; /* set by shr, but due to rot this is false */
880 /*****************************************************************************
881 * public functions, declared in strcalc.h
882 *****************************************************************************/
883 const void *sc_get_buffer(void)
885 return (void*)calc_buffer;
888 const int sc_get_buffer_length(void)
890 return CALC_BUFFER_SIZE;
893 /* XXX doesn't check for overflows */
894 void sc_val_from_str(const char *str, unsigned int len, void *buffer)
896 const char *orig_str = str;
897 unsigned int orig_len = len;
902 base = alloca(CALC_BUFFER_SIZE);
903 val = alloca(CALC_BUFFER_SIZE);
905 /* verify valid pointers (not null) */
907 /* a string no characters long is an error */
910 if (buffer == NULL) buffer = calc_buffer;
912 CLEAR_BUFFER(buffer);
913 memset(base, SC_0, CALC_BUFFER_SIZE);
914 memset(val, SC_0, CALC_BUFFER_SIZE);
916 /* strip leading spaces */
917 while ((len > 0) && (*str == ' ')) { len--; str++; }
919 /* if the first two characters are 0x or 0X -> hex
920 * if the first is a 0 -> oct
921 * else dec, strip leading -/+ and remember sign
923 * only a + or - sign is no number resulting in an error */
928 if (str[1] == 'x' || str[1] == 'X') /* hex */
932 base[1] = SC_1; base[0] = SC_0;
938 base[1] = SC_0; base[0] = SC_8;
946 base[1] = SC_0; base[0] = SC_A;
955 base[1] = SC_0; base[0] = SC_A;
959 default: /* dec, else would have begun with 0x or 0 */
960 base[1] = SC_0; base[0] = SC_A;
963 else /* dec, else would have begun with 0x or 0 */
965 base[1] = SC_0; base[0] = SC_A;
968 /* BEGIN string evaluation, from left to right */
979 if (base[0] > SC_9 || base[1] > SC_0) /* (base > 10) */
981 val[0] = _digit((*str)-'a'+10);
983 else fail_char(orig_str, orig_len, *str, str-orig_str+1);
992 if (base[0] > SC_9 || base[1] > SC_0) /* (base > 10) */
994 val[0] = _digit((*str)-'A'+10);
996 else fail_char(orig_str, orig_len, *str, str-orig_str+1);
1001 if (base[0] > SC_7 || base[1] > SC_0) /* (base > 8) */
1003 val[0] = _digit((*str)-'0');
1005 else fail_char(orig_str, orig_len, *str, str-orig_str+1);
1017 val[0] = _digit((*str)-'0');
1022 fail_char(orig_str, orig_len, *str, str-orig_str+1);
1023 } /* switch(*str) */
1025 /* Radix conversion from base b to base B:
1026 * (UnUn-1...U1U0)b == ((((Un*b + Un-1)*b + ...)*b + U1)*b + U0)B */
1027 _mul(base, calc_buffer, calc_buffer); /* multiply current value with base */
1028 _add(val, calc_buffer, calc_buffer); /* add next digit to current value */
1030 /* get ready for the next letter */
1034 } /* while (len > 0 ) */
1038 _negate(calc_buffer, calc_buffer);
1042 void sc_val_from_long(long value, void *buffer)
1045 char sign, is_minlong;
1047 if (buffer == NULL) buffer = calc_buffer;
1051 is_minlong = value == LONG_MIN;
1053 /* use absolute value, special treatment of MIN_LONG */
1061 CLEAR_BUFFER(buffer);
1063 while ((value != 0) && (pos < (char*)buffer + CALC_BUFFER_SIZE))
1065 *pos++ = _digit(value & 0xf);
1072 _inc(buffer, buffer);
1074 _negate(buffer, buffer);
1078 void sc_val_from_ulong(unsigned long value, void *buffer)
1082 if (buffer == NULL) buffer = calc_buffer;
1085 while (pos < (char*)buffer + CALC_BUFFER_SIZE)
1087 *pos++ = _digit(value & 0xf);
1092 long sc_val_to_long(const void *val)
1097 for (i = CALC_BUFFER_SIZE - 1; i >= 0; i--)
1099 l = (l << 4) + _val(((char *)val)[i]);
1104 void sc_min_from_bits(unsigned int num_bits, unsigned int sign, void *buffer)
1109 if (buffer == NULL) buffer = calc_buffer;
1110 CLEAR_BUFFER(buffer);
1112 if (!sign) return; /* unsigned means minimum is 0(zero) */
1116 bits = num_bits - 1;
1117 for (i = 0; i < bits/4; i++)
1120 *pos++ = min_digit[bits%4];
1122 for (i++; i <= CALC_BUFFER_SIZE - 1; i++)
1126 void sc_max_from_bits(unsigned int num_bits, unsigned int sign, void *buffer)
1131 if (buffer == NULL) buffer = calc_buffer;
1132 CLEAR_BUFFER(buffer);
1135 bits = num_bits - sign;
1136 for (i = 0; i < bits/4; i++)
1139 *pos++ = max_digit[bits%4];
1141 for (i++; i <= CALC_BUFFER_SIZE - 1; i++)
1145 void sc_calc(const void* value1, const void* value2, unsigned op, void *buffer)
1147 char *unused_res; /* temp buffer holding unused result of divmod */
1149 const char *val1 = (const char *)value1;
1150 const char *val2 = (const char *)value2;
1152 unused_res = alloca(CALC_BUFFER_SIZE);
1153 CLEAR_BUFFER(calc_buffer);
1156 DEBUGPRINTF_COMPUTATION(("%s ", sc_print_hex(value1)));
1161 _negate(val1, calc_buffer);
1162 DEBUGPRINTF_COMPUTATION(("negated: %s\n", sc_print_hex(calc_buffer)));
1165 DEBUGPRINTF_COMPUTATION(("| "));
1166 _bitor(val1, val2, calc_buffer);
1169 DEBUGPRINTF_COMPUTATION(("& "));
1170 _bitand(val1, val2, calc_buffer);
1173 DEBUGPRINTF_COMPUTATION(("^ "));
1174 _bitxor(val1, val2, calc_buffer);
1177 _bitnot(val1, calc_buffer);
1178 DEBUGPRINTF_COMPUTATION(("bit-negated: %s\n", sc_print_hex(calc_buffer)));
1181 DEBUGPRINTF_COMPUTATION(("+ "));
1182 _add(val1, val2, calc_buffer);
1185 DEBUGPRINTF_COMPUTATION(("- "));
1186 _sub(val1, val2, calc_buffer);
1189 DEBUGPRINTF_COMPUTATION(("* "));
1190 _mul(val1, val2, calc_buffer);
1193 DEBUGPRINTF_COMPUTATION(("/ "));
1194 _divmod(val1, val2, calc_buffer, unused_res);
1197 DEBUGPRINTF_COMPUTATION(("%% "));
1198 _divmod(val1, val2, unused_res, calc_buffer);
1203 DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
1204 DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
1206 if ((buffer != NULL) && (buffer != calc_buffer))
1208 memcpy(buffer, calc_buffer, CALC_BUFFER_SIZE);
1212 void sc_bitcalc(const void* value1, const void* value2, int radius, int sign, unsigned op, void* buffer)
1214 const char *val1 = (const char *)value1;
1215 const char *val2 = (const char *)value2;
1219 offset = sc_val_to_long(val2);
1221 DEBUGPRINTF_COMPUTATION(("%s ", sc_print_hex(value1)));
1225 DEBUGPRINTF_COMPUTATION(("<< %ld ", offset));
1226 _shl(val1, calc_buffer, offset, radius, sign);
1229 DEBUGPRINTF_COMPUTATION((">> %ld ", offset));
1230 _shr(val1, calc_buffer, offset, radius, sign, 0);
1233 DEBUGPRINTF_COMPUTATION((">>> %ld ", offset));
1234 _shr(val1, calc_buffer, offset, radius, sign, 1);
1237 DEBUGPRINTF_COMPUTATION(("<<>> %ld ", offset));
1238 _rot(val1, calc_buffer, offset, radius, sign);
1243 DEBUGPRINTF_COMPUTATION(("-> %s\n", sc_print_hex(calc_buffer)));
1245 if ((buffer != NULL) && (buffer != calc_buffer))
1247 memmove(buffer, calc_buffer, CALC_BUFFER_SIZE);
1251 int sc_comp(const void* value1, const void* value2)
1253 int counter = CALC_BUFFER_SIZE - 1;
1254 const char *val1 = (const char *)value1;
1255 const char *val2 = (const char *)value2;
1257 /* compare signs first:
1258 * the loop below can only compare values of the same sign! */
1259 if (_sign(val1) != _sign(val2)) return (_sign(val1) == 1)?(1):(-1);
1261 /* loop until two digits differ, the values are equal if there
1262 * are no such two digits */
1263 while (val1[counter] == val2[counter])
1266 if (counter < 0) return 0;
1269 /* the leftmost digit is the most significant, so this returns
1270 * the correct result.
1271 * This implies the digit enum is ordered */
1272 return (val1[counter] > val2[counter]) ? (1) : (-1);
1275 int sc_get_highest_set_bit(const void *value)
1277 const char *val = (const char*)value;
1280 high = CALC_BUFFER_SIZE * 4 - 1;
1282 for (counter = CALC_BUFFER_SIZE-1; counter >= 0; counter--) {
1283 if (val[counter] == SC_0) high -= 4;
1285 if (val[counter] > SC_7) return high;
1286 else if (val[counter] > SC_3) return high - 1;
1287 else if (val[counter] > SC_1) return high - 2;
1288 else return high - 3;
1294 int sc_get_lowest_set_bit(const void *value)
1296 const char *val = (const char*)value;
1300 sign = (_sign(val)==1)?(SC_0):(SC_F);
1303 for (counter = 0; counter < CALC_BUFFER_SIZE; counter++) {
1304 if (val[counter] == SC_0) low += 4;
1306 if (val[counter] < SC_2) return low;
1307 else if (val[counter] < SC_4) return low + 1;
1308 else if (val[counter] < SC_8) return low + 2;
1309 else return low + 3;
1315 int sc_is_zero(const void *value)
1317 const char* val = (const char *)value;
1320 for (counter = 0; counter < CALC_BUFFER_SIZE; counter++) {
1321 if (val[counter] != SC_0) return 0;
1326 int sc_is_negative(const void *value)
1328 return _sign(value) == -1;
1331 int sc_had_carry(void)
1336 unsigned char sc_sub_bits(const void *value, int len, unsigned byte_ofs)
1338 const char *val = (const char *)value;
1339 unsigned nibble_ofs = 2 * byte_ofs;
1342 /* the current scheme uses one byte to store a nibble */
1343 if (nibble_ofs >= len)
1346 res = _val(val[nibble_ofs]);
1347 if (len > nibble_ofs + 1)
1348 res |= _val(val[nibble_ofs + 1]) << 4;
1354 * convert to a string
1355 * XXX Doesn't check buffer bounds
1357 const char *sc_print(const void *value, unsigned bits, enum base_t base)
1359 static const char big_digits[] = "0123456789ABCDEF";
1360 static const char small_digits[] = "0123456789abcdef";
1362 char *base_val, *div1_res, *div2_res, *rem_res;
1363 int counter, nibbles, i, sign;
1366 const char *val = (const char *)value;
1370 const char *digits = small_digits;
1372 base_val = alloca(CALC_BUFFER_SIZE);
1373 div1_res = alloca(CALC_BUFFER_SIZE);
1374 div2_res = alloca(CALC_BUFFER_SIZE);
1375 rem_res = alloca(CALC_BUFFER_SIZE);
1377 pos = output_buffer + BIT_PATTERN_SIZE;
1382 bits = BIT_PATTERN_SIZE;
1383 #ifdef STRCALC_DEBUG_FULLPRINT
1387 nibbles = bits >> 2;
1391 digits = big_digits;
1393 for (counter = 0; counter < nibbles; ++counter) {
1394 *(--pos) = digits[_val(val[counter])];
1395 #ifdef STRCALC_DEBUG_GROUPPRINT
1396 if ((counter+1)%8 == 0)
1401 /* last nibble must be masked */
1403 x = and_table[_val(val[++counter])][bits & 3];
1404 *(--pos) = digits[_val(x)];
1407 /* now kill zeros */
1408 for (; counter > 1; --counter, ++pos) {
1409 #ifdef STRCALC_DEBUG_GROUPPRINT
1410 if (pos[0] == ' ') ++pos;
1418 for (counter = 0; counter < nibbles; ++counter) {
1420 p = binary_table[_val(val[counter])];
1427 /* last nibble must be masked */
1429 x = and_table[_val(val[++counter])][bits & 3];
1432 p = binary_table[_val(x)];
1439 /* now kill zeros */
1440 for (counter <<= 2; counter > 1; --counter, ++pos)
1447 memset(base_val, SC_0, CALC_BUFFER_SIZE);
1448 base_val[0] = base == SC_DEC ? SC_A : SC_8;
1452 if (base == SC_DEC) {
1453 /* check for negative values */
1454 if (_bit(val, bits - 1)) {
1455 _negate(val, div2_res);
1461 /* transfer data into oscilating buffers */
1462 memset(div1_res, SC_0, CALC_BUFFER_SIZE);
1463 for (counter = 0; counter < nibbles; ++counter)
1464 div1_res[counter] = p[counter];
1466 /* last nibble must be masked */
1470 div1_res[counter] = and_table[_val(p[counter])][bits & 3];
1476 _divmod(m, base_val, n, rem_res);
1480 *(--pos) = digits[_val(rem_res[0])];
1483 for (i = 0; i < sizeof(div1_res); ++i)
1494 printf("%i\n", base);
1501 void init_strcalc(int precision)
1503 if (calc_buffer == NULL) {
1504 if (precision <= 0) precision = SC_DEFAULT_PRECISION;
1506 /* round up to multiple of 4 */
1507 if (precision & 0x3) precision += 4 - (precision&0x3);
1509 BIT_PATTERN_SIZE = (precision);
1510 CALC_BUFFER_SIZE = (precision / 2);
1511 MAX_VALUE_SIZE = (precision / 4);
1513 calc_buffer = malloc(CALC_BUFFER_SIZE+1 * sizeof(char));
1514 output_buffer = malloc(BIT_PATTERN_SIZE+1 * sizeof(char));
1516 if (calc_buffer == NULL || output_buffer == NULL)
1518 assert(0 && "malloc failed");
1522 DEBUGPRINTF(("init strcalc: \n\tPRECISION: %d\n\tCALC_BUFFER_SIZE = %d\n\tMAX_VALUE_SIZE = %d\n\tbuffer pointer: %p\n", precision, CALC_BUFFER_SIZE, MAX_VALUE_SIZE, calc_buffer));
1525 int sc_get_precision(void)
1527 return BIT_PATTERN_SIZE;