1
! longint.h - support for signed and unsigned 4 byte integers in Inform.
3
! Mainly by Chris Hall - c@pobox.co.uk.
4
! Signed integer support by Francis Irving - francis@pobox.co.uk.
5
! Please email us with any errors, omissions or if you've
6
! found this code useful.
8
! For example use of this module, see longint.inf, which should be
9
! available from the same place you got this file.
11
! For a complete Inform program using this module see
12
! http://www.meta.demon.co.uk/zbefunge.html
14
! (If you need to edit this file, note that indentations are 4 spaces
15
! and tabs are not used.)
17
! This source code is distributed free, but remains
18
! Copyright 1997-1998 Chris Hall and Francis Irving. Release 1.
22
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
24
! Functions beginning "LongSign" work on signed integers.
25
! Functions beginning "LongUnsign" work on unsigned integers.
26
! Functions beginning "Long" are generally applicable.
28
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
31
Array _LongNegTemp0->4;
32
Array _LongNegTemp1->4;
34
! Print a signed long. Use by writing "print (longsign)x;".
36
LongSignOutputAsChars(n, LongPrintChar);
39
! Print an unsigned long. Use by writing "print (longunsign)x;".
41
LongUnsignOutputAsChars(n, LongPrintChar);
44
! Generalised printing.
45
! This takes "n" and outputs it a character at
46
! a time, calling function "fn". Returns the length
48
[LongSignOutputAsChars n fn
56
LongSignAbsAssign(_LongNegTemp0, n);
57
len = len + LongNum4(_LongNegTemp0->0,_LongNegTemp0->1,_LongNegTemp0->2,_LongNegTemp0->3, fn);
61
! As signed version above.
62
[LongUnsignOutputAsChars n fn
64
len = LongNum4(n->0,n->1,n->2,n->3, fn);
77
b=b+256*(a%10); a=a/10;
78
c=c+256*(b%10); b=b/10;
79
d=d+256*(c%10); c=c/10;
83
len = len + LongNum4(a,b,c,d, fn);
91
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
92
!! Simple testing and assigning
94
! Test to see if a signed long is negative.
102
! Test to see if long is zero. Signed or unsigned.
104
if ((a->0 == 0) && (a->1 == 0) && (a->2 == 0) && (a->3 == 0))
110
! Sets values into a signed or unsigned long.
111
! The appropriate encoding is left up to the caller:
112
! 1. We store our longs in big-endian (most significant first) order.
113
! 2. a&$80 is non-zero for negative signed integers.
114
! You might want to call this with parameters (0, 0, 0, x) to
115
! set a value from 0 to 255. Then use LongSignNegAssign to
117
[LongSet l a b c d; ! l=((a*256+b)*256+c)*256+d
124
! Copy either a signed or unsigned long.
125
[LongAssign d s; ! d=s
132
! d=-s d and s can be the same variable
133
[LongSignNegAssign d s
137
t=d->3+1; d->3=t%256;
138
t=d->2+t/256; d->2=t%256;
139
t=d->1+t/256; d->1=t%256;
140
t=d->0+t/256; d->0=t%256;
143
! d=positive part of s
144
[LongSignAbsAssign d s;
145
if (LongSignIsNeg(s))
146
LongSignNegAssign(d, s);
151
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
152
!! Addition and subtraction.
154
! r=a+b; (r may be same variable as a or b)
155
! Works for signed or unsigned longs.
158
t=a->3+b->3; r->3=t%256;
159
t=a->2+b->2+t/256; r->2=t%256;
160
t=a->1+b->1+t/256; r->1=t%256;
161
t=a->0+b->0+t/256; r->0=t%256;
164
! r=a-b; (r may be same variable as a or b)
165
! Works for signed or unsigned longs.
168
t=256+a->3-b->3; r->3=t%256;
169
t=256+a->2-b->2-(t<256); r->2=t%256;
170
t=256+a->1-b->1-(t<256); r->1=t%256;
171
t=256+a->0-b->0-(t<256); r->0=t%256;
174
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
175
!! Multiplication and division.
177
! r=a*b; (r may _not_ be same variable as a or b)
178
! Works for signed or unsigned longs. Note that the
179
! destination variable must be a different variable
180
! from both of the source variables.
183
t=(a->3%16)*(b->3%16); r->3=t%16;
184
t=(a->3%16)*(b->3/16)
185
+(a->3/16)*(b->3%16)+t/16; r->3=r->3+16*(t%16);
186
t=(a->3%16)*(b->2%16)
188
+(a->2%16)*(b->3%16)+t/16; r->2=t%16;
189
t=(a->3%16)*(b->2/16)
192
+(a->2/16)*(b->3%16)+t/16; r->2=r->2+16*(t%16);
193
t=(a->3%16)*(b->1%16)
197
+(a->1%16)*(b->3%16)+t/16; r->1=t%16;
198
t=(a->3%16)*(b->1/16)
203
+(a->1/16)*(b->3%16)+t/16; r->1=r->1+16*(t%16);
204
t=(a->3%16)*(b->0%16)
210
+(a->0%16)*(b->3%16)+t/16; r->0=t%16;
211
t=(a->3%16)*(b->0/16)
214
+(a->2/16)*(b->1%16)+t/16;
215
t=(a->1%16)*(b->2/16)
218
+(a->0/16)*(b->3%16)+t; r->0=r->0+16*(t%16);
221
Array _LongDMTemp0->4;
222
Array _LongDMTemp1->4;
224
! d=a/b; m=a%b (d and m may be same variable as a or b)
225
! Works for unsigned longs only.
226
[LongUnsignDivMod d m a b
229
! Division by zero! The user is encouraged to test for this
230
! himself before calling the various division functions. We
231
! simply force the interpreter to perform a divide by zero.
232
if(LongIsZero(b)){a=0;a=a/0;}
234
LongAssign(_LongDMTemp1,b);
237
_LongDMTemp0->0=_LongDMTemp0->1=_LongDMTemp0->2=0; _LongDMTemp0->3=1;
239
while(LongUnsignLE(_LongDMTemp1,m)){
240
t=LongShl(_LongDMTemp0);
242
LongShl(_LongDMTemp1);
245
if(LongShr(_LongDMTemp0,t)) break;
247
if(~~t) LongShr(_LongDMTemp1);
248
if(LongUnsignLE(_LongDMTemp1,m)){
249
LongSub(m,m,_LongDMTemp1);
250
LongAdd(d,d,_LongDMTemp0);
255
Array _LongDMTemp2->4;
257
! r=a/b; (r may be same variable as a or b)
258
! Works for signed longs only.
261
n = LongNegIndex(a, b,_LongNegTemp0,_LongNegTemp1);
262
LongUnsignDivMod(r,_LongDMTemp2,_LongNegTemp0,_LongNegTemp1);
263
LongUseNegIndex(n, r);
266
! r=a%b; (r may be same variable as a or b)
267
! Works for signed longs only.
270
n = LongNegIndex(a, b,_LongNegTemp0,_LongNegTemp1);
271
LongUnsignDivMod(_LongDMTemp2,r,_LongNegTemp0,_LongNegTemp1);
272
LongUseNegIndex(n, r);
276
! c=abs(a), d= abs(b) if a*b is negative, return that.
277
[LongNegIndex a b c d;
278
LongSignAbsAssign(c, a);
279
LongSignAbsAssign(d, b);
280
if (LongSignIsNeg(a) ~= LongSignIsNeg(b))
287
! if n true, let r=-r
288
[ LongUseNegIndex n r;
290
LongSignNegAssign(r, r);
293
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
300
! Works for signed longs only.
301
[LongSignCompare a b;
302
if (LongSignIsNeg(a) && (~~LongSignIsNeg(b))) return -1;
303
if ((~~LongSignIsNeg(a)) && LongSignIsNeg(b)) return 1;
305
if (~~LongSignIsNeg(a))
307
LongSignAbsAssign(_LongNegTemp0, a);
308
LongSignAbsAssign(_LongNegTemp1, b);
312
! swap round if they are both negative
313
LongSignAbsAssign(_LongNegTemp0, b);
314
LongSignAbsAssign(_LongNegTemp1, a);
317
return LongUnsignCompare(_LongNegTemp0, _LongNegTemp1);
324
! Works for unsigned longs only.
325
[LongUnsignCompare a b;
326
if(a->0<b->0) return(-1);
328
if(a->1<b->1) return(-1);
330
if(a->2<b->2) return(-1);
332
if(a->3<b->3) return(-1);
337
[LongUnsignLT a b; return(LongUnsignCompare(a,b)< 0);]; ! return(a< b);
338
[LongUnsignLE a b; return(LongUnsignCompare(a,b)<=0);]; ! return(a<=b);
339
[LongUnsignGT a b; return(LongUnsignCompare(a,b)> 0);]; ! return(a> b);
340
[LongUnsignGE a b; return(LongUnsignCompare(a,b)>=0);]; ! return(a>=b);
341
[LongUnsignEQ a b; return(LongUnsignCompare(a,b)==0);]; ! return(a==b);
342
[LongUnsignNE a b; return(LongUnsignCompare(a,b)~=0);]; ! return(a~=b);
345
[LongSignLT a b; return(LongSignCompare(a,b)< 0);]; ! return(a< b);
346
[LongSignLE a b; return(LongSignCompare(a,b)<=0);]; ! return(a<=b);
347
[LongSignGT a b; return(LongSignCompare(a,b)> 0);]; ! return(a> b);
348
[LongSignGE a b; return(LongSignCompare(a,b)>=0);]; ! return(a>=b);
349
[LongSignEQ a b; return(LongSignCompare(a,b)==0);]; ! return(a==b);
350
[LongSignNE a b; return(LongSignCompare(a,b)~=0);]; ! return(a~=b);
352
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
353
!! Bitwise comparisons.
355
! These bitwise operators aren't really signed or unsigned.
357
! a=(a<<1+t); return(bit lost off end);
359
t=a->3*2+t; a->3=t%256;
360
t=a->2*2+t/256; a->2=t%256;
361
t=a->1*2+t/256; a->1=t%256;
362
t=a->0*2+t/256; a->0=t%256;
366
! a=((a+(t<<32))>>1); return(bit lost off end);
368
t=a->0+256*t; a->0=t/2;
369
t=a->1+256*(t%2); a->1=t/2;
370
t=a->2+256*(t%2); a->2=t/2;
371
t=a->3+256*(t%2); a->3=t/2;