rev 561 - in trunk: include/prothon modules/Re src
SVN User <[email protected]> Fri, 28 May 2004 16:57:35 -0400
| Newsgroups | gmane.comp.lang.prothon.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: mark
Date: 2004-05-28 16:57:33 -0400 (Fri, 28 May 2004)
New Revision: 561
Modified:
trunk/include/prothon/prothon.h
trunk/include/prothon/prothon_dll.h
trunk/modules/Re/Re.c
trunk/src/builtins-int.c
trunk/src/builtins-string.c
trunk/src/parser.h
trunk/src/parser_routines.c
trunk/src/prothon.y
Log:
long ints partially implemented, ints probably very broken
Modified: trunk/include/prothon/prothon.h
===================================================================
--- trunk/include/prothon/prothon.h 2004-05-28 05:50:02 UTC (rev 560)
+++ trunk/include/prothon/prothon.h 2004-05-28 20:57:33 UTC (rev 561)
@@ -313,7 +313,6 @@
// constants
ZERO_INT, //
- MAX_INT, // MaxInt
// Containers
ROOT_GLOBALS, // Root_Globals
@@ -920,21 +919,29 @@
// when index is 0 .. -n, parms[1] is a list and -index is list index
#define ITEM (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index))
-#define INT_32_PARAM(index, var) /* int var; */ \
+#define INT____PARAM(index, var) /* obj_t var; */ \
{ if (!has_proto(ist, (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)), OBJ(INT_PROTO))) { \
raise_exception(ist, OBJ(TYPE_EXC), \
"expected a integer in parameter " #index); \
- return NULL; \
+ return (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)); \
} \
- (var) = (int) (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index))->data.i64; }
+ (var) = (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)); }
+#define INT_32_PARAM(index, var) /* i32_t var; */ \
+{ if (!has_proto(ist, (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)), OBJ(INT_PROTO))) { \
+ raise_exception(ist, OBJ(TYPE_EXC), \
+ "expected a integer in parameter " #index); \
+ return (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)); \
+ } \
+ (var) = int2i32t(index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)); }
+
#define INT_64_PARAM(index, var) /* i64_t var; */ \
{ if (!has_proto(ist, (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)), OBJ(INT_PROTO))) { \
raise_exception(ist, OBJ(TYPE_EXC), \
"expected a integer in parameter " #index); \
return (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)); \
} \
- (var) = (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index))->data.i64; }
+ (var) = int2i64t(index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)); }
#define STRING_PARAM(index, var) \
{ if (!has_proto(ist, (index > 0 ? parms[((index)-1)*2+1] : list_item(ist, parms[1], -index)), OBJ(STRING_PROTO))) { \
Modified: trunk/include/prothon/prothon_dll.h
===================================================================
--- trunk/include/prothon/prothon_dll.h 2004-05-28 05:50:02 UTC (rev 560)
+++ trunk/include/prothon/prothon_dll.h 2004-05-28 20:57:33 UTC (rev 561)
@@ -183,12 +183,12 @@
"object has binary data, expected none"); \
return NULL; }
-#define BIN_STR_CHK(slf) \
- if (self == slf##_OBJ) \
+#define BIN_STR_CHK(slf) \
+ if (self == slf##_OBJ) \
return call_func(ist, self, SYM(STR_), 0, NULL, slf##_OBJ); \
- if (self->data_type == DATA_TYPE_NONE) { \
- char msg[80]; \
- apr_snprintf(msg, sizeof(msg), "<%s:Uninitialized>", #slf); \
+ if (self->data_type == DATA_TYPE_NONE) { \
+ char msg[80]; \
+ apr_snprintf(msg, sizeof(msg), "<%s:Uninitialized>", #slf); \
return NEW_STRING(msg); }
#define BIN_EMPTY_OR_NOT_CHK(slf) \
Modified: trunk/modules/Re/Re.c
===================================================================
--- trunk/modules/Re/Re.c 2004-05-28 05:50:02 UTC (rev 560)
+++ trunk/modules/Re/Re.c 2004-05-28 20:57:33 UTC (rev 561)
@@ -193,7 +193,7 @@
DEF( ReCompiled, search, FPARM3( s, NULL,
start, OBJ(ZERO_INT),
- end, OBJ(MAX_INT) ) ) {
+ end, NEW_INT(MAX_INT_VAL) ) ) {
obj_p match_obj, lastindex_obj;
int err;
unsigned int i, last_index=0, ngrps = numgrps(self);
Modified: trunk/src/builtins-int.c
===================================================================
--- trunk/src/builtins-int.c 2004-05-28 05:50:02 UTC (rev 560)
+++ trunk/src/builtins-int.c 2004-05-28 20:57:33 UTC (rev 561)
@@ -77,6 +77,11 @@
#define INT_MAX 2147483647 /* maximum (signed) int value */
#define Py_IS_INFINITY(X) ((X) && (X)*0.5 == (X))
+#define MAX32 0x000000003fffffff
+#define MIN32 -MAX32
+#define MAX64 0x3fffffffffffffff
+#define MIN64 -MAX64
+
typedef u16_t digit;
typedef u32_t wdigit;
#define BASE_TWODIGITS_TYPE long
@@ -88,12 +93,23 @@
#define MASK ((int)(BASE - 1))
typedef struct {
- int size;
+ u32_t size;
+ i32_t dsize;
digit digit[];
} long_t;
+typedef digit* digit_p;
typedef long_t* long_p;
+#define long_size(obj) (((long_p)((obj)->data.ptr))->size)
+#define long_dsize(obj) (((long_p)((obj)->data.ptr))->dsize)
+#define long_digitp(obj) (((long_p)((obj)->data.ptr))->digit)
+
+#define int_sign(obj) \
+ ( obj->data_type == DATA_TYPE_IMMDATA ? \
+ (obj->data.i64 == 0 ? 0 : (obj->data.i64 < 0 ? -1 : 1)) : \
+ (long_dsize(obj) == 0 ? 0 : (long_dsize(obj) < 0 ? -1 : 1)) ) \
+
#define SIGCHECK(x) if (0) x
#define Py_CHARMASK(c) ((c) & 0xff)
#define Py_INCREF
@@ -108,14 +124,14 @@
/* Long integer representation.
The absolute value of a number is equal to
- SUM(for i=0 through abs(size)-1) digit[i] * 2**(SHIFT*i)
- Negative numbers are represented with size < 0;
- zero is represented by size == 0.
- In a normalized number, digit[abs(size)-1] (the most significant
+ SUM(for i=0 through abs(dsize)-1) digit[i] * 2**(SHIFT*i)
+ Negative numbers are represented with dsize < 0;
+ zero is represented by dsize == 0.
+ In a normalized number, digit[abs(dsize)-1] (the most significant
digit) is never zero. Also, in all cases, for all valid i,
0 <= digit[i] <= MASK.
The allocation function takes care of allocating extra memory
- so that digit[0] ... digit[abs(size)-1] are actually available.
+ so that digit[0] ... digit[abs(dsize)-1] are actually available.
*/
MODULE_DECLARE(Int);
@@ -131,39 +147,49 @@
return obj;
}
+//********************************* new_int_long_obj **************************
+obj_p new_int_long_obj(isp ist, long_p longp){
+ obj_p obj = NEW_OBJ(OBJ(INT_PROTO));
+ obj->data_type = DATA_TYPE_DATAPTR;
+ obj->data.ptr = pr_malloc(longp->size * sizeof(digit));
+ memcpy(obj->data.ptr, longp, longp->size * sizeof(digit));
+ obj->immutable = TRUE;
+ return obj;
+}
/* Normalize (remove leading zeros from) a int object.
Doesn't attempt to free the storage--in most cases, due to the nature
of the algorithms used, this could save at most be one word anyway. */
static long_p long_normalize(register long_p v) {
- int j = abs(v->size);
+ int j = abs(v->dsize);
register int i = j;
while (i > 0 && v->digit[i-1] == 0)
--i;
if (i != j)
- v->size = (v->size < 0) ? -(i) : i;
+ v->dsize = (v->dsize < 0) ? -(i) : i;
return v;
}
-/* Allocate a new long int object with size digits.
+/* Allocate a new long int object with dsize digits.
Return NULL and set exception if we run out of memory. */
-long_p new_longp_non_init(int size) {
- return (long_p) pr_malloc(sizeof(long_t) + size * sizeof(digit));
+long_p new_longp_non_init(u32_t size) {
+ long_p longp = pr_malloc(sizeof(long_t) + size * sizeof(digit));
+ longp->size = size;
+ return longp;
}
long_p copy_longp(long_p src) {
long_p result;
int i;
-
assert(src != NULL);
- i = src->size;
- if (i < 0)
- i = -(i);
+ i = abs(src->dsize)+1;
result = new_longp_non_init(i);
if (result != NULL) {
- result->size = src->size;
+ if (src->dsize >= 0) result->dsize = i;
+ else result->dsize = -i;
+ result->digit[--i] = 0;
while (--i >= 0)
result->digit[i] = src->digit[i];
}
@@ -194,7 +220,7 @@
v = new_longp_non_init(ndigits);
if (v != NULL) {
digit *p = v->digit;
- v->size = negative ? -ndigits : ndigits;
+ v->dsize = negative ? -ndigits : ndigits;
t = (unsigned long)ival;
while (t) {
*p++ = (digit)(t & MASK);
@@ -234,7 +260,7 @@
frac = ldexp(frac, SHIFT);
}
if (neg)
- v->size = -(v->size);
+ v->dsize = -(v->dsize);
return (long_p)v;
}
@@ -248,7 +274,7 @@
int i, sign;
v = (long_p) vv;
- i = v->size;
+ i = v->dsize;
sign = 1;
x = 0;
if (i < 0) {
@@ -276,13 +302,6 @@
return -1;
}
-int _PyLong_Sign(long_p vv)
-{
- long_p v = (long_p)vv;
- assert(v != NULL);
- return v->size == 0 ? 0 : (v->size < 0 ? -1 : 1);
-}
-
size_t
_PyLong_NumBits(long_p vv)
{
@@ -292,7 +311,7 @@
assert(v != NULL);
assert(PyLong_Check(v));
- ndigits = abs(v->size);
+ ndigits = abs(v->dsize);
assert(ndigits == 0 || v->digit[ndigits - 1] != 0);
if (ndigits > 0) {
digit msd = v->digit[ndigits - 1];
@@ -336,7 +355,7 @@
int nbitsneeded;
v = (long_p)vv;
- i = v->size;
+ i = v->dsize;
sign = 1;
if (i < 0) {
sign = -1;
@@ -394,9 +413,7 @@
* is modified in place, by adding y to it. Carries are propagated as far as
* x[m-1], and the remaining carry (0 or 1) is returned.
*/
-static digit
-v_iadd(digit *x, int m, digit *y, int n)
-{
+static digit v_iadd(digit *x, int m, digit *y, int n) {
int i;
digit carry = 0;
@@ -455,7 +472,7 @@
static long_p
muladd1(long_p a, wdigit n, wdigit extra)
{
- int size_a = abs(a->size);
+ int size_a = abs(a->dsize);
long_p z = new_longp_non_init(size_a+1);
twodigits carry = extra;
int i;
@@ -471,21 +488,21 @@
return long_normalize(z);
}
-/* Divide long pin, w/ size digits, by non-zero digit n, storing quotient
+/* Divide long pin, w/ dsize digits, by non-zero digit n, storing quotient
in pout, and returning the remainder. pin and pout point at the LSD.
It's OK for pin == pout on entry, which saves oodles of mallocs/frees in
long_format, but that should be done with great care since longs are
immutable. */
static digit
-inplace_divrem1(digit *pout, digit *pin, int size, digit n)
+inplace_divrem1(digit *pout, digit *pin, int dsize, digit n)
{
twodigits rem = 0;
assert(n > 0 && n <= MASK);
- pin += size;
- pout += size;
- while (--size >= 0) {
+ pin += dsize;
+ pout += dsize;
+ while (--dsize >= 0) {
digit hi;
rem = (rem << SHIFT) + *--pin;
*--pout = hi = (digit)(rem / n);
@@ -501,14 +518,14 @@
static long_p
divrem1(long_p a, digit n, digit *prem)
{
- const int size = abs(a->size);
+ const int dsize = abs(a->dsize);
long_p z;
assert(n > 0 && n <= MASK);
- z = new_longp_non_init(size);
+ z = new_longp_non_init(dsize);
if (z == NULL)
return NULL;
- *prem = inplace_divrem1(z->digit, a->digit, size, n);
+ *prem = inplace_divrem1(z->digit, a->digit, dsize, n);
return long_normalize(z);
}
@@ -519,7 +536,7 @@
register long_p a = (long_p) aa;
obj_p str;
int i;
- const int size_a = abs(a->size);
+ const int size_a = abs(a->dsize);
char *p;
int bits;
char sign = '\0';
@@ -540,10 +557,10 @@
p = pr_strptr(str) + i;
if (addL)
*--p = 'L';
- if (a->size < 0)
+ if (a->dsize < 0)
sign = '-';
- if (a->size == 0) {
+ if (a->dsize == 0) {
*--p = '0';
}
else if ((base & (base - 1)) == 0) {
@@ -574,7 +591,7 @@
/* Not 0, and base not a power of 2. Divide repeatedly by
base, but for speed use the highest power of base that
fits in a digit. */
- int size = size_a;
+ int dsize = size_a;
digit *pin = a->digit;
long_p scratch;
/* powbasw <- largest power of base that fits in a digit. */
@@ -589,7 +606,7 @@
}
/* Get a scratch area for repeated division. */
- scratch = new_longp_non_init(size);
+ scratch = new_longp_non_init(dsize);
if (scratch == NULL) {
pr_free(str);
return NULL;
@@ -599,10 +616,10 @@
do {
int ntostore = power;
digit rem = inplace_divrem1(scratch->digit,
- pin, size, powbase);
+ pin, dsize, powbase);
pin = scratch->digit; /* no need to use a again */
- if (pin[size - 1] == 0)
- --size;
+ if (pin[dsize - 1] == 0)
+ --dsize;
SIGCHECK({
pr_free(scratch);
pr_free(str);
@@ -622,8 +639,8 @@
/* Termination is a bit delicate: must not
store leading zeroes, so must get out if
remaining quotient and rem are both 0. */
- } while (ntostore && (size || rem));
- } while (size != 0);
+ } while (ntostore && (dsize || rem));
+ } while (dsize != 0);
pr_free(scratch);
}
@@ -797,8 +814,8 @@
return NULL;
if (str == start)
goto onError;
- if (sign < 0 && z != NULL && z->size != 0)
- z->size = -(z->size);
+ if (sign < 0 && z != NULL && z->dsize != 0)
+ z->dsize = -(z->dsize);
if (*str == 'L' || *str == 'l')
str++;
while (*str && isspace(Py_CHARMASK(*str)))
@@ -849,7 +866,7 @@
long_divrem(long_p a, long_p b,
long_p *pdiv, long_p *prem)
{
- int size_a = abs(a->size), size_b = abs(b->size);
+ int size_a = abs(a->dsize), size_b = abs(b->dsize);
long_p z;
if (size_b == 0) {
@@ -882,10 +899,10 @@
The quotient z has the sign of a*b;
the remainder r has the sign of a,
so a = b*z + r. */
- if ((a->size < 0) != (b->size < 0))
- z->size = -(z->size);
- if (a->size < 0 && (*prem)->size != 0)
- (*prem)->size = -((*prem)->size);
+ if ((a->dsize < 0) != (b->dsize < 0))
+ z->dsize = -(z->dsize);
+ if (a->dsize < 0 && (*prem)->dsize != 0)
+ (*prem)->dsize = -((*prem)->dsize);
*pdiv = z;
return 0;
}
@@ -895,8 +912,8 @@
static long_p
x_divrem(long_p v1, long_p w1, long_p *prem)
{
- int size_v = abs(v1->size), size_w = abs(w1->size);
- digit d = (digit) ((twodigits)BASE / (w1->digit[size_w-1] + 1));
+ int size_v = abs(v1->dsize), size_w = abs(w1->dsize);
+ digit d = (digit) ((twodigits)BASE / (w1->digit[size_w-1] + 1));
long_p v = mul1(v1, d);
long_p w = mul1(w1, d);
long_p a;
@@ -910,12 +927,12 @@
assert(size_v >= size_w && size_w > 1); /* Assert checks by div() */
assert(v->ob_refcnt == 1); /* Since v will be used as accumulator! */
- assert(size_w == abs(w->size)); /* That's how d was calculated */
+ assert(size_w == abs(w->dsize)); /* That's how d was calculated */
- size_v = abs(v->size);
+ size_v = abs(v->dsize);
a = new_longp_non_init(size_v - size_w + 1);
- for (j = size_v, k = a->size-1; a != NULL && k >= 0; --j, --k) {
+ for (j = size_v, k = a->dsize-1; a != NULL && k >= 0; --j, --k) {
digit vj = (j >= size_v) ? 0 : v->digit[j];
twodigits q;
stwodigits carry = 0;
@@ -996,63 +1013,30 @@
{
int sign;
- if (a->size != b->size) {
- if (abs(a->size) == 0 && abs(b->size) == 0)
+ if (a->dsize != b->dsize) {
+ if (abs(a->dsize) == 0 && abs(b->dsize) == 0)
sign = 0;
else
- sign = a->size - b->size;
+ sign = a->dsize - b->dsize;
}
else {
- int i = abs(a->size);
+ int i = abs(a->dsize);
while (--i >= 0 && a->digit[i] == b->digit[i])
;
if (i < 0)
sign = 0;
else {
sign = (int)a->digit[i] - (int)b->digit[i];
- if (a->size < 0)
+ if (a->dsize < 0)
sign = -sign;
}
}
return sign < 0 ? -1 : sign > 0 ? 1 : 0;
}
-static long
-long_hash(long_p v)
+static long_p x_add(long_p a, long_p b)
{
- long x;
- int i, sign;
-
- /* This is designed so that ints and longs with the
- same value hash to the same value, otherwise comparisons
- of mapping keys will turn out weird */
- i = v->size;
- sign = 1;
- x = 0;
- if (i < 0) {
- sign = -1;
- i = -(i);
- }
-#define LONG_BIT_SHIFT (8*sizeof(long) - SHIFT)
- while (--i >= 0) {
- /* Force a native long #-bits (32 or 64) circular shift */
- x = ((x << SHIFT) & ~MASK) | ((x >> LONG_BIT_SHIFT) & MASK);
- x += v->digit[i];
- }
-#undef LONG_BIT_SHIFT
- x = x * sign;
- if (x == -1)
- x = -2;
- return x;
-}
-
-
-/* Add the absolute values of two long integers. */
-
-static long_p
-x_add(long_p a, long_p b)
-{
- int size_a = abs(a->size), size_b = abs(b->size);
+ int size_a = abs(a->dsize), size_b = abs(b->dsize);
long_p z;
int i;
digit carry = 0;
@@ -1083,10 +1067,9 @@
/* Subtract the absolute values of two integers. */
-static long_p
-x_sub(long_p a, long_p b)
+static long_p x_sub(long_p a, long_p b)
{
- int size_a = abs(a->size), size_b = abs(b->size);
+ int size_a = abs(a->dsize), size_b = abs(b->dsize);
long_p z;
int i;
int sign = 1;
@@ -1132,28 +1115,27 @@
}
assert(borrow == 0);
if (sign < 0)
- z->size = -(z->size);
+ z->dsize = -(z->dsize);
return long_normalize(z);
}
-static long_p
-long_add(long_p v, long_p w)
+static long_p long_add(long_p v, long_p w)
{
long_p a, b, z;
CONVERT_BINOP((long_p)v, (long_p)w, &a, &b);
- if (a->size < 0) {
- if (b->size < 0) {
+ if (a->dsize < 0) {
+ if (b->dsize < 0) {
z = x_add(a, b);
- if (z != NULL && z->size != 0)
- z->size = -(z->size);
+ if (z != NULL && z->dsize != 0)
+ z->dsize = -(z->dsize);
}
else
z = x_sub(b, a);
}
else {
- if (b->size < 0)
+ if (b->dsize < 0)
z = x_sub(a, b);
else
z = x_add(a, b);
@@ -1163,23 +1145,22 @@
return (long_p)z;
}
-static long_p
-long_sub(long_p v, long_p w)
+static long_p long_sub(long_p v, long_p w)
{
long_p a, b, z;
CONVERT_BINOP((long_p)v, (long_p)w, &a, &b);
- if (a->size < 0) {
- if (b->size < 0)
+ if (a->dsize < 0) {
+ if (b->dsize < 0)
z = x_sub(a, b);
else
z = x_add(a, b);
- if (z != NULL && z->size != 0)
- z->size = -(z->size);
+ if (z != NULL && z->dsize != 0)
+ z->dsize = -(z->dsize);
}
else {
- if (b->size < 0)
+ if (b->dsize < 0)
z = x_add(a, b);
else
z = x_sub(a, b);
@@ -1192,19 +1173,18 @@
/* Grade school multiplication, ignoring the signs.
* Returns the absolute value of the product, or NULL if error.
*/
-static long_p
-x_mul(long_p a, long_p b)
+static long_p x_mul(long_p a, long_p b)
{
long_p z;
- int size_a = abs(a->size);
- int size_b = abs(b->size);
+ int size_a = abs(a->dsize);
+ int size_b = abs(b->dsize);
int i;
z = new_longp_non_init(size_a + size_b);
if (z == NULL)
return NULL;
- memset(z->digit, 0, z->size * sizeof(digit));
+ memset(z->digit, 0, z->dsize * sizeof(digit));
for (i = 0; i < size_a; ++i) {
twodigits carry = 0;
twodigits f = a->digit[i];
@@ -1221,7 +1201,7 @@
carry >>= SHIFT;
}
for (; carry != 0; ++j) {
- assert(i+j < z->size);
+ assert(i+j < z->dsize);
carry += *pz;
*pz++ = (digit) (carry & MASK);
carry >>= SHIFT;
@@ -1231,20 +1211,20 @@
}
/* A helper for Karatsuba multiplication (k_mul).
- Takes a long "n" and an integer "size" representing the place to
- split, and sets low and high such that abs(n) == (high << size) + low,
+ Takes a long "n" and an integer "dsize" representing the place to
+ split, and sets low and high such that abs(n) == (high << dsize) + low,
viewing the shift as being by digits. The sign bit is ignored, and
the return values are >= 0.
Returns 0 on success, -1 on failure.
*/
static int
-kmul_split(long_p n, int size, long_p *high, long_p *low)
+kmul_split(long_p n, int dsize, long_p *high, long_p *low)
{
long_p hi, lo;
int size_lo, size_hi;
- const int size_n = abs(n->size);
+ const int size_n = abs(n->dsize);
- size_lo = min(size_n, size);
+ size_lo = min(size_n, dsize);
size_hi = size_n - size_lo;
if ((hi = new_longp_non_init(size_hi)) == NULL)
@@ -1271,8 +1251,8 @@
static long_p
k_mul(long_p a, long_p b)
{
- int asize = abs(a->size);
- int bsize = abs(b->size);
+ int asize = abs(a->dsize);
+ int bsize = abs(b->dsize);
long_p ah = NULL;
long_p al = NULL;
long_p bh = NULL;
@@ -1287,7 +1267,7 @@
* Then the original product is
* ah*bh*X*X + (k - ah*bh - al*bl)*X + al*bl
* By picking X to be a power of 2, "*X" is just shifting, and it's
- * been reduced to 3 multiplies on numbers half the size.
+ * been reduced to 3 multiplies on numbers half the dsize.
*/
/* We want to split based on the larger number; fiddle so that b
@@ -1314,7 +1294,7 @@
/* If a is small compared to b, splitting on b gives a degenerate
* case with ah==0, and Karatsuba may be (even much) less efficient
* than "grade school" then. However, we can still win, by viewing
- * b as a string of "big digits", each of width a->size. That
+ * b as a string of "big digits", each of width a->dsize. That
* leads to a sequence of balanced calls to k_mul.
*/
if (2 * asize <= bsize)
@@ -1323,7 +1303,7 @@
/* Split a & b into hi & lo pieces. */
shift = bsize >> 1;
if (kmul_split(a, shift, &ah, &al) < 0) goto fail;
- assert(ah->size > 0); /* the split isn't degenerate */
+ assert(ah->dsize > 0); /* the split isn't degenerate */
if (kmul_split(b, shift, &bh, &bl) < 0) goto fail;
@@ -1348,20 +1328,20 @@
if (ret == NULL) goto fail;
#ifdef Py_DEBUG
/* Fill with trash, to catch reference to uninitialized digits. */
- memset(ret->digit, 0xDF, ret->size * sizeof(digit));
+ memset(ret->digit, 0xDF, ret->dsize * sizeof(digit));
#endif
/* 2. t1 <- ah*bh, and copy into high digits of result. */
if ((t1 = k_mul(ah, bh)) == NULL) goto fail;
- assert(t1->size >= 0);
- assert(2*shift + t1->size <= ret->size);
+ assert(t1->dsize >= 0);
+ assert(2*shift + t1->dsize <= ret->dsize);
memcpy(ret->digit + 2*shift, t1->digit,
- t1->size * sizeof(digit));
+ t1->dsize * sizeof(digit));
/* Zero-out the digits higher than the ah*bh copy. */
- i = ret->size - 2*shift - t1->size;
+ i = ret->dsize - 2*shift - t1->dsize;
if (i)
- memset(ret->digit + 2*shift + t1->size, 0,
+ memset(ret->digit + 2*shift + t1->dsize, 0,
i * sizeof(digit));
/* 3. t2 <- al*bl, and copy into the low digits. */
@@ -1369,23 +1349,23 @@
pr_free(t1);
goto fail;
}
- assert(t2->size >= 0);
- assert(t2->size <= 2*shift); /* no overlap with high digits */
- memcpy(ret->digit, t2->digit, t2->size * sizeof(digit));
+ assert(t2->dsize >= 0);
+ assert(t2->dsize <= 2*shift); /* no overlap with high digits */
+ memcpy(ret->digit, t2->digit, t2->dsize * sizeof(digit));
/* Zero out remaining digits. */
- i = 2*shift - t2->size; /* number of uninitialized digits */
+ i = 2*shift - t2->dsize; /* number of uninitialized digits */
if (i)
- memset(ret->digit + t2->size, 0, i * sizeof(digit));
+ memset(ret->digit + t2->dsize, 0, i * sizeof(digit));
/* 4 & 5. Subtract ah*bh (t1) and al*bl (t2). We do al*bl first
* because it's fresher in cache.
*/
- i = ret->size - shift; /* # digits after shift */
- (void)v_isub(ret->digit + shift, i, t2->digit, t2->size);
+ i = ret->dsize - shift; /* # digits after shift */
+ (void)v_isub(ret->digit + shift, i, t2->digit, t2->dsize);
pr_free(t2);
- (void)v_isub(ret->digit + shift, i, t1->digit, t1->size);
+ (void)v_isub(ret->digit + shift, i, t1->digit, t1->dsize);
pr_free(t1);
/* 6. t3 <- (ah+al)(bh+bl), and add into result. */
@@ -1406,12 +1386,12 @@
pr_free(t1);
pr_free(t2);
if (t3 == NULL) goto fail;
- assert(t3->size >= 0);
+ assert(t3->dsize >= 0);
/* Add t3. It's not obvious why we can't run out of room here.
* See the (*) comment after this function.
*/
- (void)v_iadd(ret->digit + shift, i, t3->digit, t3->size);
+ (void)v_iadd(ret->digit + shift, i, t3->digit, t3->dsize);
pr_free(t3);
return long_normalize(ret);
@@ -1442,7 +1422,7 @@
to fit into, = (by #1 and #2) asize + f(bsize/2) + c(bsize/2) - f(bsize/2) =
asize + c(bsize/2) available digit positions.
-bh has c(bsize/2) digits, and bl at most f(size/2) digits. So bh+hl has
+bh has c(bsize/2) digits, and bl at most f(dsize/2) digits. So bh+hl has
at most c(bsize/2) digits + 1 bit.
If asize == bsize, ah has c(bsize/2) digits, else ah has at most f(bsize/2)
@@ -1472,7 +1452,7 @@
/* b has at least twice the digits of a, and a is big enough that Karatsuba
* would pay off *if* the inputs had balanced sizes. View b as a sequence
- * of slices, each with a->size digits, and multiply the slices by a,
+ * of slices, each with a->dsize digits, and multiply the slices by a,
* one at a time. This gives k_mul balanced inputs to work with, and is
* also cache-friendly (we compute one double-width slice of the result
* at a time, then move on, never bactracking except for the helpful
@@ -1481,8 +1461,8 @@
static long_p
k_lopsided_mul(long_p a, long_p b)
{
- const int asize = abs(a->size);
- int bsize = abs(b->size);
+ const int asize = abs(a->dsize);
+ int bsize = abs(b->dsize);
int nbdone; /* # of b digits already multiplied */
long_p ret;
long_p bslice = NULL;
@@ -1494,7 +1474,7 @@
ret = new_longp_non_init(asize + bsize);
if (ret == NULL)
return NULL;
- memset(ret->digit, 0, ret->size * sizeof(digit));
+ memset(ret->digit, 0, ret->dsize * sizeof(digit));
/* Successive slices of b are copied into bslice. */
bslice = new_longp_non_init(asize);
@@ -1509,14 +1489,14 @@
/* Multiply the next slice of b by a. */
memcpy(bslice->digit, b->digit + nbdone,
nbtouse * sizeof(digit));
- bslice->size = nbtouse;
+ bslice->dsize = nbtouse;
product = k_mul(a, bslice);
if (product == NULL)
goto fail;
/* Add into result. */
- (void)v_iadd(ret->digit + nbdone, ret->size - nbdone,
- product->digit, product->size);
+ (void)v_iadd(ret->digit + nbdone, ret->dsize - nbdone,
+ product->digit, product->dsize);
pr_free(product);
bsize -= nbtouse;
@@ -1532,15 +1512,13 @@
return NULL;
}
-static long_p
-long_mul(long_p v, long_p w)
-{
+static long_p long_mul(long_p v, long_p w) {
long_p a=v, b=w, z;
z = k_mul(a, b);
/* Negate if exactly one of the inputs is negative. */
- if (((a->size ^ b->size) < 0) && z)
- z->size = -(z->size);
+ if (((a->dsize ^ b->dsize) < 0) && z)
+ z->dsize = -(z->dsize);
pr_free(a);
pr_free(b);
return (long_p)z;
@@ -1569,8 +1547,8 @@
if (long_divrem(v, w, &div, &mod) < 0)
return -1;
- if ((mod->size < 0 && w->size > 0) ||
- (mod->size > 0 && w->size < 0)) {
+ if ((mod->dsize < 0 && w->dsize > 0) ||
+ (mod->dsize > 0 && w->dsize < 0)) {
long_p temp;
long_p one;
temp = (long_p) long_add(mod, w);
@@ -1597,8 +1575,7 @@
return 0;
}
-static long_p
-long_div(long_p v, long_p w)
+static long_p long_div(long_p v, long_p w)
{
long_p a, b, div, mod;
@@ -1612,7 +1589,7 @@
pr_free(a);
pr_free(b);
pr_free(mod);
- return (long_p)div;
+ return (long_p) div;
}
static long_p
@@ -1670,8 +1647,7 @@
}
-static long_p
-long_mod(long_p v, long_p w)
+static long_p long_mod(long_p v, long_p w)
{
long_p a, b, div, mod;
@@ -1685,7 +1661,7 @@
pr_free(a);
pr_free(b);
pr_free(div);
- return (long_p)mod;
+ return (long_p) mod;
}
// w must be positive
@@ -1699,13 +1675,13 @@
CONVERT_BINOP(v, w, &a, &b);
c = x;
- if (c && ((long_p)c)->size == 0) {
+ if (c && ((long_p)c)->dsize == 0) {
raise_exception(ist, OBJ(VALUE_EXC),
"pow() 3rd argument cannot be 0");
z = NULL;
goto error;
}
- size_b = b->size;
+ size_b = b->dsize;
z = (long_p)new_longp(1);
for (i = 0; i < size_b; ++i) {
digit bi = b->digit[i];
@@ -1776,8 +1752,7 @@
return (long_p)z;
}
-static long_p
-long_invert(long_p v)
+static long_p long_invert(long_p v)
{
/* Implement ~x as -(x+1) */
long_p x;
@@ -1789,7 +1764,7 @@
pr_free(w);
if (x == NULL)
return NULL;
- x->size = -(x->size);
+ x->dsize = -(x->dsize);
return (long_p)x;
}
@@ -1802,7 +1777,7 @@
CONVERT_BINOP((long_p)v, (long_p)w, &a, &b);
- if (a->size < 0) {
+ if (a->dsize < 0) {
/* Right shifting negative numbers is harder */
long_p a1, a2;
a1 = (long_p) long_invert(a);
@@ -1824,7 +1799,7 @@
goto rshift_error;
}
wordshift = shiftby / SHIFT;
- newsize = abs(a->size) - wordshift;
+ newsize = abs(a->dsize) - wordshift;
if (newsize <= 0) {
z = new_longp_non_init(0);
pr_free(a);
@@ -1838,8 +1813,8 @@
z = new_longp_non_init((int)newsize);
if (z == NULL)
goto rshift_error;
- if (a->size < 0)
- z->size = -(z->size);
+ if (a->dsize < 0)
+ z->dsize = -(z->dsize);
for (i = 0, j = (int) wordshift; i < newsize; i++, j++) {
z->digit[i] = (a->digit[j] >> loshift) & lomask;
if (i+1 < newsize)
@@ -1881,15 +1856,15 @@
wordshift = (int)shiftby / SHIFT;
remshift = (int)shiftby - wordshift * SHIFT;
- oldsize = abs(a->size);
+ oldsize = abs(a->dsize);
newsize = oldsize + wordshift;
if (remshift)
++newsize;
z = new_longp_non_init(newsize);
if (z == NULL)
goto lshift_error;
- if (a->size < 0)
- z->size = -(z->size);
+ if (a->dsize < 0)
+ z->dsize = -(z->dsize);
for (i = 0; i < wordshift; i++)
z->digit[i] = 0;
accum = 0;
@@ -1912,8 +1887,7 @@
/* Bitwise and/xor/or operations */
-static long_p
-long_bitwise(long_p a,
+static long_p long_bitwise(long_p a,
int op, /* '&', '|', '^' */
long_p b)
{
@@ -1925,7 +1899,7 @@
digit diga, digb;
long_p v;
- if (a->size < 0) {
+ if (a->dsize < 0) {
a = (long_p) long_invert(a);
maska = MASK;
}
@@ -1933,7 +1907,7 @@
Py_INCREF(a);
maska = 0;
}
- if (b->size < 0) {
+ if (b->dsize < 0) {
b = (long_p) long_invert(b);
maskb = MASK;
}
@@ -1978,8 +1952,8 @@
whose length should be ignored.
*/
- size_a = a->size;
- size_b = b->size;
+ size_a = a->dsize;
+ size_b = b->dsize;
size_z = op == '&'
? (maska
? size_b
@@ -2013,9 +1987,7 @@
return v;
}
-static long_p
-long_and(long_p v, long_p w)
-{
+static long_p long_and(long_p v, long_p w) {
long_p a, b;
long_p c;
CONVERT_BINOP(v, w, &a, &b);
@@ -2025,8 +1997,7 @@
return c;
}
-static long_p
-long_xor(long_p v, long_p w)
+static long_p long_xor(long_p v, long_p w)
{
long_p a, b;
long_p c;
@@ -2037,8 +2008,7 @@
return c;
}
-static long_p
-long_or(long_p v, long_p w)
+static long_p long_or(long_p v, long_p w)
{
long_p a, b;
long_p c;
@@ -2049,12 +2019,40 @@
return c;
}
+static long long_hash(long_p v)
+{
+ long x;
+ int i, sign;
+ /* This is designed so that ints and longs with the
+ same value hash to the same value, otherwise comparisons
+ of mapping keys will turn out weird */
+ i = v->dsize;
+ sign = 1;
+ x = 0;
+ if (i < 0) {
+ sign = -1;
+ i = -(i);
+ }
+#define LONG_BIT_SHIFT (8*sizeof(long) - SHIFT)
+ while (--i >= 0) {
+ /* Force a native long #-bits (32 or 64) circular shift */
+ x = ((x << SHIFT) & ~MASK) | ((x >> LONG_BIT_SHIFT) & MASK);
+ x += v->digit[i];
+ }
+#undef LONG_BIT_SHIFT
+ x = x * sign;
+ if (x == -1)
+ x = -2;
+ return x;
+}
+
+
// ***************************** INT MODULE ***********************************
#define INT_DATA_SIZE 8
#define is_Int(objid) (has_proto(ist, objid, Int_OBJ))
-#define Int_value(objid) (objid->data.i64)
+#define int_imm_value(objid) (objid->data.i64)
static obj_p SYM_LIMIT;
@@ -2071,54 +2069,72 @@
/* Dependent objects */
OBJ(ZERO_INT) = NEW_INT(0);
- OBJ(MAX_INT) = NEW_INT(MAX_INT_VAL);
-
- OBJ(LONG_PROTO) = NEW_STRING("0");
- clr_immutable(OBJ(LONG_PROTO));
- set_obj_doc(OBJ(LONG_PROTO), "long integer number object prototype");
- set_obj_id(OBJ(LONG_PROTO), *, Long);
- set_immutable(OBJ(LONG_PROTO));
}
-DEF(Int, init_, FORM_STAR_PARAM) { // 9bd8c0 9a4760 0 0 9bd820
- i64_t i = 0;
+DEF(Int, init_, FORM_STAR_PARAM) {
+ obj_p i;
BIN_EMPTY_CHK();
if (list_len(ist, parms[1]))
- INT_64_PARAM(0,i);
- SET_TYPE_IF_EXC(Int_OBJ, self, DATA_TYPE_IMMDATA) return NULL;
- self->imm_data_len = IMMEDIATE_DATA_LEN;
- self->data.i64 = i;
+ INT____PARAM(0, i);
+ copy_object_data(ist, self, i);
return OBJ(NONE);
}
DEF(Int, str_, NULL){
char str[24];
BIN_STR_CHK(Int);
- apr_snprintf(str, sizeof(str), "%"APR_INT64_T_FMT, (i64_t)Int_value(self));
- return NEW_STRING(str);
+ if (self->data_type == DATA_TYPE_IMMDATA) {
+ apr_snprintf(str, sizeof(str), "%"APR_INT64_T_FMT, (i64_t)int_imm_value(self));
+ return NEW_STRING(str);
+ } else {
+ return long_format(self->data.ptr, 10, FALSE);
+ }
}
DEF(Int, bool__QUES, NULL) {
BIN_CONTENT_CHK(Int);
- if (Int_value(self)) return OBJ(PR_TRUE);
- else return OBJ(PR_FALSE);
+ if (self->data_type == DATA_TYPE_IMMDATA) {
+ if (int_imm_value(self)) return OBJ(PR_TRUE);
+ else return OBJ(PR_FALSE);
+ } else {
+ if (long_dsize(self)) return OBJ(PR_TRUE);
+ else return OBJ(PR_FALSE);
+ }
}
DEF(Int, hash_, NULL) {
- i32_t i32 = (i32_t) Int_value(self);
+ long_p v;
+ obj_p res;
BIN_CONTENT_CHK(Int);
- return new_hash_obj(ist, i32);
+ if (self->data_type == DATA_TYPE_IMMDATA) {
+ res = new_hash_obj(ist, long_hash(v = new_longp(int_imm_value(self))));
+ pr_free(v);
+ return res;
+ }
+ else
+ return new_hash_obj(ist, long_hash(self->data.ptr));
}
DEF(Int, abs_, NULL){
- i64_t num = Int_value(self);
BIN_CONTENT_CHK(Int);
- return NEW_INT(num < 0 ? -num : num);
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ return NEW_INT(abs(int_imm_value(self)));
+ else {
+ obj_p res = copy_object(ist, self);
+ long_dsize(res) = abs(long_dsize(res));
+ return res;
+ }
}
DEF(Int, neg_, NULL){
BIN_CONTENT_CHK(Int);
- return NEW_INT( - Int_value(self) );
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ return NEW_INT( - int_imm_value(self) );
+ else {
+ obj_p res = copy_object(ist, self);
+ long_dsize(res) = -long_dsize(res);
+ return res;
+ }
}
DEF(Int, pos_, NULL){
@@ -2128,6 +2144,9 @@
DEF(Int, add_, FORM_RPARAM){
obj_p other = parms[1];
+ i64_t siv;
+ i64_t oiv;
+
BIN_CONTENT_CHK(Int);
if (!is_Int(other)) {
if (covers(other, self))
@@ -2135,7 +2154,25 @@
raise_exception(ist, OBJ(TYPE_EXC), "Integer cannot be added to this object");
return OBJ(NONE);
}
- return NEW_INT(Int_value(self) + Int_value(other));
+ siv = int_imm_value(self);
+ oiv = int_imm_value(other);
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA &&
+ siv < MAX64 || oiv < MAX64 &&
+ siv > MIN64 || oiv > MIN64 )
+ return NEW_INT(siv+oiv);
+ else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(siv);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(oiv);
+ else
+ b = other->data.ptr;
+ return new_int_long_obj(ist, long_add(a,b));
+ }
}
DEF(Int, div_, FORM_RPARAM){
@@ -2148,7 +2185,7 @@
raise_exception(ist, OBJ(TYPE_EXC), "Integer cannot be divided by this object");
return OBJ(NONE);
}
- float_self = call_func1(ist, OBJ(FLOAT_PROTO), SYM(COERCE_), self); if_exc_return NULL;
+ float_self = call_func1(ist, OBJ(FLOAT_PROTO), SYM(COERCE_), self); if_exc_return NULL;
float_other = call_func1(ist, OBJ(FLOAT_PROTO), SYM(COERCE_), other); if_exc_return NULL;
res = call_func1(ist, float_self, SYM(DIV_), float_other);
del_unlock(float_self); del_unlock(float_other);
@@ -2164,11 +2201,25 @@
raise_exception(ist, OBJ(TYPE_EXC), "Integer cannot be floor divided by this object");
return OBJ(NONE);
}
- if (Int_value(other) == 0) {
- raise_exception(ist, OBJ(DIVIDEZERO_EXC), NULL);
- return NULL;
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA ) {
+ if (int_imm_value(other) == 0) {
+ raise_exception(ist, OBJ(DIVIDEZERO_EXC), NULL);
+ return NULL;
+ }
+ return NEW_INT(int_imm_value(self) / int_imm_value(other));
+ } else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(self->data.i64);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(other->data.i64);
+ else
+ b = other->data.ptr;
+ return new_int_long_obj(ist, long_div(a,b));
}
- return NEW_INT(Int_value(self) / Int_value(other));
}
DEF(Int, mod_, FORM_RPARAM) {
@@ -2180,15 +2231,32 @@
raise_exception(ist, OBJ(TYPE_EXC), "Integer cannot be modded by this object");
return OBJ(NONE);
}
- if (Int_value(other) == 0) {
- raise_exception(ist, OBJ(DIVIDEZERO_EXC), "modulo by zero");
- return NULL;
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA ) {
+ if (int_imm_value(other) == 0) {
+ raise_exception(ist, OBJ(DIVIDEZERO_EXC), "modulo by zero");
+ return NULL;
+ }
+ return NEW_INT(int_imm_value(self) % int_imm_value(other));
+ } else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(self->data.i64);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(other->data.i64);
+ else
+ b = other->data.ptr;
+ return new_int_long_obj(ist, long_mod(a,b));
}
- return NEW_INT(Int_value(self) % Int_value(other));
}
-DEF(Int, mul_, FORM_RPARAM) {
+DEF(Int, mul_, FORM_RPARAM){
obj_p other = parms[1];
+ i64_t siv;
+ i64_t oiv;
+
BIN_CONTENT_CHK(Int);
if (!is_Int(other)) {
if (covers(other, self))
@@ -2196,30 +2264,82 @@
raise_exception(ist, OBJ(TYPE_EXC), "Integer cannot be multiplied by this object");
return OBJ(NONE);
}
- return NEW_INT(Int_value(self) * Int_value(other));
+ siv = int_imm_value(self);
+ oiv = int_imm_value(other);
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA &&
+ siv < MAX32 && oiv < MAX32 && siv > MIN32 && oiv > MIN32 )
+ return NEW_INT(siv*oiv);
+ else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(siv);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(oiv);
+ else
+ b = other->data.ptr;
+ return new_int_long_obj(ist, long_mul(a,b));
+ }
}
-DEF(Int, sub_, FORM_RPARAM) {
+DEF(Int, sub_, FORM_RPARAM){
obj_p other = parms[1];
+ i64_t siv;
+ i64_t oiv;
+
BIN_CONTENT_CHK(Int);
if (!is_Int(other)) {
if (covers(other, self))
return call_func1(ist, other, SYM(RSUB_), self);
- raise_exception(ist, OBJ(TYPE_EXC), "This object cannot be subtracted from an Integer");
+ raise_exception(ist, OBJ(TYPE_EXC), "Integer cannot be subtracted from this object");
return OBJ(NONE);
}
- return NEW_INT(Int_value(self) - Int_value(other));
+ siv = int_imm_value(self);
+ oiv = int_imm_value(other);
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA &&
+ siv < MAX64 && oiv < MAX64 && siv > MIN64 && oiv > MIN64 )
+ return NEW_INT(siv-oiv);
+ else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(siv);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(oiv);
+ else
+ b = other->data.ptr;
+ return new_int_long_obj(ist, long_sub(a,b));
+ }
}
DEF(Int, pow_, FORM_RPARAM){
- obj_p res;
- obj_p float_self, float_other, other = parms[1];
+ obj_p res, other = parms[1], float_self, float_other;
+ long_p a, b;
+ int iso = 0;
+
BIN_CONTENT_CHK(Int);
- float_self = call_func1(ist, OBJ(FLOAT_PROTO), SYM(COERCE_), self); if_exc_return NULL;
- float_other = call_func1(ist, OBJ(FLOAT_PROTO), SYM(COERCE_), other); if_exc_return NULL;
- res = call_func1(ist, float_self, SYM(POW_), float_other);
- del_unlock(float_self); del_unlock(float_other);
- return res;
+ if (!is_Int(other) || (iso = int_sign(other)) < 0) {
+ float_self = call_func1(ist, OBJ(FLOAT_PROTO), SYM(COERCE_), self); if_exc_return NULL;
+ float_other = call_func1(ist, OBJ(FLOAT_PROTO), SYM(COERCE_), other); if_exc_return NULL;
+ res = call_func1(ist, float_self, SYM(POW_), float_other);
+ del_unlock(float_self); del_unlock(float_other);
+ return res;
+ }
+ if (!iso) return NEW_INT(1);
+
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(self->data.i64);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(other->data.i64);
+ else
+ b = other->data.ptr;
+ return new_int_long_obj(ist, long_pow(a, b, NULL));
}
DEF(Int, cmp, FORM_RPARAM){
@@ -2231,12 +2351,26 @@
raise_exception(ist, OBJ(TYPE_EXC), "This object cannot be compared to an Integer");
return OBJ(NONE);
}
- if (Int_value(self) == Int_value(other))
- return NEW_INT(0);
- else if (Int_value(self) > Int_value(other))
- return NEW_INT(1);
- else
- return NEW_INT(-1);
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA ) {
+ if (int_imm_value(self) == int_imm_value(other))
+ return NEW_INT(0);
+ else if (int_imm_value(self) > int_imm_value(other))
+ return NEW_INT(1);
+ else
+ return NEW_INT(-1);
+ } else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(self->data.i64);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(other->data.i64);
+ else
+ b = other->data.ptr;
+ return NEW_INT(long_compare(a,b));
+ }
}
DEF(Int, eq__QUES, FORM_RPARAM){
@@ -2249,12 +2383,30 @@
if (c) return call_func1(ist, other, SYM(EQ__QUES), self);
return OBJ(PR_FALSE);
}
- if (Int_value(self) == Int_value(other)) return OBJ(PR_TRUE);
- else return OBJ(PR_FALSE);
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA ) {
+ if (int_imm_value(self) == int_imm_value(other)) return OBJ(PR_TRUE);
+ else return OBJ(PR_FALSE);
+ } else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(self->data.i64);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(other->data.i64);
+ else
+ b = other->data.ptr;
+ if (long_compare(a,b)) return OBJ(PR_FALSE);
+ else return OBJ(PR_TRUE);
+ }
}
DEF(Int, invert_, NULL){
BIN_CONTENT_CHK(Int);
- return NEW_INT( ~ Int_value(self) );
+ if ( self->data_type == DATA_TYPE_IMMDATA)
+ return NEW_INT( ~ int_imm_value(self) );
+ else
+ return new_int_long_obj(ist, long_invert(self->data.ptr));
}
DEF(Int, xor_, FORM_RPARAM) {
@@ -2264,7 +2416,21 @@
raise_exception(ist, OBJ(TYPE_EXC), "object cannot be xor'd with an Integer");
return OBJ(NONE);
}
- return NEW_INT(Int_value(self) ^ Int_value(other));
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA ) {
+ return NEW_INT(int_imm_value(self) ^ int_imm_value(other));
+ } else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(self->data.i64);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(other->data.i64);
+ else
+ b = other->data.ptr;
+ return new_int_long_obj(ist, long_xor(a, b));
+ }
}
DEF(Int, and_, FORM_RPARAM) {
@@ -2274,7 +2440,21 @@
raise_exception(ist, OBJ(TYPE_EXC), "object cannot be and'd with an Integer");
return OBJ(NONE);
}
- return NEW_INT(Int_value(self) & Int_value(other));
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA ) {
+ return NEW_INT(int_imm_value(self) & int_imm_value(other));
+ } else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(self->data.i64);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(other->data.i64);
+ else
+ b = other->data.ptr;
+ return new_int_long_obj(ist, long_and(a, b));
+ }
}
DEF(Int, or_, FORM_RPARAM) {
@@ -2284,27 +2464,77 @@
raise_exception(ist, OBJ(TYPE_EXC), "object cannot be or'd with an Integer");
return OBJ(NONE);
}
- return NEW_INT(Int_value(self) | Int_value(other));
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA ) {
+ return NEW_INT(int_imm_value(self) | int_imm_value(other));
+ } else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(self->data.i64);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(other->data.i64);
+ else
+ b = other->data.ptr;
+ return new_int_long_obj(ist, long_or(a, b));
+ }
}
DEF(Int, rShift_, FORM_RPARAM) {
obj_p other = parms[1];
+ i64_t siv, oiv;
BIN_CONTENT_CHK(Int);
if (!is_Int(other)) {
raise_exception(ist, OBJ(TYPE_EXC), "object cannot be shifted with an Integer");
return OBJ(NONE);
}
- return NEW_INT(Int_value(self) >> Int_value(other));
+ siv = int_imm_value(self);
+ oiv = int_imm_value(other);
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA &&
+ siv < MAX32 && siv > MIN32 && oiv > -32 )
+ return NEW_INT(int_imm_value(self) >> int_imm_value(other));
+ else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(self->data.i64);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(other->data.i64);
+ else
+ b = other->data.ptr;
+ return new_int_long_obj(ist, long_rshift(a, b));
+ }
}
DEF(Int, lShift_, FORM_RPARAM) {
obj_p other = parms[1];
+ i64_t siv, oiv;
BIN_CONTENT_CHK(Int);
if (!is_Int(other)) {
raise_exception(ist, OBJ(TYPE_EXC), "object cannot be shifted with an Integer");
return OBJ(NONE);
}
- return NEW_INT(Int_value(self) << Int_value(other));
+ siv = int_imm_value(self);
+ oiv = int_imm_value(other);
+ if ( self->data_type == DATA_TYPE_IMMDATA &&
+ other->data_type == DATA_TYPE_IMMDATA &&
+ siv < MAX32 && siv > MIN32 && oiv < 32 )
+ return NEW_INT(int_imm_value(self) << int_imm_value(other));
+ else {
+ long_p a, b;
+ if (self->data_type == DATA_TYPE_IMMDATA)
+ a = new_longp(self->data.i64);
+ else
+ a = self->data.ptr;
+ if (other->data_type == DATA_TYPE_IMMDATA)
+ b = new_longp(other->data.i64);
+ else
+ b = other->data.ptr;
+ return new_int_long_obj(ist, long_lshift(a, b));
+ }
}
DEF(Int, iter_, NULL) {
@@ -2319,7 +2549,7 @@
DEF(Int, chr, NULL) {
char s[1];
BIN_CONTENT_CHK(Int);
- s[0] = (char) Int_value(self);
+ s[0] = (char) int_imm_value(self);
return NEW_STRINGN(s, 1);
}
@@ -2335,7 +2565,7 @@
obj_p limit, res;
BIN_CONTENT_CHK(IntGen);
if ( !(limit=get_attr(ist, self, SYM_LIMIT)) ||
- Int_value(self) == Int_value(limit) ) {
+ int_imm_value(self) == int_imm_value(limit) ) {
if (limit) {
read_unlock(ist, self);
del_attr(ist, self, SYM_LIMIT);
@@ -2344,9 +2574,9 @@
raise_exception(ist, OBJ(STOP_ITERATION_EXC), NULL);
return NULL;
}
- res = NEW_INT(Int_value(self));
+ res = NEW_INT(int_imm_value(self));
def_write_lock(self);
- Int_value(self)++;
+ int_imm_value(self)++;
def_write_unlock(self);
return res;
}
Modified: trunk/src/builtins-string.c
===================================================================
--- trunk/src/builtins-string.c 2004-05-28 05:50:02 UTC (rev 560)
+++ trunk/src/builtins-string.c 2004-05-28 20:57:33 UTC (rev 561)
@@ -482,7 +482,7 @@
return changeCase(ist,self,&toupper,AT_WORD_START);
}
-#define Int_value(objid) (objid->data.i64)
+#define int_imm_value(objid) (objid->data.i64)
DEF(String, find, FPARM2( stringToFind, NULL, indexToStartLooking, NEW_INT(0) )) {
size_t str_len = pr_strlen(self);
size_t find_len = 0;
@@ -500,7 +500,7 @@
raise_exception(ist, OBJ(TYPE_EXC), "find function parameter 2 must be an integer");
return NULL;
} else {
- start = (size_t)Int_value(parms[3]);
+ start = (size_t)int_imm_value(parms[3]);
}
find_ptr = pr_strptr(parms[1]);
@@ -508,7 +508,7 @@
if (find_len<1) {
return new_int_obj(ist,0);
}
- found = bin_strstr(pr_strptr(self)+Int_value(parms[3]),str_len,find_ptr,find_len);
+ found = bin_strstr(pr_strptr(self)+int_imm_value(parms[3]),str_len,find_ptr,find_len);
if (found) {
result = new_int_obj(ist,found-pr_strptr(self));
} else {
Modified: trunk/src/parser.h
===================================================================
--- trunk/src/parser.h 2004-05-28 05:50:02 UTC (rev 560)
+++ trunk/src/parser.h 2004-05-28 20:57:33 UTC (rev 561)
@@ -204,7 +204,7 @@
code_p star_seq_to_param(void* param, code_p expr);
code_p star_star_dict_to_param(void* param, code_p expr);
code_p star_star_ref_to_formparm(void* param, obj_p label);
-code_p string_to_obj(void* param, obj_p str, int long_flag);
+code_p string_to_obj(void* param, obj_p str);
code_p tgt_eq_expr_to_stmt(void* param, clist_p left, clist_p right);
code_p tgt_eq_stmt_to_stmt(void* param, clist_p left, code_p right);
code_p tgtparm_to_obj(void* param, code_p expr);
Modified: trunk/src/parser_routines.c
===================================================================
--- trunk/src/parser_routines.c 2004-05-28 05:50:02 UTC (rev 560)
+++ trunk/src/parser_routines.c 2004-05-28 20:57:33 UTC (rev 561)
@@ -1487,11 +1487,11 @@
add_to_const_list(param, obj);
return debug_retrn(__LINE__, res);
}
-code_p string_to_obj(void* param, obj_p str, int long_flag){
+code_p string_to_obj(void* param, obj_p str){
code_p p = new_code(param, 2, 1, 1, OP_PUSH);
pr_str_p obj_str;
size_t len = pr_strlen(str);
- obj_p proto = (long_flag == NEW_LONG? OBJ(LONG_PROTO) : OBJ(STRING_PROTO));
+ obj_p proto = OBJ(STRING_PROTO);
obj_p obj = new_object(IST, proto);
if (len < IMMEDIATE_DATA_LEN) {
obj->data_type = DATA_TYPE_IMMDATA;
Modified: trunk/src/prothon.y
===================================================================
--- trunk/src/prothon.y 2004-05-28 05:50:02 UTC (rev 560)
+++ trunk/src/prothon.y 2004-05-28 20:57:33 UTC (rev 561)
@@ -547,7 +547,6 @@
SELF { $$ = self_to_obj(yylex_param); }
| CALLER { $$ = caller_to_obj(yylex_param); }
| INT_ { $$ = int_to_obj(yylex_param, $1); }
- | LONG_ { $$ = string_to_obj(yylex_param, $1, NEW_LONG); }
| FLOAT_ { $$ = float_to_obj(yylex_param, $1, NEW_REAL); }
| INT_IMAG { $$ = float_to_obj(yylex_param, (double) $1, NEW_IMAG); }
| FLOAT_IMAG { $$ = float_to_obj(yylex_param, $1, NEW_IMAG); }
@@ -1158,7 +1157,7 @@
}
/* process dot, int, or float */
if (c == '.' || (c >= '0' && c <= '9') ) {
- int imag_flag=0, long_flag=0, nonzero_flag=0, past_e_flag=0;
+ int imag_flag=0, nonzero_flag=0, past_e_flag=0;
int hex_flag=0, int_dot_flag=0;
int str_index=0, cur_size=INITIAL_STRING_ALLOC;
char* str_ptr = pr_malloc(cur_size);
@@ -1187,8 +1186,7 @@
add_string(c, &str_ptr, &str_index, &cur_size);
if (c == 'x' || c == 'X')
hex_flag = 1;
- if ( (imag_flag = (c == 'j' || c == 'J')) ||
- (long_flag = (c == 'l' || c == 'L')) )
+ if (imag_flag = (c == 'j' || c == 'J'))
break;
if (c != '0' && c != 'x' && c != 'X')
nonzero_flag = 1;
@@ -1201,16 +1199,11 @@
}
if (hex_flag || int_dot_flag || (c != '.' && c != 'e' && c != 'E')){
char* p;
- if (imag_flag || long_flag)
+ if (imag_flag)
str_index--;
else
ungetch(c, state);
str_ptr[str_index++]=0;
- if (long_flag){
- str_ptr = pr_realloc(str_ptr, str_index);
- lvalp->str_type = new_string_n_obj((((parse_state*) yylex_param)->ist), str_ptr, str_index-1);
- return LONG_;
- }
if (str_ptr[0] == '0') {
if (hex_flag){
u64_t val = 0;