summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorDavid Cournapeau <cournape@gmail.com>2009-03-06 14:41:42 +0000
committerDavid Cournapeau <cournape@gmail.com>2009-03-06 14:41:42 +0000
commit358ef7d5d8169ba3419894174180d38466c1725a (patch)
tree9ca03ee3081913e4fd5751a764cbe803cc8131d0 /numpy
parent944894a446d11463019005e2762fda47f4dc30b4 (diff)
parentfb4035fa27d02fcb8c9fce9141fe8bfd3c1859ec (diff)
downloadnumpy-358ef7d5d8169ba3419894174180d38466c1725a.tar.gz
Merge branch 'runtime_endian'
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/code_generators/generate_numpy_api.py35
-rw-r--r--numpy/core/code_generators/numpy_api_order.txt1
-rw-r--r--numpy/core/include/numpy/ndarrayobject.h4
-rw-r--r--numpy/core/include/numpy/npy_common.h7
-rw-r--r--numpy/core/include/numpy/npy_cpu.h38
-rw-r--r--numpy/core/include/numpy/npy_endian.h35
-rw-r--r--numpy/core/src/multiarraymodule.c28
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)
{