/* $Header$ */
/*
* Copyright © 1988-2004 Keith Packard and Bart Massey.
* All Rights Reserved. See the file COPYING in this directory
* for licensing information.
*/
#include "nickle.h"
static Value
IntPlus (Value av, Value bv, int expandOk)
{
int r = ValueInt(av) + ValueInt(bv);
if (expandOk && NICKLE_INT_CARRIED(r))
return Plus (NewIntInteger (ValueInt(av)), NewIntInteger(ValueInt(bv)));
return NewInt(r);
}
static Value
IntMinus (Value av, Value bv, int expandOk)
{
int r = ValueInt(av) - ValueInt(bv);
if (expandOk && NICKLE_INT_CARRIED(r))
return Minus (NewIntInteger (ValueInt(av)), NewIntInteger(ValueInt(bv)));
return NewInt(r);
}
int
logbase2(int a)
{
int log = 0;
if (a < 0)
a = -a;
while (a & (~ 0xff)) {
log += 8;
a >>= 8;
}
if (a & (~0xf)) {
log += 4;
a >>= 4;
}
if (a & (~0x3)) {
log += 2;
a >>= 2;
}
if (a & (~0x1))
log += 1;
return log;
}
#define HALF_BITS (NICKLE_INT_BITS>>1)
#define HALF_MAX (1 << (NICKLE_INT_BITS>>1))
static Value
IntTimes (Value av, Value bv, int expandOk)
{
int a = ValueInt(av), b = ValueInt(bv);
signed_digit rd = (signed_digit) a * (signed_digit) b;
if (rd > (signed_digit) MAX_NICKLE_INT || rd < (signed_digit) MIN_NICKLE_INT)
return NewSignedDigitInteger (rd);
return NewInt ((int) rd);
}
static Value
IntDivide (Value av, Value bv, int expandOk)
{
ENTER ();
int a = ValueInt(av), b = ValueInt(bv);
Value ret;
if (b == 0)
{
RaiseStandardException (exception_divide_by_zero,
"int divide by zero",
2, av, bv);
RETURN (Void);
}
if (expandOk && a % b != 0)
ret = Divide (NewIntRational (a), NewIntRational (b));
else
ret = NewInt (a/b);
RETURN (ret);
}
static Value
IntDiv (Value av, Value bv, int expandOk)
{
ENTER ();
int a = ValueInt(av), b = ValueInt(bv);
int d;
Value ret;
if (b == 0)
{
RaiseStandardException (exception_divide_by_zero,
"int div by zero",
2, av, bv);
RETURN (Void);
}
switch (catagorize_signs (IntSign(a), IntSign(b))) {
case BothPositive:
d = a / b;
break;
case FirstPositive:
d = - (a / -b);
break;
case SecondPositive:
d = -(a / -b);
if (a % -b)
d--;
break;
case BothNegative:
default:
d = -a / -b;
if (-a % -b)
d++;
break;
}
ret = NewInt (d);
RETURN (ret);
}
/*
* dividend * quotient + remainder = divisor
*
* IntSign(quotient) = IntSign (dividend) * IntSign (divisor)
* 0 <= remainder < abs (dividend)
*/
static Value
IntMod (Value av, Value bv, int expandOk)
{
ENTER ();
int a = ValueInt(av), b = ValueInt(bv);
int r;
if (b == 0)
{
RaiseStandardException (exception_divide_by_zero,
"int modulus by zero",
2, av, bv);
RETURN (Void);
}
switch (catagorize_signs (IntSign(a), IntSign(b))) {
case BothPositive:
r = a % b;
break;
case FirstPositive:
r = a % -b;
break;
case SecondPositive:
r = -a % b;
if (r)
r = b - r;
break;
case BothNegative:
default:
r = -a % -b;
if (r)
r = -b - r;
break;
}
RETURN (NewInt (r));
}
static Value
IntEqual (Value av, Value bv, int expandOk)
{
int a = ValueInt(av), b = ValueInt(bv);
if (a == b)
return TrueVal;
return FalseVal;
}
static Value
IntLess (Value av, Value bv, int expandOk)
{
int a = ValueInt(av), b = ValueInt(bv);
if (a < b)
return TrueVal;
return FalseVal;
}
static Value
IntLand (Value av, Value bv, int expandOk)
{
ENTER ();
int a = ValueInt(av), b = ValueInt(bv);
RETURN (NewInt (a & b));
}
static Value
IntLor (Value av, Value bv, int expandOk)
{
ENTER ();
int a = ValueInt(av), b = ValueInt(bv);
RETURN (NewInt (a | b));
}
static Value
IntNegate (Value av, int expandOk)
{
ENTER ();
int a = ValueInt(av);
if (-(-a) != a)
RETURN (Negate (NewIntInteger (a)));
RETURN (NewInt (-a));
}
static Value
IntFloor (Value av, int expandOk)
{
return av;
}
static Value
IntCeil (Value av, int expandOk)
{
return av;
}
static Bool
IntPrint (Value f, Value av, char format, int base, int width, int prec, int fill)
{
int a = ValueInt(av);
int digit;
int w;
int fraction_width;
char space[64], *s;
char letter;
int neg;
long len;
if ('A' <= format && format <= 'Z')
letter = 'A';
else
letter = 'a';
if (base == 0)
base = 10;
switch (format) {
case 'c':
space[StringPutChar (a, space)] = '\0';
s = space;
break;
default:
s = space + sizeof (space);
*--s = '\0';
neg = 0;
if (a < 0)
{
a = -a;
neg = 1;
}
if (!a)
*--s = '0';
else
{
while (a)
{
digit = a % base;
if (digit <= 9)
digit = '0' + digit;
else
digit = letter + digit - 10;
*--s = digit;
a /= base;
}
if (neg)
*--s = '-';
}
}
len = strlen (s);
w = StringLength (s, len);
fraction_width = 0;
if (prec >= 0)
{
int avail_width;
if (width > 0)
avail_width = width;
else
avail_width = -width;
fraction_width = prec + 1;
if (avail_width > 0)
{
if (w + fraction_width > avail_width)
{
fraction_width = avail_width - w;
if (fraction_width < 0)
fraction_width = 0;
}
}
}
w += fraction_width;
while (width > w)
{
FileOutchar (f, fill);
width--;
}
FilePutsc (f, s, len);
if (fraction_width)
{
FileOutput (f, '.');
--fraction_width;
while (fraction_width)
{
FileOutput (f, '0');
--fraction_width;
}
}
while (-width > w)
{
FileOutchar (f, fill);
width++;
}
return True;
}
static HashValue
IntHash (Value av)
{
return (HashValue) ValueInt (av);;
}
ValueRep IntRep = {
{ 0, 0, "IntRep" }, /* data */
rep_int, /* tag */
{ /* binary */
IntPlus,
IntMinus,
IntTimes,
IntDivide,
IntDiv,
IntMod,
IntLess,
IntEqual,
IntLand,
IntLor
},
{
IntNegate,
IntFloor,
IntCeil,
},
0, 0,
IntPrint,
0,
IntHash,
};
int
IntInit (void)
{
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1