comparison interps/c-intercal/src/fiddle.c @ 996:859f9b4339e6

<Gregor> tar xf egobot.tar.xz
author HackBot
date Sun, 09 Dec 2012 19:30:08 +0000
parents
children
comparison
equal deleted inserted replaced
995:6883f5911eb7 996:859f9b4339e6
1 /*
2 * fiddle.c -- functions that implement the five INTERCAL operators
3 *
4 * We link these to the compiler, too, in order to do constant folding
5 *
6 LICENSE TERMS
7 Copyright (C) 1996 Eric S. Raymond
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "fiddle.h"
25 #include "sizes.h"
26 #include "ick_lose.h"
27 #include <stdio.h>
28
29 unsigned int ick_mingle(register unsigned int r, register unsigned int s)
30 {
31 if (ick_Base == 2) {
32 if (r>0xffff || s>0xffff)
33 ick_lose(IE533, ick_lineno, (const char *)NULL);
34 r = ((r & 0x0000ff00) << 8) | (r & 0x000000ff);
35 r = ((r & 0x00f000f0) << 4) | (r & 0x000f000f);
36 r = ((r & 0x0c0c0c0c) << 2) | (r & 0x03030303);
37 r = ((r & 0x22222222) << 1) | (r & 0x11111111);
38 s = ((s & 0x0000ff00) << 8) | (s & 0x000000ff);
39 s = ((s & 0x00f000f0) << 4) | (s & 0x000f000f);
40 s = ((s & 0x0c0c0c0c) << 2) | (s & 0x03030303);
41 s = ((s & 0x22222222) << 1) | (s & 0x11111111);
42 return (r << 1) | s;
43 }
44 else {
45 unsigned int result = 0, fac = 1;
46 int i;
47 for (i = 0 ; i < ick_Small_digits ; i++) {
48 result += fac * (s % ick_Base);
49 s /= ick_Base;
50 fac *= ick_Base;
51 result += fac * (r % ick_Base);
52 r /= ick_Base;
53 fac *= ick_Base;
54 }
55 return result;
56 }
57 }
58
59 unsigned int ick_iselect(register unsigned int r, register unsigned int s)
60 {
61 if (ick_Base == 2) {
62 register unsigned int i = 1, t = 0;
63 while (s) {
64 if (s & i) {
65 t |= r & i;
66 s ^= i;
67 i <<= 1;
68 }
69 else {
70 s >>= 1;
71 r >>= 1;
72 }
73 }
74 return(t);
75 }
76 else {
77 unsigned int j, result = 0, fac, digit, ofac = 1;
78 for (j = (unsigned)ick_Base - 1 ; j > 0 ; j--) {
79 int i;
80 fac = 1;
81 for (i = 0; i < ick_Large_digits ; i++) {
82 if ((s / fac) % ick_Base == j) {
83 digit = (r / fac) % ick_Base;
84 if (digit)
85 result += ofac * (digit > j ? digit : j);
86 ofac *= ick_Base;
87 }
88 fac *= ick_Base;
89 }
90 }
91 return result;
92 }
93 }
94
95 static unsigned int ick_whirl(unsigned int len, unsigned int p, unsigned int n)
96 {
97 unsigned int i, fac = 1, result = 0, d1, d2, dsave;
98 d1 = n % ick_Base;
99 dsave = d1;
100 for (i = 1 ; i <= len ; i++) {
101 d2 = d1;
102 d1 = (i < len) ? (n /= ick_Base, n % ick_Base) : dsave;
103 if (d1 <= p)
104 result += fac * ((d2 < d1 || d2 > p) ? d1 : d2);
105 else
106 result += fac * ((d2 < d1 && d2 > p) ? d1 : d2);
107 fac *= ick_Base;
108 }
109 return result;
110 }
111
112 unsigned int ick_and16(unsigned int n)
113 {
114 if (ick_Base == 2) {
115 unsigned int m = (n >> 1);
116 if (n & 1)
117 m |= 0x8000;
118 return(m & n);
119 }
120 else {
121 return ick_whirl((unsigned)ick_Small_digits,0,n);
122 }
123 }
124
125 unsigned int ick_or16(unsigned int n)
126 {
127 if (ick_Base == 2) {
128 unsigned int m = (n >> 1);
129 if (n & 1)
130 m |= 0x8000;
131 return(m | n);
132 }
133 else {
134 return ick_whirl((unsigned)ick_Small_digits,(unsigned)ick_Base-1,n);
135 }
136 }
137
138 unsigned int ick_whirl16(unsigned int p, unsigned int n)
139 {
140 return ick_whirl((unsigned)ick_Small_digits,p,n);
141 }
142
143 unsigned int ick_and32(unsigned int n)
144 {
145 if (ick_Base == 2) {
146 unsigned int m = (n >> 1);
147 if (n & 1)
148 m |= 0x80000000;
149 return(m & n);
150 }
151 else {
152 return ick_whirl((unsigned)ick_Large_digits,0,n);
153 }
154 }
155
156 unsigned int ick_or32(unsigned int n)
157 {
158 if (ick_Base == 2) {
159 unsigned int m = (n >> 1);
160 if (n & 1)
161 m |= 0x80000000;
162 return(m | n);
163 }
164 else {
165 return ick_whirl((unsigned)ick_Large_digits,(unsigned)ick_Base-1,n);
166 }
167 }
168
169 unsigned int ick_whirl32(unsigned int p, unsigned int n)
170 {
171 return ick_whirl((unsigned)ick_Large_digits,p,n);
172 }
173
174 static unsigned int ick_xor(unsigned int len, unsigned int n)
175 {
176 unsigned int i, fac = 1, result = 0, d1, d2, dsave;
177 d1 = n % ick_Base;
178 dsave = d1;
179 for (i = 1 ; i <= len ; i++) {
180 d2 = d1;
181 d1 = (i < len) ? (n /= ick_Base, n % ick_Base) : dsave;
182 result += fac * ((ick_Base + d1 - d2) % ick_Base);
183 fac *= ick_Base;
184 }
185 return result;
186 }
187
188 unsigned int ick_xor16(unsigned int n)
189 {
190 if (ick_Base == 2) {
191 unsigned int m = (n >> 1);
192 if (n & 1)
193 m |= 0x8000;
194 return(m ^ n);
195 }
196 else {
197 return ick_xor((unsigned)ick_Small_digits,n);
198 }
199 }
200
201 unsigned int ick_xor32(unsigned int n)
202 {
203 if (ick_Base == 2) {
204 unsigned int m = (n >> 1);
205 if (n & 1)
206 m |= 0x80000000;
207 return(m ^ n);
208 }
209 else {
210 return ick_xor((unsigned)ick_Large_digits,n);
211 }
212 }
213
214 static unsigned int ick_fin(unsigned int len, unsigned int n)
215 {
216 unsigned int i, fac = 1, result = 0, d1, d2, dsave;
217 d1 = n % ick_Base;
218 dsave = d1;
219 for (i = 1 ; i <= len ; i++) {
220 d2 = d1;
221 d1 = (i < len) ? (n /= ick_Base, n % ick_Base) : dsave;
222 result += fac * ((d1 + d2) % ick_Base);
223 fac *= ick_Base;
224 }
225 return result;
226 }
227
228 unsigned int ick_fin16(unsigned int n)
229 {
230 if (ick_Base == 2) {
231 unsigned int m = (n >> 1);
232 if (n & 1)
233 m |= 0x8000;
234 return(m ^ n);
235 }
236 else {
237 return ick_fin((unsigned)ick_Small_digits,n);
238 }
239 }
240
241 unsigned int ick_fin32(unsigned int n)
242 {
243 if (ick_Base == 2) {
244 unsigned int m = (n >> 1);
245 if (n & 1)
246 m |= 0x80000000;
247 return(m ^ n);
248 }
249 else {
250 return ick_fin((unsigned)ick_Large_digits,n);
251 }
252 }
253
254 /* AIS: Reversed operations, for operand overloading */
255
256 static unsigned int ick_rotleft16(unsigned int n)
257 {
258 return !!(n&0x8000)|((n&0x7FFF)<<1);
259 }
260 static unsigned int ick_rotleft32(unsigned int n)
261 {
262 return !!(n&0x80000000)|((n&0x7FFFFFFF)<<1);
263 }
264
265 /* For the time being, just work out the answer in binary, and test using
266 the base-whatever operation. This means that there'll nearly always be
267 a failure in reversing in bases other than 2. */
268 unsigned int ick_rev_or16(unsigned int n)
269 {
270 if(ick_or16(ick_rotleft16(ick_and16(n)))==n) return ick_rotleft16(ick_and16(n));
271 ick_lose(IE277, ick_lineno, (const char*) NULL);
272 /*@-unreachable@*/ return 0; /*@=unreachable@*/
273 }
274
275 unsigned int ick_rev_or32(unsigned int n)
276 {
277 if(ick_or32(ick_rotleft32(ick_and32(n)))==n) return ick_rotleft32(ick_and32(n));
278 ick_lose(IE277, ick_lineno, (const char*) NULL);
279 /*@-unreachable@*/ return 0; /*@=unreachable@*/
280 }
281
282 unsigned int ick_rev_and16(unsigned int n)
283 {
284 if(ick_and16(ick_rotleft16(ick_or16(n)))==n) return ick_rotleft16(ick_or16(n));
285 ick_lose(IE277, ick_lineno, (const char*) NULL);
286 /*@-unreachable@*/ return 0; /*@=unreachable@*/
287 }
288
289 unsigned int ick_rev_and32(unsigned int n)
290 {
291 if(ick_and32(ick_rotleft32(ick_or32(n)))==n) return ick_rotleft32(ick_or32(n));
292 ick_lose(IE277, ick_lineno, (const char*) NULL);
293 /*@-unreachable@*/ return 0; /*@=unreachable@*/
294 }
295
296 unsigned int ick_rev_xor16(unsigned int n)
297 {
298 unsigned int a=0, l=1, t=0;
299 while(l<=0x4000)
300 {
301 if(n&l)
302 t^=1;
303 if(t)
304 a+=l*2;
305 l*=2;
306 }
307 if(ick_xor16(a)==n) return a;
308 ick_lose(IE277, ick_lineno, (const char*) NULL);
309 /*@-unreachable@*/ return 0; /*@=unreachable@*/
310 }
311
312
313 unsigned int ick_rev_xor32(unsigned int n)
314 {
315 unsigned int a=0, l=1, t=0;
316 while(l<=0x4000000)
317 {
318 if(n&l)
319 t^=1;
320 if(t)
321 a+=l*2;
322 l*=2;
323 }
324 if(ick_xor32(a)==n) return a;
325 ick_lose(IE277, ick_lineno, (const char*) NULL);
326 /*@-unreachable@*/ return 0; /*@=unreachable@*/
327 }
328
329 unsigned int ick_rev_fin16(unsigned int n)
330 {
331 unsigned int a=0, l=1, t=0;
332 while(l<=0x4000)
333 {
334 if(n&l)
335 t^=1;
336 if(t)
337 a+=l*2;
338 l*=2;
339 }
340 if(ick_fin16(a)==n) return a;
341 ick_lose(IE277, ick_lineno, (const char*) NULL);
342 /*@-unreachable@*/ return 0; /*@=unreachable@*/
343 }
344
345
346 unsigned int ick_rev_fin32(unsigned int n)
347 {
348 unsigned int a=0, l=1, t=0;
349 while(l<=0x4000000)
350 {
351 if(n&l)
352 t^=1;
353 if(t)
354 a+=l*2;
355 l*=2;
356 }
357 if(ick_fin32(a)==n) return a;
358 ick_lose(IE277, ick_lineno, (const char*) NULL);
359 /*@-unreachable@*/ return 0; /*@=unreachable@*/
360 }
361
362 unsigned int ick_rev_whirl16(unsigned int p, unsigned int n)
363 {
364 /* Only reverse if all digits are the same. */
365 if(ick_whirl16(p,n)==n) return n;
366 ick_lose(IE277, ick_lineno, (const char*) NULL);
367 /*@-unreachable@*/ return 0; /*@=unreachable@*/
368 }
369
370 unsigned int ick_rev_whirl32(unsigned int p, unsigned int n)
371 {
372 /* Only reverse if all digits are the same. */
373 if(ick_whirl32(p,n)==n) return n;
374 ick_lose(IE277, ick_lineno, (const char*) NULL);
375 /*@-unreachable@*/ return 0; /*@=unreachable@*/
376 }
377
378 /* AIS: Some helper functions for the optimizer, only working in base 2 */
379
380 unsigned int ick_xselx(unsigned int x)
381 {
382 register unsigned int r=0;
383 if(ick_Base != 2) ick_lose(IE778, ick_lineno, (const char*) NULL);
384 while(x) {if(x&1) r=(r<<1)|1; x>>=1;}
385 return r;
386 }
387
388 unsigned int ick_setbitcount(unsigned int x)
389 {
390 register unsigned int r=0;
391 while(x) {if(x&1) r++; x>>=1;}
392 return r;
393 }
394
395 unsigned int ick_smudgeright(unsigned int x)
396 {
397 x=x|(x>>1);
398 x=x|(x>>2);
399 x=x|(x>>4);
400 x=x|(x>>8);
401 x=x|(x>>18);
402 return x;
403 }
404
405 unsigned int ick_smudgeleft(unsigned int x)
406 {
407 x=x|(x<<1);
408 x=x|(x<<2);
409 x=x|(x<<4);
410 x=x|(x<<8);
411 x=x|(x<<18);
412 return x;
413 }
414
415 /* fiddle.c */