diff options
| author | David Cournapeau <cournape@gmail.com> | 2009-03-06 14:41:42 +0000 |
|---|---|---|
| committer | David Cournapeau <cournape@gmail.com> | 2009-03-06 14:41:42 +0000 |
| commit | 358ef7d5d8169ba3419894174180d38466c1725a (patch) | |
| tree | 9ca03ee3081913e4fd5751a764cbe803cc8131d0 /numpy | |
| parent | 944894a446d11463019005e2762fda47f4dc30b4 (diff) | |
| parent | fb4035fa27d02fcb8c9fce9141fe8bfd3c1859ec (diff) | |
| download | numpy-358ef7d5d8169ba3419894174180d38466c1725a.tar.gz | |
Merge branch 'runtime_endian'
Diffstat (limited to 'numpy')
| -rw-r--r-- | numpy/core/code_generators/generate_numpy_api.py | 35 | ||||
| -rw-r--r-- | numpy/core/code_generators/numpy_api_order.txt | 1 | ||||
| -rw-r--r-- | numpy/core/include/numpy/ndarrayobject.h | 4 | ||||
| -rw-r--r-- | numpy/core/include/numpy/npy_common.h | 7 | ||||
| -rw-r--r-- | numpy/core/include/numpy/npy_cpu.h | 38 | ||||
| -rw-r--r-- | numpy/core/include/numpy/npy_endian.h | 35 | ||||
| -rw-r--r-- | numpy/core/src/multiarraymodule.c | 28 |
7 files changed, 133 insertions, 15 deletions
diff --git a/numpy/core/code_generators/generate_numpy_api.py b/numpy/core/code_generators/generate_numpy_api.py index 2b5a550de..4dda84146 100644 --- a/numpy/core/code_generators/generate_numpy_api.py +++ b/numpy/core/code_generators/generate_numpy_api.py @@ -65,13 +65,7 @@ static void **PyArray_API=NULL; static int _import_array(void) { -#ifdef WORDS_BIGENDIAN - union { - long i; - char c[sizeof(long)]; - } bint = {1}; -#endif - + int st; PyObject *numpy = PyImport_ImportModule("numpy.core.multiarray"); PyObject *c_api = NULL; if (numpy == NULL) return -1; @@ -90,13 +84,26 @@ _import_array(void) (int) NPY_VERSION, (int) PyArray_GetNDArrayCVersion()); return -1; } - -#ifdef WORDS_BIGENDIAN - if (bint.c[0] == 1) { - PyErr_Format(PyExc_RuntimeError, "module compiled against "\ - "python headers configured as big endian, but little endian arch "\ - "detected: this is a python 2.6.* bug (see bug 4728 in python bug "\ - "tracker )"); + + /* + * Perform runtime check of endianness and check it matches the one set by + * the headers (npy_endian.h) as a safeguard + */ + st = PyArray_GetEndianness(); + if (st == NPY_CPU_UNKNOWN_ENDIAN) { + PyErr_Format(PyExc_RuntimeError, "FATAL: module compiled as unknown endian"); + return -1; + } +#ifdef NPY_BIG_ENDIAN + if (st != NPY_CPU_BIG) { + PyErr_Format(PyExc_RuntimeError, "FATAL: module compiled as "\ + "big endian, but detected different endianness at runtime"); + return -1; + } +#elif defined(NPY_LITTLE_ENDIAN) + if (st != NPY_CPU_LITTLE) { + PyErr_Format(PyExc_RuntimeError, "FATAL: module compiled as"\ + "little endian, but detected different endianness at runtime"); return -1; } #endif diff --git a/numpy/core/code_generators/numpy_api_order.txt b/numpy/core/code_generators/numpy_api_order.txt index ff629d6e4..05735bbda 100644 --- a/numpy/core/code_generators/numpy_api_order.txt +++ b/numpy/core/code_generators/numpy_api_order.txt @@ -171,3 +171,4 @@ PyArray_CheckAxis PyArray_OverflowMultiplyList PyArray_CompareString PyArray_MultiIterFromObjects +PyArray_GetEndianness diff --git a/numpy/core/include/numpy/ndarrayobject.h b/numpy/core/include/numpy/ndarrayobject.h index f754959f9..018c5d689 100644 --- a/numpy/core/include/numpy/ndarrayobject.h +++ b/numpy/core/include/numpy/ndarrayobject.h @@ -23,6 +23,8 @@ extern "C" CONFUSE_EMACS #define NPY_ALLOW_THREADS 0 #endif +#include "npy_endian.h" + #include "utils.h" /* There are several places in the code where an array of dimensions is @@ -1728,7 +1730,7 @@ typedef struct { #define NPY_SWAP 's' #define NPY_IGNORE '|' -#ifdef WORDS_BIGENDIAN +#ifdef NPY_BIG_ENDIAN #define NPY_NATBYTE NPY_BIG #define NPY_OPPBYTE NPY_LITTLE #else diff --git a/numpy/core/include/numpy/npy_common.h b/numpy/core/include/numpy/npy_common.h index 01f97f6ad..36f4d9e64 100644 --- a/numpy/core/include/numpy/npy_common.h +++ b/numpy/core/include/numpy/npy_common.h @@ -4,6 +4,13 @@ /* This is auto-generated */ #include "numpyconfig.h" +/* enums for detected endianness */ +enum { + NPY_CPU_UNKNOWN_ENDIAN, + NPY_CPU_LITTLE, + NPY_CPU_BIG, +}; + /* Some platforms don't define bool, long long, or long double. Handle that here. */ diff --git a/numpy/core/include/numpy/npy_cpu.h b/numpy/core/include/numpy/npy_cpu.h new file mode 100644 index 000000000..24815fbc5 --- /dev/null +++ b/numpy/core/include/numpy/npy_cpu.h @@ -0,0 +1,38 @@ +/* + * This set (target) cpu specific macros: + * - Possible values: + * NPY_CPU_X86 + * NPY_CPU_AMD64 + * NPY_CPU_PPC + * NPY_CPU_SPARC + * NPY_CPU_S390 + * NPY_CPU_PARISC + */ +#ifndef _NPY_CPUARCH_H_ +#define _NPY_CPUARCH_H_ + +#if defined ( _i386_ ) || defined( __i386__ ) + /* __i386__ is defined by gcc and Intel compiler on Linux, _i386_ by + VS compiler */ + #define NPY_CPU_X86 +#elif defined(__x86_64__) || defined(__amd64__) + /* both __x86_64__ and __amd64__ are defined by gcc */ + #define NPY_CPU_AMD64 +#elif defined(__ppc__) || defined(__powerpc__) + /* __ppc__ is defined by gcc, I remember having seen __powerpc__ once, + * but can't find it ATM */ + #define NPY_CPU_PPC +#elif defined(__sparc__) || defined(__sparc) + /* __sparc__ is defined by gcc and Forte (e.g. Sun) compilers */ + #define NPY_CPU_SPARC +#elif defined(__s390__) + #define NPY_TARGET_CPU NPY_S390 +#elif defined(__parisc__) + /* XXX: Not sure about this one... */ + #define NPY_CPU_PARISC +#else + #error Unknown CPU, please report this to numpy maintainers with \ + information about your platform (OS, CPU and compiler) +#endif + +#endif diff --git a/numpy/core/include/numpy/npy_endian.h b/numpy/core/include/numpy/npy_endian.h new file mode 100644 index 000000000..e51b01fbc --- /dev/null +++ b/numpy/core/include/numpy/npy_endian.h @@ -0,0 +1,35 @@ +#ifndef _NPY_ENDIAN_H_ +#define _NPY_ENDIAN_H_ + +/* NPY_BYTE_ORDER is set to the same value as BYTE_ORDER set by glibc in + * endian.h */ + +#ifdef NPY_HAVE_ENDIAN_H + /* Use endian.h if available */ + #include <endian.h> + #define NPY_BYTE_ORDER __BYTE_ORDER + #if (__BYTE_ORDER == __LITTLE_ENDIAN) + #define NPY_LITTLE_ENDIAN + #elif (__BYTE_ORDER == __BIG_ENDIAN) + #define NPY_BIG_ENDIAN + #else + #error Unknown machine endianness detected. + #endif +#else + /* Set endianness info using target CPU */ + #include "npy_cpu.h" + + #if defined(NPY_CPU_X86) || defined(NPY_CPU_AMD64) + #define NPY_LITTLE_ENDIAN + #define NPY_BYTE_ORDER 1234 + #elif defined(NPY_CPU_PPC) || defined(NPY_CPU_SPARC) || \ + defined(NPY_CPU_S390) || \ + defined(NPY_CPU_PARISC) + #define NPY_BIG_ENDIAN + #define NPY_BYTE_ORDER 4321 + #else + #error Unknown CPU: don't know how to set endianness + #endif +#endif + +#endif diff --git a/numpy/core/src/multiarraymodule.c b/numpy/core/src/multiarraymodule.c index 83c9ed40d..1b0e21526 100644 --- a/numpy/core/src/multiarraymodule.c +++ b/numpy/core/src/multiarraymodule.c @@ -7684,6 +7684,34 @@ array__get_ndarray_c_version(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObje return PyInt_FromLong( (long) PyArray_GetNDArrayCVersion() ); } +static int compute_endianness() +{ + union { + char c[4]; + npy_uint32 i; + } bint; + int st; + + bint.i = 'ABCD'; + + switch(bint.c[0]) { + case 'A': + return NPY_CPU_BIG; + case 'D': + return NPY_CPU_LITTLE; + default: + return NPY_CPU_UNKNOWN_ENDIAN; + } +} + +/*NUMPY_API +*/ +static int +PyArray_GetEndianness(void) +{ + return compute_endianness(); +} + static PyObject * array__reconstruct(PyObject *NPY_UNUSED(dummy), PyObject *args) { |
