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;