From 7d3a511a40a8c90eac66d3d59edbbe3c3d4559b1 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Sat, 8 Jul 2000 04:17:21 +0000 Subject: [PATCH] Cray J90 fixes for long ints. This was a convenient excuse to create the pyport.h file recently discussed! Please use new Py_ARITHMETIC_RIGHT_SHIFT when right-shifting a signed int and you *need* sign-extension. This is #define'd in pyport.h, keying off new config symbol SIGNED_RIGHT_SHIFT_ZERO_FILLS. If you're running on a platform that needs that symbol #define'd, the std tests never would have worked for you (in particular, at least test_long would have failed). The autoconfig stuff got added to Python after my Unix days, so I don't know how that works. Would someone please look into doing & testing an auto-config of the SIGNED_RIGHT_SHIFT_ZERO_FILLS symbol? It needs to be defined if & only if, e.g., (-1) >> 3 is not -1. --- Include/Python.h | 1 + Include/longintrepr.h | 7 +++--- Include/pyport.h | 57 +++++++++++++++++++++++++++++++++++++++++++ Objects/intobject.c | 5 +--- Objects/longobject.c | 13 ++++++---- acconfig.h | 5 ++++ 6 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 Include/pyport.h diff --git a/Include/Python.h b/Include/Python.h index 3389c0a41d8..b36b5daeae0 100644 --- a/Include/Python.h +++ b/Include/Python.h @@ -31,6 +31,7 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. #include "patchlevel.h" #include "config.h" +#include "pyport.h" /* config.h may or may not define DL_IMPORT */ #ifndef DL_IMPORT /* declarations for DLL import/export */ diff --git a/Include/longintrepr.h b/Include/longintrepr.h index 4ddbd06e59c..fed01ed8b1f 100644 --- a/Include/longintrepr.h +++ b/Include/longintrepr.h @@ -18,7 +18,7 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. /* Parameters of the long integer representation. These shouldn't have to be changed as C should guarantee that a short - contains at least 16 bits, but it's made changeable any way. + contains at least 16 bits, but it's made changeable anyway. Note: 'digit' should be able to hold 2*MASK+1, and 'twodigits' should be able to hold the intermediate results in 'mul' (at most MASK << SHIFT). @@ -28,8 +28,9 @@ redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. typedef unsigned short digit; typedef unsigned int wdigit; /* digit widened to parameter size */ -typedef unsigned long twodigits; -typedef long stwodigits; /* signed variant of twodigits */ +#define BASE_TWODIGITS_TYPE long +typedef unsigned BASE_TWODIGITS_TYPE twodigits; +typedef BASE_TWODIGITS_TYPE stwodigits; /* signed variant of twodigits */ #define SHIFT 15 #define BASE ((digit)1 << SHIFT) diff --git a/Include/pyport.h b/Include/pyport.h new file mode 100644 index 00000000000..558b17dab15 --- /dev/null +++ b/Include/pyport.h @@ -0,0 +1,57 @@ +/*********************************************************** +Copyright (c) 2000, BeOpen.com. +All rights reserved. + +See the file "Misc/COPYRIGHT" for information on usage and +redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. +******************************************************************/ + +#ifndef Py_PYPORT_H +#define Py_PYPORT_H 1 + +/************************************************************************** +Symbols and macros to supply platform-independent interfaces to basic +C-language operations whose spellings vary across platforms. + +Please try to make documentation here as clear as possible: by definition, +the stuff here is trying to illuminate C's darkest corners. + +Config #defines referenced here: + +SIGNED_RIGHT_SHIFT_ZERO_FILLS +Meaning: To be defined iff i>>j does not extend the sign bit when i is a + signed integral type and i < 0. +Used in: Py_ARITHMETIC_RIGHT_SHIFT +**************************************************************************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Py_ARITHMETIC_RIGHT_SHIFT + * C doesn't define whether a right-shift of a signed integer sign-extends + * or zero-fills. Here a macro to force sign extension: + * Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) + * Return I >> J, forcing sign extension. + * Requirements: + * I is of basic signed type TYPE (char, short, int, long, or long long). + * TYPE is one of char, short, int, long, or long long, although long long + * must not be used except on platforms that support it. + * J is an integer >= 0 and strictly less than the number of bits in TYPE + * (because C doesn't define what happens for J outside that range either). + * Caution: + * I may be evaluated more than once. + */ +#ifdef SIGNED_RIGHT_SHIFT_ZERO_FILLS +#define Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) \ + ((I) < 0 ? ~((~(unsigned TYPE)(I)) >> (J)) : (I) >> (J)) +#else +#define Py_ARITHMETIC_RIGHT_SHIFT(TYPE, I, J) ((I) >> (J)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* Py_PYPORT_H */ diff --git a/Objects/intobject.c b/Objects/intobject.c index ba3dde1b738..a5dc134562a 100644 --- a/Objects/intobject.c +++ b/Objects/intobject.c @@ -721,10 +721,7 @@ int_rshift(v, w) a = 0; } else { - if (a < 0) - a = ~( ~(unsigned long)a >> b ); - else - a = (unsigned long)a >> b; + a = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); } return PyInt_FromLong(a); } diff --git a/Objects/longobject.c b/Objects/longobject.c index a28dbaf34d7..df3c6a58860 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -571,7 +571,8 @@ long_format(PyObject *aa, int base, int addL) int last = abs(a->ob_size); int basebits = 1; i = base; - while ((i >>= 1) > 1) ++basebits; + while ((i >>= 1) > 1) + ++basebits; i = 0; for (;;) { @@ -853,7 +854,9 @@ x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem) carry += v->ob_digit[i+k] - z + ((twodigits)zz << SHIFT); v->ob_digit[i+k] = carry & MASK; - carry = (carry >> SHIFT) - zz; + carry = Py_ARITHMETIC_RIGHT_SHIFT(BASE_TWODIGITS_TYPE, + carry, SHIFT); + carry -= zz; } if (i+k < size_v) { @@ -870,7 +873,9 @@ x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem) for (i = 0; i < size_w && i+k < size_v; ++i) { carry += v->ob_digit[i+k] + w->ob_digit[i]; v->ob_digit[i+k] = carry & MASK; - carry >>= SHIFT; + carry = Py_ARITHMETIC_RIGHT_SHIFT( + BASE_TWODIGITS_TYPE, + carry, SHIFT); } } } /* for j, k */ @@ -988,8 +993,6 @@ x_add(PyLongObject *a, PyLongObject *b) for (i = 0; i < size_b; ++i) { carry += a->ob_digit[i] + b->ob_digit[i]; z->ob_digit[i] = carry & MASK; - /* The following assumes unsigned shifts don't - propagate the sign bit. */ carry >>= SHIFT; } for (; i < size_a; ++i) { diff --git a/acconfig.h b/acconfig.h index ab775e9cbb4..210f38143b0 100644 --- a/acconfig.h +++ b/acconfig.h @@ -169,5 +169,10 @@ /* Defined when any dynamic module loading is enabled */ #undef HAVE_DYNAMIC_LOADING +/* Define if i>>j for signed int i does not extend the sign bit + when i < 0 +*/ +#undef SIGNED_RIGHT_SHIFT_ZERO_FILLS + /* Leave that blank line there-- autoheader needs it! */