1 /****i* strcalc/implementation
12 #include <assert.h> /* assertions */
13 #include <string.h> /* memset/memcmp */
14 #include <stdio.h> /* output for error messages */
15 #include <limits.h> /* definition of LONG_MIN, used in sc_get_val_from_long */
18 * local definitions and macros
20 #define CLEAR_BUFFER(b) assert(b); memset(b, SC_0, CALC_BUFFER_SIZE)
21 #define _val(a) ((a)-SC_0)
22 #define _digit(a) ((a)+SC_0)
23 #define _bitisset(digit, pos) (and_table[_val(digit)][_val(shift_table[pos])] != SC_0)
25 #define fail_char(a, b, c, d) _fail_char((a), (b), (c), (d), __FILE__, __LINE__)
27 /* shortcut output for debugging */
28 # define sc_print_hex(a) sc_print((a), 0, SC_HEX)
29 # define sc_print_dec(a) sc_print((a), 0, SC_DEC)
30 # define sc_print_oct(a) sc_print((a), 0, SC_OCT)
31 # define sc_print_bin(a) sc_print((a), 0, SC_BIN)
33 #ifdef STRCALC_DEBUG_PRINTCOMP
34 # define DEBUGPRINTF_COMPUTATION(x) printf x
36 # define DEBUGPRINTF_COMPUTATION(x) ((void)0)
39 # define DEBUGPRINTF(x) printf x
41 # define DEBUGPRINTF(x) ((void)0)
49 static char *calc_buffer = NULL; /* buffer holding all results */
50 static char *output_buffer = NULL; /* buffer for output */
51 static int BIT_PATTERN_SIZE; /* maximum number of bits */
52 static int CALC_BUFFER_SIZE; /* size of internally stored values */
53 static int MAX_VALUE_SIZE; /* maximum size of values */
55 static int carry_flag; /* some computation set carry_flag: */
56 /* rightshift if bits were lost due to shifting */
57 /* division if there was a remainder */
59 static const char max_digit[4] = { SC_0, SC_1, SC_3, SC_7 };
60 static const char min_digit[4] = { SC_F, SC_E, SC_C, SC_8 };
62 static const char not_table[16] = { SC_F, SC_E, SC_D, SC_C, SC_B, SC_A, SC_9, SC_8,
63 SC_7, SC_6, SC_5, SC_4, SC_3, SC_2, SC_1, SC_0 };
65 static const char shift_table[4] = { SC_1, SC_2, SC_4, SC_8 };
67 static const char and_table[16][16] = {
68 { SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0,
69 SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0 },
71 { SC_0, SC_1, SC_0, SC_1, SC_0, SC_1, SC_0, SC_1,
72 SC_0, SC_1, SC_0, SC_1, SC_0, SC_1, SC_0, SC_1 },
74 { SC_0, SC_0, SC_2, SC_2, SC_0, SC_0, SC_2, SC_2,
75 SC_0, SC_0, SC_2, SC_2, SC_0, SC_0, SC_2, SC_2 },
77 { SC_0, SC_1, SC_2, SC_3, SC_0, SC_1, SC_2, SC_3,
78 SC_0, SC_1, SC_2, SC_3, SC_0, SC_1, SC_2, SC_3 },
80 { SC_0, SC_0, SC_0, SC_0, SC_4, SC_4, SC_4, SC_4,
81 SC_0, SC_0, SC_0, SC_0, SC_4, SC_4, SC_4, SC_4 },
83 { SC_0, SC_1, SC_0, SC_1, SC_4, SC_5, SC_4, SC_5,
84 SC_0, SC_1, SC_0, SC_1, SC_4, SC_5, SC_4, SC_5 },
86 { SC_0, SC_0, SC_2, SC_2, SC_4, SC_4, SC_6, SC_6,
87 SC_0, SC_0, SC_2, SC_2, SC_4, SC_4, SC_6, SC_6 },
89 { SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7,
90 SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7 },
92 { SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0, SC_0,
93 SC_8, SC_8, SC_8, SC_8, SC_8, SC_8, SC_8, SC_8 },
95 { SC_0, SC_1, SC_0, SC_1, SC_0, SC_1, SC_0, SC_1,
96 SC_8, SC_9, SC_8, SC_9, SC_8, SC_9, SC_8, SC_9 },
98 { SC_0, SC_0, SC_2, SC_2, SC_0, SC_0, SC_2, SC_2,
99 SC_8, SC_8, SC_A, SC_A, SC_8, SC_8, SC_A, SC_A },
101 { SC_0, SC_1, SC_2, SC_3, SC_0, SC_1, SC_2, SC_3,
102 SC_8, SC_9, SC_A, SC_B, SC_8, SC_9, SC_A, SC_B },
104 { SC_0, SC_0, SC_0, SC_0, SC_4, SC_4, SC_4, SC_4,
105 SC_8, SC_8, SC_8, SC_8, SC_C, SC_C, SC_C, SC_C },
107 { SC_0, SC_1, SC_0, SC_1, SC_4, SC_5, SC_4, SC_5,
108 SC_8, SC_9, SC_8, SC_9, SC_C, SC_D, SC_C, SC_D },
110 { SC_0, SC_0, SC_2, SC_2, SC_4, SC_4, SC_6, SC_6,
111 SC_8, SC_8, SC_A, SC_A, SC_C, SC_C, SC_E, SC_E },
113 { SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7,
114 SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F } };
116 static const char or_table[16][16] = {
117 { SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7,
118 SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F },
120 { SC_1, SC_1, SC_3, SC_3, SC_5, SC_5, SC_7, SC_7,
121 SC_9, SC_9, SC_B, SC_B, SC_D, SC_D, SC_F, SC_F },
123 { SC_2, SC_3, SC_2, SC_3, SC_6, SC_7, SC_6, SC_7,
124 SC_A, SC_B, SC_A, SC_B, SC_E, SC_F, SC_E, SC_F },
126 { SC_3, SC_3, SC_3, SC_3, SC_7, SC_7, SC_7, SC_7,
127 SC_B, SC_B, SC_B, SC_B, SC_F, SC_F, SC_F, SC_F },
129 { SC_4, SC_5, SC_6, SC_7, SC_4, SC_5, SC_6, SC_7,
130 SC_C, SC_D, SC_E, SC_F, SC_C, SC_D, SC_E, SC_F },
132 { SC_5, SC_5, SC_7, SC_7, SC_5, SC_5, SC_7, SC_7,
133 SC_D, SC_D, SC_F, SC_F, SC_D, SC_D, SC_F, SC_F },
135 { SC_6, SC_7, SC_6, SC_7, SC_6, SC_7, SC_6, SC_7,
136 SC_E, SC_F, SC_E, SC_F, SC_E, SC_F, SC_E, SC_F },
138 { SC_7, SC_7, SC_7, SC_7, SC_7, SC_7, SC_7, SC_7,
139 SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F },
141 { SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F,
142 SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F },
144 { SC_9, SC_9, SC_B, SC_B, SC_D, SC_D, SC_F, SC_F,
145 SC_9, SC_9, SC_B, SC_B, SC_D, SC_D, SC_F, SC_F },
147 { SC_A, SC_B, SC_A, SC_B, SC_E, SC_F, SC_E, SC_F,
148 SC_A, SC_B, SC_A, SC_B, SC_E, SC_F, SC_E, SC_F },
150 { SC_B, SC_B, SC_B, SC_B, SC_F, SC_F, SC_F, SC_F,
151 SC_B, SC_B, SC_B, SC_B, SC_F, SC_F, SC_F, SC_F },
153 { SC_C, SC_D, SC_E, SC_F, SC_C, SC_D, SC_E, SC_F,
154 SC_C, SC_D, SC_E, SC_F, SC_C, SC_D, SC_E, SC_F },
156 { SC_D, SC_D, SC_F, SC_F, SC_D, SC_D, SC_F, SC_F,
157 SC_D, SC_D, SC_F, SC_F, SC_D, SC_D, SC_F, SC_F },
159 { SC_E, SC_F, SC_E, SC_F, SC_E, SC_F, SC_E, SC_F,
160 SC_E, SC_F, SC_E, SC_F, SC_E, SC_F, SC_E, SC_F },
162 { SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F,
163 SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F, SC_F } };
165 static char const xor_table[16][16] = {
166 { SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7,
167 SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F },
169 { SC_1, SC_0, SC_3, SC_2, SC_5, SC_4, SC_7, SC_6,
170 SC_9, SC_8, SC_B, SC_A, SC_D, SC_C, SC_F, SC_E },
172 { SC_2, SC_3, SC_0, SC_1, SC_6, SC_7, SC_4, SC_5,
173 SC_A, SC_B, SC_8, SC_9, SC_E, SC_F, SC_C, SC_D },
175 { SC_3, SC_2, SC_1, SC_0, SC_7, SC_6, SC_5, SC_4,
176 SC_B, SC_A, SC_9, SC_8, SC_F, SC_E, SC_D, SC_C },
178 { SC_4, SC_5, SC_6, SC_7, SC_0, SC_1, SC_2, SC_3,
179 SC_C, SC_D, SC_E, SC_F, SC_8, SC_9, SC_A, SC_B },
181 { SC_5, SC_4, SC_7, SC_6, SC_1, SC_0, SC_3, SC_2,
182 SC_D, SC_C, SC_F, SC_E, SC_9, SC_8, SC_B, SC_A },
184 { SC_6, SC_7, SC_4, SC_5, SC_2, SC_3, SC_0, SC_1,
185 SC_E, SC_F, SC_C, SC_D, SC_A, SC_B, SC_8, SC_9 },
187 { SC_7, SC_6, SC_5, SC_4, SC_3, SC_2, SC_1, SC_0,
188 SC_F, SC_E, SC_D, SC_C, SC_B, SC_A, SC_9, SC_8 },
190 { SC_8, SC_9, SC_A, SC_B, SC_C, SC_D, SC_E, SC_F,
191 SC_0, SC_1, SC_2, SC_3, SC_4, SC_5, SC_6, SC_7 },
193 { SC_9, SC_8, SC_B, SC_A, SC_D, SC_C, SC_F, SC_E,
194 SC_1, SC_0, SC_3, SC_2, SC_5, SC_4, SC_7, SC_6 },
196 { SC_A, SC_B, SC_8, SC_9, SC_E, SC_F, SC_C, SC_D,
197 SC_2, SC_3, SC_0, SC_1, SC_6, SC_7, SC_4, SC_5 },
199 { SC_B, SC_A, SC_9, SC_8, SC_F, SC_E, SC_D, SC_C,
200 SC_3, SC_2, SC_1, SC_0, SC_7, SC_6, SC_5, SC_4 },
202 { SC_C, SC_D, SC_E, SC_F, SC_8, SC_9, SC_A, SC_B,
203 SC_4, SC_5, SC_6, SC_7, SC_0, SC_1, SC_2, SC_3 },
205 { SC_D, SC_C, SC_F, SC_E, SC_9, SC_8, SC_B, SC_A,
206 SC_5, SC_4, SC_7, SC_6, SC_1, SC_0, SC_3, SC_2 },
208 { SC_E, SC_F, SC_C, SC_D, SC_A, SC_B, SC_8, SC_9,
209 SC_6, SC_7, SC_4, SC_5, SC_2, SC_3, SC_0, SC_1 },
211 { SC_F, SC_E, SC_D, SC_C, SC_B, SC_A, SC_9, SC_8,
212 SC_7, SC_6, SC_5, SC_4, SC_3, SC_2, SC_1, SC_0 }
215 static char const add_table[16][16][2] = {
216 { {SC_0, SC_0}, {SC_1, SC_0}, {SC_2, SC_0}, {SC_3, SC_0},
217 {SC_4, SC_0}, {SC_5, SC_0}, {SC_6, SC_0}, {SC_7, SC_0},
218 {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0},
219 {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0} },
221 { {SC_1, SC_0}, {SC_2, SC_0}, {SC_3, SC_0}, {SC_4, SC_0},
222 {SC_5, SC_0}, {SC_6, SC_0}, {SC_7, SC_0}, {SC_8, SC_0},
223 {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0},
224 {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1} },
226 { {SC_2, SC_0}, {SC_3, SC_0}, {SC_4, SC_0}, {SC_5, SC_0},
227 {SC_6, SC_0}, {SC_7, SC_0}, {SC_8, SC_0}, {SC_9, SC_0},
228 {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0},
229 {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1} },
231 { {SC_3, SC_0}, {SC_4, SC_0}, {SC_5, SC_0}, {SC_6, SC_0},
232 {SC_7, SC_0}, {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0},
233 {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0},
234 {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1} },
236 { {SC_4, SC_0}, {SC_5, SC_0}, {SC_6, SC_0}, {SC_7, SC_0},
237 {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0},
238 {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0},
239 {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1} },
241 { {SC_5, SC_0}, {SC_6, SC_0}, {SC_7, SC_0}, {SC_8, SC_0},
242 {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0},
243 {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1},
244 {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1} },
246 { {SC_6, SC_0}, {SC_7, SC_0}, {SC_8, SC_0}, {SC_9, SC_0},
247 {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0},
248 {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1},
249 {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1} },
251 { {SC_7, SC_0}, {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0},
252 {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0},
253 {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1},
254 {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1}, {SC_6, SC_1} },
256 { {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0},
257 {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0},
258 {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1},
259 {SC_4, SC_1}, {SC_5, SC_1}, {SC_6, SC_1}, {SC_7, SC_1} },
261 { {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0},
262 {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1},
263 {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1},
264 {SC_5, SC_1}, {SC_6, SC_1}, {SC_7, SC_1}, {SC_8, SC_1} },
266 { {SC_A, SC_0}, {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0},
267 {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1},
268 {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1},
269 {SC_6, SC_1}, {SC_7, SC_1}, {SC_8, SC_1}, {SC_9, SC_1} },
271 { {SC_B, SC_0}, {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0},
272 {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1},
273 {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1}, {SC_6, SC_1},
274 {SC_7, SC_1}, {SC_8, SC_1}, {SC_9, SC_1}, {SC_A, SC_1} },
276 { {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0},
277 {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1},
278 {SC_4, SC_1}, {SC_5, SC_1}, {SC_6, SC_1}, {SC_7, SC_1},
279 {SC_8, SC_1}, {SC_9, SC_1}, {SC_A, SC_1}, {SC_B, SC_1} },
281 { {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1},
282 {SC_1, SC_1}, {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1},
283 {SC_5, SC_1}, {SC_6, SC_1}, {SC_7, SC_1}, {SC_8, SC_1},
284 {SC_9, SC_1}, {SC_A, SC_1}, {SC_B, SC_1}, {SC_C, SC_1} },
286 { {SC_E, SC_0}, {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1},
287 {SC_2, SC_1}, {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1},
288 {SC_6, SC_1}, {SC_7, SC_1}, {SC_8, SC_1}, {SC_9, SC_1},
289 {SC_A, SC_1}, {SC_B, SC_1}, {SC_C, SC_1}, {SC_D, SC_1} },
291 { {SC_F, SC_0}, {SC_0, SC_1}, {SC_1, SC_1}, {SC_2, SC_1},
292 {SC_3, SC_1}, {SC_4, SC_1}, {SC_5, SC_1}, {SC_6, SC_1},
293 {SC_7, SC_1}, {SC_8, SC_1}, {SC_9, SC_1}, {SC_A, SC_1},
294 {SC_B, SC_1}, {SC_C, SC_1}, {SC_D, SC_1}, {SC_E, SC_1} }
297 static char const mul_table[16][16][2] = {
298 { {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0},
299 {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0},
300 {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0},
301 {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0} },
303 { {SC_0, SC_0}, {SC_1, SC_0}, {SC_2, SC_0}, {SC_3, SC_0},
304 {SC_4, SC_0}, {SC_5, SC_0}, {SC_6, SC_0}, {SC_7, SC_0},
305 {SC_8, SC_0}, {SC_9, SC_0}, {SC_A, SC_0}, {SC_B, SC_0},
306 {SC_C, SC_0}, {SC_D, SC_0}, {SC_E, SC_0}, {SC_F, SC_0} },
308 { {SC_0, SC_0}, {SC_2, SC_0}, {SC_4, SC_0}, {SC_6, SC_0},
309 {SC_8, SC_0}, {SC_A, SC_0}, {SC_C, SC_0}, {SC_E, SC_0},
310 {SC_0, SC_1}, {SC_2, SC_1}, {SC_4, SC_1}, {SC_6, SC_1},
311 {SC_8, SC_1}, {SC_A, SC_1}, {SC_C, SC_1}, {SC_E, SC_1} },
313 { {SC_0, SC_0}, {SC_3, SC_0}, {SC_6, SC_0}, {SC_9, SC_0},
314 {SC_C, SC_0}, {SC_F, SC_0}, {SC_2, SC_1}, {SC_5, SC_1},
315 {SC_8, SC_1}, {SC_B, SC_1}, {SC_E, SC_1}, {SC_1, SC_2},
316 {SC_4, SC_2}, {SC_7, SC_2}, {SC_A, SC_2}, {SC_D, SC_2} },
318 { {SC_0, SC_0}, {SC_4, SC_0}, {SC_8, SC_0}, {SC_C, SC_0},
319 {SC_0, SC_1}, {SC_4, SC_1}, {SC_8, SC_1}, {SC_C, SC_1},
320 {SC_0, SC_2}, {SC_4, SC_2}, {SC_8, SC_2}, {SC_C, SC_2},
321 {SC_0, SC_3}, {SC_4, SC_3}, {SC_8, SC_3}, {SC_C, SC_3} },
323 { {SC_0, SC_0}, {SC_5, SC_0}, {SC_A, SC_0}, {SC_F, SC_0},
324 {SC_4, SC_1}, {SC_9, SC_1}, {SC_E, SC_1}, {SC_3, SC_2},
325 {SC_8, SC_2}, {SC_D, SC_2}, {SC_2, SC_3}, {SC_7, SC_3},
326 {SC_C, SC_3}, {SC_1, SC_4}, {SC_6, SC_4}, {SC_B, SC_4} },
328 { {SC_0, SC_0}, {SC_6, SC_0}, {SC_C, SC_0}, {SC_2, SC_1},
329 {SC_8, SC_1}, {SC_E, SC_1}, {SC_4, SC_2}, {SC_A, SC_2},
330 {SC_0, SC_3}, {SC_6, SC_3}, {SC_C, SC_3}, {SC_2, SC_4},
331 {SC_8, SC_4}, {SC_E, SC_4}, {SC_4, SC_5}, {SC_A, SC_5} },
333 { {SC_0, SC_0}, {SC_7, SC_0}, {SC_E, SC_0}, {SC_5, SC_1},
334 {SC_C, SC_1}, {SC_3, SC_2}, {SC_A, SC_2}, {SC_1, SC_3},
335 {SC_8, SC_3}, {SC_F, SC_3}, {SC_6, SC_4}, {SC_D, SC_4},
336 {SC_4, SC_5}, {SC_B, SC_5}, {SC_2, SC_6}, {SC_9, SC_6} },
338 { {SC_0, SC_0}, {SC_8, SC_0}, {SC_0, SC_1}, {SC_8, SC_1},
339 {SC_0, SC_2}, {SC_8, SC_2}, {SC_0, SC_3}, {SC_8, SC_3},
340 {SC_0, SC_4}, {SC_8, SC_4}, {SC_0, SC_5}, {SC_8, SC_5},
341 {SC_0, SC_6}, {SC_8, SC_6}, {SC_0, SC_7}, {SC_8, SC_7} },
343 { {SC_0, SC_0}, {SC_9, SC_0}, {SC_2, SC_1}, {SC_B, SC_1},
344 {SC_4, SC_2}, {SC_D, SC_2}, {SC_6, SC_3}, {SC_F, SC_3},
345 {SC_8, SC_4}, {SC_1, SC_5}, {SC_A, SC_5}, {SC_3, SC_6},
346 {SC_C, SC_6}, {SC_5, SC_7}, {SC_E, SC_7}, {SC_7, SC_8} },
348 { {SC_0, SC_0}, {SC_A, SC_0}, {SC_4, SC_1}, {SC_E, SC_1},
349 {SC_8, SC_2}, {SC_2, SC_3}, {SC_C, SC_3}, {SC_6, SC_4},
350 {SC_0, SC_5}, {SC_A, SC_5}, {SC_4, SC_6}, {SC_E, SC_6},
351 {SC_8, SC_7}, {SC_2, SC_8}, {SC_C, SC_8}, {SC_6, SC_9} },
353 { {SC_0, SC_0}, {SC_B, SC_0}, {SC_6, SC_1}, {SC_1, SC_2},
354 {SC_C, SC_2}, {SC_7, SC_3}, {SC_2, SC_4}, {SC_D, SC_4},
355 {SC_8, SC_5}, {SC_3, SC_6}, {SC_E, SC_6}, {SC_9, SC_7},
356 {SC_4, SC_8}, {SC_F, SC_8}, {SC_A, SC_9}, {SC_5, SC_A} },
358 { {SC_0, SC_0}, {SC_C, SC_0}, {SC_8, SC_1}, {SC_4, SC_2},
359 {SC_0, SC_3}, {SC_C, SC_3}, {SC_8, SC_4}, {SC_4, SC_5},
360 {SC_0, SC_6}, {SC_C, SC_6}, {SC_8, SC_7}, {SC_4, SC_8},
361 {SC_0, SC_9}, {SC_C, SC_9}, {SC_8, SC_A}, {SC_4, SC_B} },
363 { {SC_0, SC_0}, {SC_D, SC_0}, {SC_A, SC_1}, {SC_7, SC_2},
364 {SC_4, SC_3}, {SC_1, SC_4}, {SC_E, SC_4}, {SC_B, SC_5},
365 {SC_8, SC_6}, {SC_5, SC_7}, {SC_2, SC_8}, {SC_F, SC_8},
366 {SC_C, SC_9}, {SC_9, SC_A}, {SC_6, SC_B}, {SC_3, SC_C} },
368 { {SC_0, SC_0}, {SC_E, SC_0}, {SC_C, SC_1}, {SC_A, SC_2},
369 {SC_8, SC_3}, {SC_6, SC_4}, {SC_4, SC_5}, {SC_2, SC_6},
370 {SC_0, SC_7}, {SC_E, SC_7}, {SC_C, SC_8}, {SC_A, SC_9},
371 {SC_8, SC_A}, {SC_6, SC_B}, {SC_4, SC_C}, {SC_2, SC_D} },
373 { {SC_0, SC_0}, {SC_F, SC_0}, {SC_E, SC_1}, {SC_D, SC_2},
374 {SC_C, SC_3}, {SC_B, SC_4}, {SC_A, SC_5}, {SC_9, SC_6},
375 {SC_8, SC_7}, {SC_7, SC_8}, {SC_6, SC_9}, {SC_5, SC_A},
376 {SC_4, SC_B}, {SC_3, SC_C}, {SC_2, SC_D}, {SC_1, SC_E} }
379 static char const shrs_table[16][4][2] = {
380 { {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0} },
381 { {SC_1, SC_0}, {SC_0, SC_8}, {SC_0, SC_4}, {SC_0, SC_2} },
382 { {SC_2, SC_0}, {SC_1, SC_0}, {SC_0, SC_8}, {SC_0, SC_4} },
383 { {SC_3, SC_0}, {SC_1, SC_8}, {SC_0, SC_C}, {SC_0, SC_6} },
384 { {SC_4, SC_0}, {SC_2, SC_0}, {SC_1, SC_0}, {SC_0, SC_8} },
385 { {SC_5, SC_0}, {SC_2, SC_8}, {SC_1, SC_4}, {SC_0, SC_A} },
386 { {SC_6, SC_0}, {SC_3, SC_0}, {SC_1, SC_8}, {SC_0, SC_C} },
387 { {SC_7, SC_0}, {SC_3, SC_8}, {SC_1, SC_C}, {SC_0, SC_E} },
388 { {SC_8, SC_0}, {SC_4, SC_0}, {SC_2, SC_0}, {SC_1, SC_0} },
389 { {SC_9, SC_0}, {SC_4, SC_8}, {SC_2, SC_4}, {SC_1, SC_2} },
390 { {SC_A, SC_0}, {SC_5, SC_0}, {SC_2, SC_8}, {SC_1, SC_4} },
391 { {SC_B, SC_0}, {SC_5, SC_8}, {SC_2, SC_C}, {SC_1, SC_6} },
392 { {SC_C, SC_0}, {SC_6, SC_0}, {SC_3, SC_0}, {SC_1, SC_8} },
393 { {SC_D, SC_0}, {SC_6, SC_8}, {SC_3, SC_4}, {SC_1, SC_A} },
394 { {SC_E, SC_0}, {SC_7, SC_0}, {SC_3, SC_8}, {SC_1, SC_C} },
395 { {SC_F, SC_0}, {SC_7, SC_8}, {SC_3, SC_C}, {SC_1, SC_E} }
398 /* for converting to binary string */
399 static const char *binary_table[16] = {
400 "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
401 "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
404 /*****************************************************************************
406 *****************************************************************************/
407 static void _fail_char(const char *str, size_t len, const char fchar, int pos,
408 const char *file, int line)
411 printf("Unexpected character '%c' in %s:%d\n", fchar, file, line);
412 while (len-- && *str) printf("%c", *str++); printf("\n");
413 while (--pos) printf(" "); printf("^\n");
417 static void _bitnot(const char *val, char *buffer)
421 for (counter = 0; counter<CALC_BUFFER_SIZE; counter++)
422 buffer[counter] = not_table[_val(val[counter])];
425 static void _bitor(const char *val1, const char *val2, char *buffer)
429 for (counter = 0; counter<CALC_BUFFER_SIZE; counter++)
430 buffer[counter] = or_table[_val(val1[counter])][_val(val2[counter])];
433 static void _bitxor(const char *val1, const char *val2, char *buffer)
437 for (counter = 0; counter<CALC_BUFFER_SIZE; counter++)
438 buffer[counter] = xor_table[_val(val1[counter])][_val(val2[counter])];
441 static void _bitand(const char *val1, const char *val2, char *buffer)
445 for (counter = 0; counter<CALC_BUFFER_SIZE; counter++)
446 buffer[counter] = and_table[_val(val1[counter])][_val(val2[counter])];
449 static int _sign(const char *val)
451 return (val[CALC_BUFFER_SIZE-1] <= SC_7) ? (1) : (-1);
455 * returns non-zero if bit at position pos is set
457 static int _bit(const char *val, int pos)
460 int nibble = pos >> 2;
462 return _bitisset(val[nibble], bit);
465 static void _inc(char *val, char *buffer)
469 while (counter++ < CALC_BUFFER_SIZE)
478 /* No carry here, *val != SC_F */
479 *buffer = add_table[_val(*val)][SC_1][0];
483 /* here a carry could be lost, this is intended because this should
484 * happen only when a value changes sign. */
487 static void _negate(const char *val, char *buffer)
489 _bitnot(val, buffer);
490 _inc(buffer, buffer);
493 static void _add(const char *val1, const char *val2, char *buffer)
496 const char *add1, *add2;
499 for (counter = 0; counter < CALC_BUFFER_SIZE; counter++)
501 add1 = add_table[_val(val1[counter])][_val(val2[counter])];
502 add2 = add_table[_val(add1[0])][_val(carry)];
503 /* carry might be zero */
504 buffer[counter] = add2[0];
505 carry = add_table[_val(add1[1])][_val(add2[1])][0];
509 static void _mul(const char *val1, const char *val2, char *buffer)
511 char temp_buffer[CALC_BUFFER_SIZE]; /* result buffer */
512 char neg_val1[CALC_BUFFER_SIZE]; /* abs of val1 */
513 char neg_val2[CALC_BUFFER_SIZE]; /* abs of val2 */
515 const char *mul, *add1, *add2; /* intermediate result containers */
516 char carry = SC_0; /* container for carries */
517 char sign = 0; /* marks result sign */
518 int c_inner, c_outer; /* loop counters */
520 /* init result buffer to zeroes */
521 memset(temp_buffer, SC_0, CALC_BUFFER_SIZE);
523 /* the multiplication works only for positive values, for negative values *
524 * it is necessary to negate them and adjust the result accordingly */
525 if (_sign(val1) == -1) {
526 _negate(val1, neg_val1);
530 if (_sign(val2) == -1) {
531 _negate(val2, neg_val2);
536 for (c_outer = 0; c_outer < MAX_VALUE_SIZE; c_outer++)
538 if (val2[c_outer] != SC_0)
540 for (c_inner = 0; c_inner < MAX_VALUE_SIZE; c_inner++)
542 /* do the following calculation: *
543 * Add the current carry, the value at position c_outer+c_inner *
544 * and the result of the multiplication of val1[c_inner] and *
545 * val2[c_outer]. This is the usual pen-and-paper multiplication. */
547 /* multiplicate the two digits */
548 mul = mul_table[_val(val1[c_inner])][_val(val2[c_outer])];
549 /* add old value to result of multiplication */
550 add1 = add_table[_val(temp_buffer[c_inner + c_outer])][_val(mul[0])];
551 /* add carry to the sum */
552 add2 = add_table[_val(add1[0])][_val(carry)];
554 /* all carries together result in new carry. This is always smaller *
556 * Both multiplicands, the carry and the value already in the temp *
557 * buffer are single digits and their value is therefore at most *
560 * (b-1)(b-1)+(b-1)+(b-1) = b*b-1 *
561 * The tables list all operations rem b, so the carry is at most *
562 * (b*b-1)rem b = -1rem b = b-1 */
563 carry = add_table[_val(mul[1])][_val(add1[1])][0];
564 carry = add_table[_val(carry)][_val(add2[1])][0];
566 temp_buffer[c_inner + c_outer] = add2[0];
569 /* A carry may hang over */
570 /* c_outer is always smaller than MAX_VALUE_SIZE! */
571 temp_buffer[MAX_VALUE_SIZE + c_outer] = carry;
577 _negate(temp_buffer, buffer);
579 memcpy(buffer, temp_buffer, CALC_BUFFER_SIZE);
582 static void _sub(const char *val1, const char *val2, char *buffer)
584 char temp_buffer[CALC_BUFFER_SIZE]; /* intermediate buffer to hold -val2 */
586 _negate(val2, temp_buffer);
587 _add(val1, temp_buffer, buffer);
590 static void _push(const char digit, char *buffer)
594 for (counter = CALC_BUFFER_SIZE - 2; counter >= 0; counter--)
596 buffer[counter+1] = buffer[counter];
601 /* XXX: This is MOST slow */
602 static void _divmod(const char *dividend, const char *divisor, char *quot, char *rem)
604 const char *minus_divisor;
605 char neg_val1[CALC_BUFFER_SIZE];
606 char neg_val2[CALC_BUFFER_SIZE];
608 char sign = 0; /* remember result sign */
610 int c_dividend; /* loop counters */
612 /* clear result buffer */
613 memset(quot, SC_0, CALC_BUFFER_SIZE);
614 memset(rem, SC_0, CALC_BUFFER_SIZE);
616 /* if the divisor is zero this won't work (quot is zero) */
617 if (sc_comp(divisor, quot) == 0) assert(0 && "division by zero!");
619 /* if the dividend is zero result is zero (quot is zero)*/
620 if (sc_comp(dividend, quot) == 0)
623 if (_sign(dividend) == -1)
625 _negate(dividend, neg_val1);
630 _negate(divisor, neg_val2);
631 if (_sign(divisor) == -1)
634 minus_divisor = divisor;
639 minus_divisor = neg_val2;
642 /* if divisor >= dividend division is easy
643 * (remember these are absolute values) */
644 switch (sc_comp(dividend, divisor))
646 case 0: /* dividend == divisor */
650 case -1: /* dividend < divisor */
651 memcpy(rem, dividend, CALC_BUFFER_SIZE);
654 default: /* unluckily division is necessary :( */
658 for (c_dividend = CALC_BUFFER_SIZE - 1; c_dividend >= 0; c_dividend--)
660 _push(dividend[c_dividend], rem);
663 if (sc_comp(rem, divisor) != -1) /* remainder >= divisor */
665 /* subtract until the remainder becomes negative, this should
666 * be faster than comparing remainder with divisor */
667 _add(rem, minus_divisor, rem);
669 while (_sign(rem) == 1)
671 quot[0] = add_table[_val(quot[0])][SC_1][0];
672 _add(rem, minus_divisor, rem);
675 /* subtracted one too much */
676 _add(rem, divisor, rem);
680 carry_flag = !sc_is_zero(rem);
689 static void _shl(const char *val1, char *buffer, long offset, int radius, unsigned is_signed)
698 assert((offset >= 0) || (0 && "negative leftshift"));
699 assert(((_sign(val1) != -1) || is_signed) || (0 && "unsigned mode and negative value"));
700 assert(((!_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == -1)) || (0 && "value is positive, should be negative"));
701 assert(((_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == 1)) || (0 && "value is negative, should be positive"));
703 /* if shifting far enough the result is zero */
704 if (offset >= radius)
706 memset(buffer, SC_0, CALC_BUFFER_SIZE);
710 shift = shift_table[_val(offset%4)]; /* this is 2 ** (offset % 4) */
713 /* shift the single digits some bytes (offset) and some bits (table)
715 for (counter = 0; counter < radius/4 - offset; counter++)
717 shl = mul_table[_val(val1[counter])][_val(shift)];
718 buffer[counter + offset] = or_table[_val(shl[0])][_val(carry)];
723 shl = mul_table[_val(val1[counter])][_val(shift)];
724 buffer[counter + offset] = or_table[_val(shl[0])][_val(carry)];
727 bitoffset = counter - 1;
730 /* fill with zeroes */
731 for (counter = 0; counter < offset; counter++) buffer[counter] = SC_0;
733 /* if the mode was signed, change sign when the mode's msb is now 1 */
734 offset = bitoffset + offset;
735 bitoffset = (radius-1) % 4;
736 if (is_signed && _bitisset(buffer[offset], bitoffset))
738 /* this sets the upper bits of the leftmost digit */
739 buffer[offset] = or_table[_val(buffer[offset])][_val(min_digit[bitoffset])];
740 for (counter = offset+1; counter < CALC_BUFFER_SIZE; counter++)
742 buffer[counter] = SC_F;
745 else if (is_signed && !_bitisset(buffer[offset], bitoffset))
747 /* this unsets the upper bits of the leftmost digit */
748 buffer[offset] = and_table[_val(buffer[offset])][_val(max_digit[bitoffset])];
749 for (counter = offset+1; counter < CALC_BUFFER_SIZE; counter++)
751 buffer[counter] = SC_0;
756 static void _shr(const char *val1, char *buffer, long offset, int radius, unsigned is_signed, int signed_shift)
767 assert((offset >= 0) || (0 && "negative rightshift"));
768 assert(((_sign(val1) != -1) || is_signed) || (0 && "unsigned mode and negative value"));
769 assert(((!_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == -1)) || (0 && "value is positive, should be negative"));
770 assert(((_bitisset(val1[(radius-1)/4], (radius-1)%4)) || !is_signed || (_sign(val1) == 1)) || (0 && "value is negative, should be positive"));
772 sign = ((signed_shift) && (_sign(val1) == -1))?(SC_F):(SC_0);
774 /* if shifting far enough the result is either 0 or -1 */
775 if (offset >= radius)
777 if (!sc_is_zero(val1)) {
780 memset(buffer, sign, CALC_BUFFER_SIZE);
787 /* check if any bits are lost, and set carry_flag if so */
788 for (counter = 0; counter < offset; counter++)
790 if (val1[counter] != 0)
796 if ((_val(val1[counter]) & ((1<<shift)-1)) != 0)
800 /* shift digits to the right with offset, carry and all */
802 if (radius/4 - offset > 0) {
803 buffer[counter] = shrs_table[_val(val1[offset])][shift][0];
806 for (; counter < radius/4 - offset; counter++)
808 shrs = shrs_table[_val(val1[counter + offset])][shift];
809 buffer[counter] = shrs[0];
810 buffer[counter-1] = or_table[_val(buffer[counter-1])][_val(shrs[1])];
813 /* the last digit is special in regard of signed/unsigned shift */
814 bitoffset = radius%4;
815 msd = (radius/4<CALC_BUFFER_SIZE)?(val1[radius/4]):(sign); /* most significant digit */
817 /* remove sign bits if mode was signed and this is an unsigned shift */
818 if (!signed_shift && is_signed) {
819 msd = and_table[_val(msd)][_val(max_digit[bitoffset])];
822 shrs = shrs_table[_val(msd)][shift];
824 /* signed shift and signed mode and negative value means all bits to the left are set */
825 if (signed_shift && is_signed && (_sign(val1) == -1)) {
826 buffer[counter] = or_table[_val(shrs[0])][_val(min_digit[bitoffset])];
828 buffer[counter] = shrs[0];
831 if (counter > 0) buffer[counter - 1] = or_table[_val(buffer[counter-1])][_val(shrs[1])];
833 /* fill with SC_F or SC_0 depending on sign */
834 for (counter++; counter < CALC_BUFFER_SIZE; counter++)
836 buffer[counter] = sign;
840 /* positive: low-order -> high order, negative other direction */
841 static void _rot(const char *val1, char *buffer, long offset, int radius, unsigned is_signed)
843 char temp1[CALC_BUFFER_SIZE];
844 char temp2[CALC_BUFFER_SIZE];
846 offset = offset % radius;
848 /* rotation by multiples of the typelength is identity */
850 memmove(buffer, val1, CALC_BUFFER_SIZE);
854 _shl(val1, temp1, offset, radius, is_signed);
855 _shr(val1, temp2, radius - offset, radius, is_signed, 0);
856 _bitor(temp1, temp2, buffer);
857 carry_flag = 0; /* set by shr, but due to rot this is false */
860 /*****************************************************************************
861 * public functions, declared in strcalc.h
862 *****************************************************************************/
863 const void *sc_get_buffer(void)
865 return (void*)calc_buffer;
868 const int sc_get_buffer_length(void)
870 return CALC_BUFFER_SIZE;
873 /* XXX doesn't check for overflows */
874 void sc_val_from_str(const char *str, unsigned int len, void *buffer)
876 const char *orig_str = str;
877 unsigned int orig_len = len;
880 char base[CALC_BUFFER_SIZE];
881 char val[CALC_BUFFER_SIZE];
883 /* verify valid pointers (not null) */
885 /* a string no characters long is an error */
888 if (buffer == NULL) buffer = calc_buffer;
890 CLEAR_BUFFER(buffer);
891 memset(base, SC_0, CALC_BUFFER_SIZE);
892 memset(val, SC_0, CALC_BUFFER_SIZE);
894 /* strip leading spaces */
895 while ((len > 0) && (*str == ' ')) { len--; str++; }
897 /* if the first two characters are 0x or 0X -> hex
898 * if the first is a 0 -> oct
899 * else dec, strip leading -/+ and remember sign
901 * only a + or - sign is no number resulting in an error */
906 if (str[1] == 'x' || str[1] == 'X') /* hex */
910 base[1] = SC_1; base[0] = SC_0;
916 base[1] = SC_0; base[0] = SC_8;
924 base[1] = SC_0; base[0] = SC_A;
933 base[1] = SC_0; base[0] = SC_A;
937 default: /* dec, else would have begun with 0x or 0 */
938 base[1] = SC_0; base[0] = SC_A;
941 else /* dec, else would have begun with 0x or 0 */
943 base[1] = SC_0; base[0] = SC_A;
946 /* BEGIN string evaluation, from left to right */
957 if (base[0] > SC_9 || base[1] > SC_0) /* (base > 10) */
959 val[0] = _digit((*str)-'a'+10);
961 else fail_char(orig_str, orig_len, *str, str-orig_str+1);
970 if (base[0] > SC_9 || base[1] > SC_0) /* (base > 10) */
972 val[0] = _digit((*str)-'A'+10);
974 else fail_char(orig_str, orig_len, *str, str-orig_str+1);
979 if (base[0] > SC_7 || base[1] > SC_0) /* (base > 8) */
981 val[0] = _digit((*str)-'0');
983 else fail_char(orig_str, orig_len, *str, str-orig_str+1);
995 val[0] = _digit((*str)-'0');
1000 fail_char(orig_str, orig_len, *str, str-orig_str+1);
1001 } /* switch(*str) */
1003 /* Radix conversion from base b to base B:
1004 * (UnUn-1...U1U0)b == ((((Un*b + Un-1)*b + ...)*b + U1)*b + U0)B */
1005 _mul(base, calc_buffer, calc_buffer); /* multiply current value with base */
1006 _add(val, calc_buffer, calc_buffer); /* add next digit to current value */
1008 /* get ready for the next letter */
1012 } /* while (len > 0 ) */
1016 _negate(calc_buffer, calc_buffer);
1020 void sc_val_from_long(long value, void *buffer)
1023 char sign, is_minlong;
1025 if (buffer == NULL) buffer = calc_buffer;
1029 is_minlong = value == LONG_MIN;
1031 /* use absolute value, special treatment of MIN_LONG */
1039 CLEAR_BUFFER(buffer);
1041 while ((value != 0) && (pos < (char*)buffer + CALC_BUFFER_SIZE))
1043 *pos++ = _digit(value & 0xf);
1050 _inc(buffer, buffer);
1052 _negate(buffer, buffer);
1056 void sc_val_from_ulong(unsigned long value, void *buffer)
1060 if (buffer == NULL) buffer = calc_buffer;
1063 while (pos < (char*)buffer + CALC_BUFFER_SIZE)
1065 *pos++ = _digit(value & 0xf);
1070 long sc_val_to_long(const void *val)
1075 for (i = CALC_BUFFER_SIZE - 1; i >= 0; i--)
1077 l = (l << 4) + _val(((char *)val)[i]);
1082 void sc_min_from_bits(unsigned int num_bits, unsigned int sign, void *buffer)
1087 if (buffer == NULL) buffer = calc_buffer;
1088 CLEAR_BUFFER(buffer);
1090 if (!sign) return; /* unsigned means minimum is 0(zero) */
1094 bits = num_bits - 1;
1095 for (i = 0; i < bits/4; i++)
1098 *pos++ = min_digit[bits%4];
1100 for (i++; i <= CALC_BUFFER_SIZE - 1; i++)
1104 void sc_max_from_bits(unsigned int num_bits, unsigned int sign, void *buffer)
1109 if (buffer == NULL) buffer = calc_buffer;
1110 CLEAR_BUFFER(buffer);
1113 bits = num_bits - sign;
1114 for (i = 0; i < bits/4; i++)
1117 *pos++ = max_digit[bits%4];
1119 for (i++; i <= CALC_BUFFER_SIZE - 1; i++)
1123 void sc_calc(const void* value1, const void* value2, unsigned op, void *buffer)
1125 char unused_res[CALC_BUFFER_SIZE]; /* temp buffer holding unused result of divmod */
1127 const char *val1 = (const char *)value1;
1128 const char *val2 = (const char *)value2;
1130 CLEAR_BUFFER(calc_buffer);
1133 DEBUGPRINTF_COMPUTATION(("%s ", sc_print_hex(value1)));
1138 _negate(val1, calc_buffer);
1139 DEBUGPRINTF_COMPUTATION(("negated: %s\n", sc_print_hex(calc_buffer)));
1142 DEBUGPRINTF_COMPUTATION(("| "));
1143 _bitor(val1, val2, calc_buffer);
1146 DEBUGPRINTF_COMPUTATION(("& "));
1147 _bitand(val1, val2, calc_buffer);
1150 DEBUGPRINTF_COMPUTATION(("^ "));
1151 _bitxor(val1, val2, calc_buffer);
1154 _bitnot(val1, calc_buffer);
1155 DEBUGPRINTF_COMPUTATION(("bit-negated: %s\n", sc_print_hex(calc_buffer)));
1158 DEBUGPRINTF_COMPUTATION(("+ "));
1159 _add(val1, val2, calc_buffer);
1162 DEBUGPRINTF_COMPUTATION(("- "));
1163 _sub(val1, val2, calc_buffer);
1166 DEBUGPRINTF_COMPUTATION(("* "));
1167 _mul(val1, val2, calc_buffer);
1170 DEBUGPRINTF_COMPUTATION(("/ "));
1171 _divmod(val1, val2, calc_buffer, unused_res);
1174 DEBUGPRINTF_COMPUTATION(("%% "));
1175 _divmod(val1, val2, unused_res, calc_buffer);
1180 DEBUGPRINTF_COMPUTATION(("%s -> ", sc_print_hex(value2)));
1181 DEBUGPRINTF_COMPUTATION(("%s\n", sc_print_hex(calc_buffer)));
1183 if ((buffer != NULL) && (buffer != calc_buffer))
1185 memcpy(buffer, calc_buffer, CALC_BUFFER_SIZE);
1189 void sc_bitcalc(const void* value1, const void* value2, int radius, int sign, unsigned op, void* buffer)
1191 const char *val1 = (const char *)value1;
1192 const char *val2 = (const char *)value2;
1196 offset = sc_val_to_long(val2);
1198 DEBUGPRINTF_COMPUTATION(("%s ", sc_print_hex(value1)));
1202 DEBUGPRINTF_COMPUTATION(("<< %ld ", offset));
1203 _shl(val1, calc_buffer, offset, radius, sign);
1206 DEBUGPRINTF_COMPUTATION((">> %ld ", offset));
1207 _shr(val1, calc_buffer, offset, radius, sign, 0);
1210 DEBUGPRINTF_COMPUTATION((">>> %ld ", offset));
1211 _shr(val1, calc_buffer, offset, radius, sign, 1);
1214 DEBUGPRINTF_COMPUTATION(("<<>> %ld ", offset));
1215 _rot(val1, calc_buffer, offset, radius, sign);
1220 DEBUGPRINTF_COMPUTATION(("-> %s\n", sc_print_hex(calc_buffer)));
1222 if ((buffer != NULL) && (buffer != calc_buffer))
1224 memmove(buffer, calc_buffer, CALC_BUFFER_SIZE);
1228 int sc_comp(const void* value1, const void* value2)
1230 int counter = CALC_BUFFER_SIZE - 1;
1231 const char *val1 = (const char *)value1;
1232 const char *val2 = (const char *)value2;
1234 /* compare signs first:
1235 * the loop below can only compare values of the same sign! */
1236 if (_sign(val1) != _sign(val2)) return (_sign(val1) == 1)?(1):(-1);
1238 /* loop until two digits differ, the values are equal if there
1239 * are no such two digits */
1240 while (val1[counter] == val2[counter])
1243 if (counter < 0) return 0;
1246 /* the leftmost digit is the most significant, so this returns
1247 * the correct result.
1248 * This implies the digit enum is ordered */
1249 return (val1[counter] > val2[counter]) ? (1) : (-1);
1252 int sc_get_highest_set_bit(const void *value)
1254 const char *val = (const char*)value;
1257 high = CALC_BUFFER_SIZE * 4 - 1;
1259 for (counter = CALC_BUFFER_SIZE-1; counter >= 0; counter--) {
1260 if (val[counter] == SC_0) high -= 4;
1262 if (val[counter] > SC_7) return high;
1263 else if (val[counter] > SC_3) return high - 1;
1264 else if (val[counter] > SC_1) return high - 2;
1265 else return high - 3;
1271 int sc_get_lowest_set_bit(const void *value)
1273 const char *val = (const char*)value;
1277 sign = (_sign(val)==1)?(SC_0):(SC_F);
1280 for (counter = 0; counter < CALC_BUFFER_SIZE; counter++) {
1281 if (val[counter] == SC_0) low += 4;
1283 if (val[counter] < SC_2) return low;
1284 else if (val[counter] < SC_4) return low + 1;
1285 else if (val[counter] < SC_8) return low + 2;
1286 else return low + 3;
1292 int sc_is_zero(const void *value)
1294 const char* val = (const char *)value;
1297 for (counter = 0; counter < CALC_BUFFER_SIZE; counter++) {
1298 if (val[counter] != SC_0) return 0;
1303 int sc_is_negative(const void *value)
1305 return _sign(value) == -1;
1308 int sc_had_carry(void)
1313 unsigned char sc_sub_bits(const void *value, int len, unsigned byte_ofs)
1315 const char *val = (const char *)value;
1316 unsigned nibble_ofs = 2 * byte_ofs;
1319 /* the current scheme uses one byte to store a nibble */
1320 if (nibble_ofs >= len)
1323 res = _val(val[nibble_ofs]);
1324 if (len > nibble_ofs + 1)
1325 res |= _val(val[nibble_ofs + 1]) << 4;
1331 * convert to a string
1332 * XXX Doesn't check buffer bounds
1334 const char *sc_print(const void *value, unsigned bits, enum base_t base)
1336 static const char big_digits[] = "0123456789ABCDEF";
1337 static const char small_digits[] = "0123456789abcdef";
1339 char base_val[CALC_BUFFER_SIZE];
1340 char div1_res[CALC_BUFFER_SIZE];
1341 char div2_res[CALC_BUFFER_SIZE];
1342 char rem_res[CALC_BUFFER_SIZE];
1343 int counter, nibbles, i, sign;
1346 const char *val = (const char *)value;
1350 const char *digits = small_digits;
1352 pos = output_buffer + BIT_PATTERN_SIZE;
1357 bits = BIT_PATTERN_SIZE;
1358 #ifdef STRCALC_DEBUG_FULLPRINT
1362 nibbles = bits >> 2;
1366 digits = big_digits;
1368 for (counter = 0; counter < nibbles; ++counter) {
1369 *(--pos) = digits[_val(val[counter])];
1370 #ifdef STRCALC_DEBUG_GROUPPRINT
1371 if ((counter+1)%8 == 0)
1376 /* last nibble must be masked */
1378 x = and_table[_val(val[++counter])][bits & 3];
1379 *(--pos) = digits[_val(x)];
1382 /* now kill zeros */
1383 for (; counter > 1; --counter, ++pos) {
1384 #ifdef STRCALC_DEBUG_GROUPPRINT
1385 if (pos[0] == ' ') ++pos;
1393 for (counter = 0; counter < nibbles; ++counter) {
1395 p = binary_table[_val(val[counter])];
1402 /* last nibble must be masked */
1404 x = and_table[_val(val[++counter])][bits & 3];
1407 p = binary_table[_val(x)];
1414 /* now kill zeros */
1415 for (counter <<= 2; counter > 1; --counter, ++pos)
1422 memset(base_val, SC_0, CALC_BUFFER_SIZE);
1423 base_val[0] = base == SC_DEC ? SC_A : SC_8;
1427 if (base == SC_DEC) {
1428 /* check for negative values */
1429 if (_bit(val, bits - 1)) {
1430 _negate(val, div2_res);
1436 /* transfer data into oscilating buffers */
1437 memset(div1_res, SC_0, CALC_BUFFER_SIZE);
1438 for (counter = 0; counter < nibbles; ++counter)
1439 div1_res[counter] = p[counter];
1441 /* last nibble must be masked */
1445 div1_res[counter] = and_table[_val(p[counter])][bits & 3];
1451 _divmod(m, base_val, n, rem_res);
1455 *(--pos) = digits[_val(rem_res[0])];
1458 for (i = 0; i < sizeof(div1_res); ++i)
1469 printf("%i\n", base);
1476 void init_strcalc(int precision)
1478 if (calc_buffer == NULL) {
1479 if (precision <= 0) precision = SC_DEFAULT_PRECISION;
1481 /* round up to multiple of 4 */
1482 if (precision & 0x3) precision += 4 - (precision&0x3);
1484 BIT_PATTERN_SIZE = (precision);
1485 CALC_BUFFER_SIZE = (precision / 2);
1486 MAX_VALUE_SIZE = (precision / 4);
1488 calc_buffer = malloc(CALC_BUFFER_SIZE+1 * sizeof(char));
1489 output_buffer = malloc(BIT_PATTERN_SIZE+1 * sizeof(char));
1491 if (calc_buffer == NULL || output_buffer == NULL)
1493 assert(0 && "malloc failed");
1497 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));
1500 int sc_get_precision(void)
1502 return BIT_PATTERN_SIZE;