""",
impl="""
static CYTHON_INLINE %(type)s __Pyx_PyInt_from_py_%(TypeName)s(PyObject* x) {
- const %(type)s neg_one = (%(type)s)-1, const_zero = 0;
- const int is_unsigned = neg_one > const_zero;
+ const %(type)s neg_one = (%(type)s)-1, const_zero = (%(type)s)0;
+ const int is_unsigned = const_zero < neg_one;
if (sizeof(%(type)s) == sizeof(char)) {
if (is_unsigned)
return (%(type)s)__Pyx_PyInt_AsUnsignedChar(x);
return (%(type)s)__Pyx_PyInt_AsUnsignedLongLong(x);
else
return (%(type)s)__Pyx_PyInt_AsSignedLongLong(x);
-#if 0
- } else if (sizeof(%(type)s) > sizeof(short) &&
- sizeof(%(type)s) < sizeof(int)) { /* __int32 ILP64 ? */
- if (is_unsigned)
- return (%(type)s)__Pyx_PyInt_AsUnsignedInt(x);
- else
- return (%(type)s)__Pyx_PyInt_AsSignedInt(x);
-#endif
+ } else {
+ %(type)s val;
+ PyObject *v = __Pyx_PyNumber_Int(x);
+ #if PY_VERSION_HEX < 0x03000000
+ 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;
+ }
+ return (%(type)s)-1;
}
- PyErr_SetString(PyExc_TypeError, "%(TypeName)s");
- return (%(type)s)-1;
}
""")
""",
impl="""
static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_%(TypeName)s(%(type)s val) {
- const %(type)s neg_one = (%(type)s)-1, const_zero = 0;
- const int is_unsigned = neg_one > const_zero;
- if (sizeof(%(type)s) < sizeof(long)) {
+ const %(type)s neg_one = (%(type)s)-1, const_zero = (%(type)s)0;
+ const int is_unsigned = const_zero < neg_one;
+ if ((sizeof(%(type)s) == sizeof(char)) ||
+ (sizeof(%(type)s) == sizeof(short))) {
return PyInt_FromLong((long)val);
- } else if (sizeof(%(type)s) == sizeof(long)) {
+ } else if ((sizeof(%(type)s) == sizeof(int)) ||
+ (sizeof(%(type)s) == sizeof(long))) {
if (is_unsigned)
return PyLong_FromUnsignedLong((unsigned long)val);
else
return PyInt_FromLong((long)val);
- } else { /* (sizeof(%(type)s) > sizeof(long)) */
+ } else if (sizeof(%(type)s) == sizeof(PY_LONG_LONG)) {
if (is_unsigned)
return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val);
else
return PyLong_FromLongLong((PY_LONG_LONG)val);
+ } else {
+ int one = 1; int little = (int)*(unsigned char *)&one;
+ unsigned char *bytes = (unsigned char *)&val;
+ return _PyLong_FromByteArray(bytes, sizeof(%(type)s),
+ little, !is_unsigned);
}
}
""")
--- /dev/null
+// -*- c++ -*-
+#include <stdio.h>
+template<unsigned int N>
+class Integral {
+
+ unsigned char bytes[N];
+
+ public:
+ Integral() {
+ for (unsigned int i=0; i<N; i++)
+ bytes[i] = 0;
+ }
+ Integral(const Integral &I) {
+ 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;
+ }
+
+ operator signed char() const {
+ return *(signed char*)&bytes[lsb()];
+ }
+ Integral& operator=(const Integral &I) {
+ for (unsigned int i=0; i<N; i++)
+ bytes[i] = I.bytes[i];
+ return *this;
+ }
+ bool operator<(const Integral &I) const
+ { return cmp(I) < 0; }
+ bool operator>(const Integral &I) const
+ { return cmp(I) > 0; }
+ bool operator<=(const Integral &I) const
+ { return cmp(I) <= 0; }
+ bool operator>=(const Integral &I) const
+ { return cmp(I) >= 0; }
+ bool operator==(const Integral &I) const
+ { return cmp(I) == 0; }
+ bool operator!=(const Integral &I) const
+ { return cmp(I) != 0; }
+
+ private:
+ static bool is_le() {
+ int one = 1;
+ return (int)*(unsigned char *)&one;
+ }
+ static unsigned int lsb() {
+ return is_le() ? 0 : N-1;
+ }
+ static unsigned int msb() {
+ return is_le() ? N-1 : 0;
+ }
+ int cmp(const Integral& J) const {
+ const Integral& I = *this;
+ unsigned char sI = I.bytes[msb()] & 0x80;
+ unsigned char sJ = J.bytes[msb()] & 0x80;
+ if (sI > sJ) return -1;
+ if (sI < sJ) return +1;
+ unsigned char bI = I.bytes[msb()] & 0x7F;
+ unsigned char bJ = J.bytes[msb()] & 0x7F;
+ int cmpabs = 0;
+ if (bI < bJ)
+ cmpabs = -1;
+ else if (bI > bJ)
+ cmpabs = +1;
+ else {
+ int incr = is_le() ? -1 : 1;
+ unsigned int i = msb() + incr;
+ while (i != lsb()) {
+ if (I.bytes[i] < J.bytes[i])
+ { cmpabs = -1; break; }
+ if (I.bytes[i] > J.bytes[i])
+ { cmpabs = +1; break; }
+ i += incr;
+ }
+ }
+ if (sI) return -cmpabs;
+ else return +cmpabs;
+ }
+
+};
+
+typedef Integral<3> Int24;
+typedef Integral<7> Int56;
+typedef Integral<11> Int88;
+typedef Integral<64> Int512;
--- /dev/null
+cdef extern from "cpp_nonstdint.h":
+ ctypedef int Int24
+ ctypedef int Int56
+ ctypedef int Int88
+ ctypedef int Int512
+
+cdef object one = 1
+
+# ---
+
+INT24_MAX = (one<<(sizeof(Int24)*8-1))-one
+INT24_MIN = (-INT24_MAX-one)
+
+def test_int24(Int24 i):
+ """
+ >>> str(test_int24(-1))
+ '-1'
+ >>> str(test_int24(0))
+ '0'
+ >>> str(test_int24(1))
+ '1'
+
+ >>> test_int24(INT24_MAX) == INT24_MAX
+ True
+ >>> test_int24(INT24_MIN) == INT24_MIN
+ True
+
+ >>> test_int24(INT24_MIN-1) #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ OverflowError: ...
+ >>> test_int24(INT24_MAX+1) #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ OverflowError: ...
+
+ >>> test_int24("123") #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ TypeError: ...
+ """
+ return i
+
+# ---
+
+INT56_MAX = (one<<(sizeof(Int56)*8-1))-one
+INT56_MIN = (-INT56_MAX-one)
+
+def test_int56(Int56 i):
+ """
+ >>> str(test_int56(-1))
+ '-1'
+ >>> str(test_int56(0))
+ '0'
+ >>> str(test_int56(1))
+ '1'
+
+ >>> test_int56(INT56_MAX) == INT56_MAX
+ True
+ >>> test_int56(INT56_MIN) == INT56_MIN
+ True
+
+ >>> test_int56(INT56_MIN-1) #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ OverflowError: ...
+ >>> test_int56(INT56_MAX+1) #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ OverflowError: ...
+
+ >>> test_int56("123") #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ TypeError: ...
+ """
+ return i
+
+# ---
+
+INT88_MAX = (one<<(sizeof(Int88)*8-1))-one
+INT88_MIN = (-INT88_MAX-one)
+
+def test_int88(Int88 i):
+ """
+ >>> str(test_int88(-1))
+ '-1'
+ >>> str(test_int88(0))
+ '0'
+ >>> str(test_int88(1))
+ '1'
+
+ >>> test_int88(INT88_MAX) == INT88_MAX
+ True
+ >>> test_int88(INT88_MIN) == INT88_MIN
+ True
+
+ >>> test_int88(INT88_MIN-1) #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ OverflowError: ...
+ >>> test_int88(INT88_MAX+1) #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ OverflowError: ...
+
+ >>> test_int88("123") #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ TypeError: ...
+ """
+ return i
+
+# ---
+
+INT512_MAX = (one<<(sizeof(Int512)*8-1))-one
+INT512_MIN = (-INT512_MAX-one)
+
+def test_int512(Int512 i):
+ """
+ >>> str(test_int512(-1))
+ '-1'
+ >>> str(test_int512(0))
+ '0'
+ >>> str(test_int512(1))
+ '1'
+
+ >>> test_int512(INT512_MAX) == INT512_MAX
+ True
+ >>> test_int512(INT512_MIN) == INT512_MIN
+ True
+
+ >>> test_int512(INT512_MIN-1) #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ OverflowError: ...
+ >>> test_int512(INT512_MAX+1) #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ OverflowError: ...
+
+ >>> test_int512("123") #doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ TypeError: ...
+ """
+ return i
+
+# ---