Skip to content

Commit 4394ebf

Browse files
committed
[fix] better handle numpy arrays when their layouts are not C-order
1 parent e40a87b commit 4394ebf

File tree

3 files changed

+46
-14
lines changed

3 files changed

+46
-14
lines changed

src/gil-gc.lisp

+4-1
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,11 @@
102102
("PyArray_Data" nil)
103103
("PyArray_GetItem" nil)
104104
("PyArray_SetItem" nil)
105+
("PyArray_Is_C_Contiguous" nil)
106+
("PyArray_Is_F_Contiguous" nil)
105107
("memcpy" nil)
106-
("PyArray_element_type_from_array" nil))
108+
("PyArray_element_type_from_array" nil)
109+
("PY4CL_PyArray_FromArray" :new))
107110
:test #'equal)
108111

109112
(defmacro pyforeign-funcall (name-and-options &rest args)

src/lispifiers.lisp

+28-13
Original file line numberDiff line numberDiff line change
@@ -86,23 +86,38 @@
8686
(pyforeign-funcall "PyArray_element_type_from_array"
8787
:pointer o :pointer)))))
8888
(from-vec (pyforeign-funcall "PyArray_Data" :pointer o :pointer))
89-
;; FIXME: Strides
9089
(array (make-array dims :element-type element-type))
9190
(num-bytes (* (array-element-type-num-bytes array)
9291
(reduce #'* dims :initial-value 1))))
93-
(if (type= t element-type)
94-
(let* ((numpy-array-data (pyforeign-funcall "PyArray_Data"
95-
:pointer o :pointer)))
96-
(loop :for idx :below (array-total-size array)
97-
:do (setf (row-major-aref array idx)
98-
(lispify
99-
(pyforeign-funcall "PyArray_GetItem"
100-
:pointer o
101-
:pointer (inc-pointer numpy-array-data
102-
(cl:* idx 8))
103-
:pointer)))))
92+
(when (zerop (foreign-funcall "PyArray_Is_C_Contiguous"
93+
:pointer o :int))
94+
(let ((new-pyarray
95+
(pyforeign-funcall
96+
"PY4CL_PyArray_FromArray"
97+
:pointer o
98+
:pointer (pyforeign-funcall
99+
"PyArray_Descr_from_element_type_code"
100+
:string (array-element-typecode array)
101+
:pointer)
102+
:int (mem-ref (foreign-symbol-pointer
103+
"PyArray_C_Contiguous")
104+
:int)
105+
:pointer)))
106+
(setq from-vec (pyforeign-funcall "PyArray_Data"
107+
:pointer new-pyarray
108+
:pointer))))
109+
(if (type= element-type t)
110+
(loop :for idx :below (array-total-size array)
111+
:do (setf (row-major-aref array idx)
112+
(lispify
113+
(pyforeign-funcall "PyArray_GetItem"
114+
:pointer o
115+
:pointer (inc-pointer from-vec
116+
(cl:* idx 8))
117+
:pointer))))
104118
(with-pointer-to-vector-data (to-vec (array-storage array))
105-
(pyforeign-funcall "memcpy" :pointer to-vec :pointer from-vec :int num-bytes)))
119+
(pyforeign-funcall "memcpy" :pointer to-vec :pointer from-vec
120+
:int num-bytes)))
106121
array))
107122

108123
;; TODO: Test these aka find reference in documentation for why this works

src/py4cl-utils.c

+14
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,17 @@ void* PyArray_GetItem(PyArrayObject* arr, void* itemptr){
9595
int PyArray_SetItem(PyArrayObject* arr, void* itemptr, PyObject* obj){
9696
return PyArray_SETITEM(arr, itemptr, obj);
9797
}
98+
99+
const int PyArray_C_Contiguous = NPY_ARRAY_C_CONTIGUOUS;
100+
const int PyArray_F_Contiguous = NPY_ARRAY_F_CONTIGUOUS;
101+
102+
int PyArray_Is_C_Contiguous(PyArrayObject* arr){
103+
return PyArray_IS_C_CONTIGUOUS(arr);
104+
}
105+
int PyArray_Is_F_Contiguous(PyArrayObject* arr){
106+
return PyArray_IS_F_CONTIGUOUS(arr);
107+
}
108+
109+
PyObject* PY4CL_PyArray_FromArray(PyArrayObject *op, PyArray_Descr *newtype, int requirements){
110+
return PyArray_FromArray(op, newtype, requirements);
111+
}

0 commit comments

Comments
 (0)