Commit 9eff1d3b authored by Robert Bradshaw's avatar Robert Bradshaw

Merge branch 'int-conversion'

parents 73e5cb51 1cbf6ba0
......@@ -3020,6 +3020,7 @@ class IndexNode(ExprNode):
else:
self.is_temp = 1
self.index = self.index.coerce_to(PyrexTypes.c_py_ssize_t_type, env).coerce_to_simple(env)
self.original_index_type.create_to_py_utility_code(env)
else:
self.index = self.index.coerce_to_pyobject(env)
self.is_temp = 1
......
......@@ -592,6 +592,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('#define __Pyx_PyObject_FromStringAndSize __Pyx_Py%s_FromStringAndSize' % c_string_type.title())
code.put(UtilityCode.load_as_string("TypeConversions", "TypeConversion.c")[0])
# These utility functions are assumed to exist and used elsewhere.
PyrexTypes.c_long_type.create_to_py_utility_code(env)
PyrexTypes.c_long_type.create_from_py_utility_code(env)
PyrexTypes.c_int_type.create_from_py_utility_code(env)
code.put(Nodes.branch_prediction_macros)
code.putln('')
code.putln('static PyObject *%s;' % env.module_cname)
......@@ -606,12 +611,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('static const char * %s= %s;' % (Naming.cfilenm_cname, Naming.file_c_macro))
code.putln('static const char *%s;' % Naming.filename_cname)
# XXX this is a mess
for utility_code in PyrexTypes.c_int_from_py_function.specialize_list:
env.use_utility_code(utility_code)
for utility_code in PyrexTypes.c_long_from_py_function.specialize_list:
env.use_utility_code(utility_code)
def generate_extern_c_macro_definition(self, code):
name = Naming.extern_c_macro
code.putln("#ifndef %s" % name)
......
This diff is collapsed.
......@@ -64,7 +64,7 @@ class TreeVisitor(object):
self.access_path = []
def dump_node(self, node, indent=0):
ignored = list(node.child_attrs) + [u'child_attrs', u'pos',
ignored = list(node.child_attrs or []) + [u'child_attrs', u'pos',
u'gil_message', u'cpp_message',
u'subexprs']
values = []
......
......@@ -51,7 +51,7 @@
#define PY_FORMAT_SIZE_T ""
#define CYTHON_FORMAT_SSIZE_T ""
#define PyInt_FromSsize_t(z) PyInt_FromLong(z)
#define PyInt_AsSsize_t(o) __Pyx_PyInt_AsInt(o)
#define PyInt_AsSsize_t(o) __Pyx_PyInt_As_int(o)
#define PyNumber_Index(o) ((PyNumber_Check(o) && !PyFloat_Check(o)) ? PyNumber_Int(o) : \
(PyErr_Format(PyExc_TypeError, \
"expected index value, got %.200s", Py_TYPE(o)->tp_name), \
......
......@@ -45,10 +45,6 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
static CYTHON_INLINE PyObject * __Pyx_PyInt_FromPtrdiff_t(ptrdiff_t);
static CYTHON_INLINE ptrdiff_t __Pyx_PyInt_AsPtrdiff_t(PyObject*);
#if CYTHON_COMPILING_IN_CPYTHON
#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
......@@ -281,37 +277,6 @@ static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
#endif
}
static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) {
unsigned PY_LONG_LONG val = __Pyx_PyInt_AsUnsignedLongLong(x);
if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) {
if ((val != (unsigned PY_LONG_LONG)-1) || !PyErr_Occurred())
PyErr_SetString(PyExc_OverflowError,
"value too large to convert to size_t");
return (size_t)-1;
}
return (size_t)val;
}
static CYTHON_INLINE PyObject * __Pyx_PyInt_FromPtrdiff_t(ptrdiff_t ival) {
if (LONG_MIN < ival && ival <= LONG_MAX)
return PyInt_FromLong((long)ival);
else {
unsigned char *bytes = (unsigned char *) &ival;
int one = 1; int little = (int)*(unsigned char*)&one;
return _PyLong_FromByteArray(bytes, sizeof(ptrdiff_t), little, 0);
}
}
static CYTHON_INLINE ptrdiff_t __Pyx_PyInt_AsPtrdiff_t(PyObject* x) {
unsigned PY_LONG_LONG val = __Pyx_PyInt_AsLongLong(x);
if (unlikely(val != (unsigned PY_LONG_LONG)(ptrdiff_t)val)) {
if ((val != (unsigned PY_LONG_LONG)-1) || !PyErr_Occurred())
PyErr_SetString(PyExc_OverflowError,
"value too large to convert to size_t");
return (ptrdiff_t)-1;
}
return (ptrdiff_t)val;
}
/////////////// FromPyStructUtility.proto ///////////////
{{struct_type_decl}};
......@@ -386,7 +351,7 @@ static CYTHON_INLINE Py_UCS4 __Pyx_PyObject_AsPy_UCS4(PyObject* x) {
"got length %" CYTHON_FORMAT_SSIZE_T "d", length);
return (Py_UCS4)-1;
}
ival = __Pyx_PyInt_AsLong(x);
ival = __Pyx_PyInt_As_long(x);
if (unlikely(ival < 0)) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_OverflowError,
......@@ -434,7 +399,7 @@ static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) {
if (unlikely(!maxval))
maxval = (long)PyUnicode_GetMax();
#endif
ival = __Pyx_PyInt_AsLong(x);
ival = __Pyx_PyInt_As_long(x);
}
if (unlikely(ival < 0)) {
if (!PyErr_Occurred())
......@@ -448,3 +413,163 @@ static CYTHON_INLINE Py_UNICODE __Pyx_PyObject_AsPy_UNICODE(PyObject* x) {
}
return (Py_UNICODE)ival;
}
/////////////// CIntToPy.proto ///////////////
static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value);
/////////////// CIntToPy ///////////////
static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value) {
const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = 0;
const int is_unsigned = neg_one > const_zero;
if (is_unsigned) {
if (sizeof({{TYPE}}) < sizeof(unsigned long)) {
return PyInt_FromLong(value);
} else if (sizeof({{TYPE}}) <= sizeof(unsigned long)) {
return PyLong_FromUnsignedLong(value);
} else if (sizeof({{TYPE}}) <= sizeof(unsigned long long)) {
return PyLong_FromUnsignedLongLong(value);
}
} else {
if (sizeof({{TYPE}}) <= sizeof(long)) {
return PyInt_FromLong(value);
} else if (sizeof({{TYPE}}) <= sizeof(long long)) {
return PyLong_FromLongLong(value);
}
}
{
int one = 1; int little = (int)*(unsigned char *)&one;
unsigned char *bytes = (unsigned char *)&value;
return _PyLong_FromByteArray(bytes, sizeof({{TYPE}}),
little, !is_unsigned);
}
}
/////////////// CIntFromPyVerify ///////////////
#define __PYX_VERIFY_RETURN_INT(type, value_type, func) \
{ \
value_type value = func(x); \
if (sizeof(type) < sizeof(value_type)) { \
if (unlikely(value != (type) value)) { \
PyErr_SetString(PyExc_OverflowError, \
(is_unsigned && unlikely(value < 0)) ? \
"can't convert negative value to " #type : \
"value too large to convert to " #type); \
return (type) -1; \
} \
} \
return (type) value; \
}
/////////////// CIntFromPy.proto ///////////////
static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *);
/////////////// CIntFromPy ///////////////
//@requires: CIntFromPyVerify
#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
#if CYTHON_USE_PYLONG_INTERNALS
#include "longintrepr.h"
#endif
#endif
static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
const {{TYPE}} neg_one = ({{TYPE}}) -1, const_zero = 0;
const int is_unsigned = neg_one > const_zero;
#if PY_MAJOR_VERSION < 3
if (likely(PyInt_Check(x))) {
if (sizeof({{TYPE}}) < sizeof(long)) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, long, PyInt_AS_LONG)
} else {
long val = PyInt_AS_LONG(x);
if (is_unsigned && unlikely(val < 0)) {
PyErr_SetString(PyExc_OverflowError,
"can't convert negative value to {{TYPE}}");
return ({{TYPE}}) -1;
}
return ({{TYPE}}) val;
}
} else
#endif
if (likely(PyLong_Check(x))) {
if (is_unsigned) {
#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
#if CYTHON_USE_PYLONG_INTERNALS
if (sizeof(digit) <= sizeof({{TYPE}})) {
switch (Py_SIZE(x)) {
case 0: return 0;
case 1: return ({{TYPE}}) ((PyLongObject*)x)->ob_digit[0];
}
}
#endif
#endif
if (unlikely(Py_SIZE(x) < 0)) {
PyErr_SetString(PyExc_OverflowError,
"can't convert negative value to {{TYPE}}");
return ({{TYPE}}) -1;
}
if (sizeof({{TYPE}}) <= sizeof(unsigned long)) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long, PyLong_AsUnsignedLong)
} else if (sizeof({{TYPE}}) <= sizeof(unsigned long long)) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long long, PyLong_AsUnsignedLongLong)
}
} else {
#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
#if CYTHON_USE_PYLONG_INTERNALS
if (sizeof(digit) <= sizeof({{TYPE}}) {
switch (Py_SIZE(x)) {
case 0: return 0;
case 1: return +({{TYPE}}) ((PyLongObject*)x)->ob_digit[0];
case -1: return -({{TYPE}}) ((PyLongObject*)x)->ob_digit[0];
}
}
#endif
#endif
if (sizeof({{TYPE}}) <= sizeof(long)) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, long, PyLong_AsLong)
} else if (sizeof({{TYPE}}) <= sizeof(long long)) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, long long, PyLong_AsLongLong)
}
}
{
#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray)
PyErr_SetString(PyExc_RuntimeError,
"_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers");
#else
{{TYPE}} val;
PyObject *v = __Pyx_PyNumber_Int(x);
#if PY_MAJOR_VERSION < 3
if (likely(v) && !PyLong_Check(v)) {
PyObject *tmp = v;
v = PyNumber_Long(tmp);
Py_DECREF(tmp);
}
#endif
if (likely(v)) {
int one = 1; int is_little = (int)*(unsigned char *)&one;
unsigned char *bytes = (unsigned char *)&val;
int ret = _PyLong_AsByteArray((PyLongObject *)v,
bytes, sizeof(val),
is_little, !is_unsigned);
Py_DECREF(v);
if (likely(!ret))
return val;
}
#endif
return ({{TYPE}}) -1;
}
} else {
{{TYPE}} val;
PyObject *tmp = __Pyx_PyNumber_Int(x);
if (!tmp) return ({{TYPE}}) -1;
val = {{FROM_PY_FUNCTION}}(tmp);
Py_DECREF(tmp);
return val;
}
}
......@@ -14,16 +14,16 @@ class Integral {
for (unsigned int i=0; i<N; i++)
bytes[i] = I.bytes[i];
}
Integral(signed char I) {
unsigned char p = (I<0) ? 0xFF : 0x00;
for (unsigned int i=0; i<N; i++)
bytes[i] = p;
bytes[lsb()] = *(unsigned char*)&I;
Integral(long long value) {
resize_signed_int((unsigned char*)&value, sizeof(value), bytes, N);
}
operator signed char() const {
return *(signed char*)&bytes[lsb()];
operator long long() const {
long long value;
resize_signed_int(bytes, N, (unsigned char*)&value, sizeof(value));
return value;
}
Integral& operator=(const Integral &I) {
for (unsigned int i=0; i<N; i++)
bytes[i] = I.bytes[i];
......@@ -41,6 +41,23 @@ class Integral {
{ return cmp(I) == 0; }
bool operator!=(const Integral &I) const
{ return cmp(I) != 0; }
bool operator==(const long long value) const {
size_t len = sizeof(long long) > N ? sizeof(long long) : N;
unsigned char* extended = new unsigned char[len];
unsigned char* other;
if (sizeof(long long) < N) {
resize_signed_int((unsigned char*)&value, sizeof(value), extended, len);
other = bytes;
} else {
resize_signed_int(bytes, N, extended, len);
}
bool res = memcmp(extended, other, len);
delete extended;
return res;
}
bool operator!=(const long long val) const
{ return !(*this == val); }
private:
static bool is_le() {
......@@ -81,7 +98,30 @@ class Integral {
if (sI) return -cmpabs;
else return +cmpabs;
}
static void resize_signed_int(const unsigned char* src, size_t src_len, unsigned char* dst, size_t dst_len) {
unsigned char msb;
size_t dst_offset = 0;
size_t src_offset = 0;
if (is_le()) {
dst_offset = 0;
src_offset = 0;
msb = ((unsigned char*) src)[src_len - 1];
} else {
if (dst_len > src_len) {
dst_offset = dst_len - src_len;
} else {
src_offset = src_len - dst_len;
}
msb = ((unsigned char*) src)[0];
}
if (msb & 0x80) {
memset(dst, 0xFF, dst_len);
} else {
memset(dst, 0, dst_len);
}
memcpy(dst + dst_offset, src + src_offset, src_len);
}
};
typedef Integral<3> Int24;
......
__doc__ = u"""
>>> c_longs()
(1, 1L, -1L, 18446744073709551615L)
(1, 1L, -1, 18446744073709551615L)
>>> negative_c_longs()
(-1, -9223285636854775809L)
>>> py_longs()
......@@ -19,6 +19,9 @@ import sys
if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u'L', u'')
elif sys.maxint > 2**31:
# sizeof(long) == sizeof(long long)
__doc__ = __doc__.replace("9223285636854775809L", "9223285636854775809")
@cython.test_assert_path_exists(
'//IntNode[@longness = "LL"]',
......@@ -30,7 +33,7 @@ def c_longs():
cdef unsigned long ua = 1UL
cdef long long aa = 0xFFFFFFFFFFFFFFFFLL
cdef unsigned long long uaa = 0xFFFFFFFFFFFFFFFFULL
return a, ua, aa, uaa
return a, ua, int(aa), uaa
@cython.test_assert_path_exists(
'//IntNode[@longness = "LL"]',
......
......@@ -4,7 +4,7 @@ __doc__ = u"""
"""
import sys
if sys.version_info[0] >= 3:
if sys.version_info[0] >= 3 or sys.maxint > 2**31:
__doc__ = __doc__.replace(u"5L", u"5")
cdef unsigned int ui
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment