Permalink
Browse files

Fix copy/copy_fortran return type & tests

  • Loading branch information...
1 parent 26d7c28 commit 1df507786b2d63019f89213eb26e63ede1df3d01 @markflorisson committed May 22, 2012
@@ -556,25 +556,27 @@ def declare_attribute(self, attribute, env, pos):
elif attribute in ("copy", "copy_fortran"):
ndim = len(self.axes)
- to_axes_c = [('direct', 'contig')]
- to_axes_f = [('direct', 'contig')]
- if ndim - 1:
- to_axes_c = [('direct', 'follow')]*(ndim-1) + to_axes_c
- to_axes_f = to_axes_f + [('direct', 'follow')]*(ndim-1)
+ follow_dim = [('direct', 'follow')]
+ contig_dim = [('direct', 'contig')]
+ to_axes_c = follow_dim * (ndim - 1) + contig_dim
+ to_axes_f = contig_dim + follow_dim * (ndim -1)
to_memview_c = MemoryViewSliceType(self.dtype, to_axes_c)
to_memview_f = MemoryViewSliceType(self.dtype, to_axes_f)
for to_memview, cython_name in [(to_memview_c, "copy"),
(to_memview_f, "copy_fortran")]:
+ copy_func_type = CFuncType(to_memview,
+ [CFuncTypeArg("memviewslice", self, None)])
+ copy_cname = MemoryView.copy_c_or_fortran_cname(to_memview)
+
entry = scope.declare_cfunction(cython_name,
- CFuncType(self, [CFuncTypeArg("memviewslice", self, None)]),
- pos=pos,
- defining=1,
- cname=MemoryView.copy_c_or_fortran_cname(to_memview))
+ copy_func_type, pos=pos, defining=1,
+ cname=copy_cname)
- #entry.utility_code_definition = \
- env.use_utility_code(MemoryView.get_copy_new_utility(pos, self, to_memview))
+ utility = MemoryView.get_copy_new_utility(pos, self,
+ to_memview)
+ env.use_utility_code(utility)
MemoryView.use_cython_array_utility_code(env)
@@ -74,7 +74,7 @@ cdef extern from *:
size_t sizeof_dtype, int contig_flag,
bint dtype_is_object) nogil except *
bint slice_is_contig "__pyx_memviewslice_is_contig" (
- {{memviewslice_name}} *mvs, char order, int ndim) nogil
+ {{memviewslice_name}} mvs, char order, int ndim) nogil
bint slices_overlap "__pyx_slices_overlap" ({{memviewslice_name}} *slice1,
{{memviewslice_name}} *slice2,
int ndim, size_t itemsize) nogil
@@ -582,12 +582,12 @@ cdef class memoryview(object):
def is_c_contig(self):
cdef {{memviewslice_name}} *mslice, tmp
mslice = get_slice_from_memview(self, &tmp)
- return slice_is_contig(mslice, 'C', self.view.ndim)
+ return slice_is_contig(mslice[0], 'C', self.view.ndim)
def is_f_contig(self):
cdef {{memviewslice_name}} *mslice, tmp
mslice = get_slice_from_memview(self, &tmp)
- return slice_is_contig(mslice, 'F', self.view.ndim)
+ return slice_is_contig(mslice[0], 'F', self.view.ndim)
def copy(self):
cdef {{memviewslice_name}} mslice
@@ -1197,7 +1197,7 @@ cdef void *copy_data_to_temp({{memviewslice_name}} *src,
if tmpslice.shape[i] == 1:
tmpslice.strides[i] = 0
- if slice_is_contig(src, order, ndim):
+ if slice_is_contig(src[0], order, ndim):
memcpy(result, src.data, size)
else:
copy_strided_to_strided(src, tmpslice, ndim, itemsize)
@@ -1260,7 +1260,7 @@ cdef int memoryview_copy_contents({{memviewslice_name}} src,
if slices_overlap(&src, &dst, ndim, itemsize):
# slices overlap, copy to temp, copy temp to dst
- if not slice_is_contig(&src, order, ndim):
+ if not slice_is_contig(src, order, ndim):
order = get_best_order(&dst, ndim)
tmpdata = copy_data_to_temp(&src, &tmp, order, ndim)
@@ -1269,10 +1269,10 @@ cdef int memoryview_copy_contents({{memviewslice_name}} src,
if not broadcasting:
# See if both slices have equal contiguity, in that case perform a
# direct copy. This only works when we are not broadcasting.
- if slice_is_contig(&src, 'C', ndim):
- direct_copy = slice_is_contig(&dst, 'C', ndim)
- elif slice_is_contig(&src, 'F', ndim):
- direct_copy = slice_is_contig(&dst, 'F', ndim)
+ if slice_is_contig(src, 'C', ndim):
+ direct_copy = slice_is_contig(dst, 'C', ndim)
+ elif slice_is_contig(src, 'F', ndim):
+ direct_copy = slice_is_contig(dst, 'F', ndim)
if direct_copy:
# Contiguous slices with same order
@@ -594,23 +594,23 @@ __pyx_slices_overlap({{memviewslice_name}} *slice1,
////////// MemviewSliceIsCContig.proto //////////
#define __pyx_memviewslice_is_c_contig{{ndim}}(slice) \
- __pyx_memviewslice_is_contig(&slice, 'C', {{ndim}})
+ __pyx_memviewslice_is_contig(slice, 'C', {{ndim}})
////////// MemviewSliceIsFContig.proto //////////
#define __pyx_memviewslice_is_f_contig{{ndim}}(slice) \
- __pyx_memviewslice_is_contig(&slice, 'F', {{ndim}})
+ __pyx_memviewslice_is_contig(slice, 'F', {{ndim}})
////////// MemviewSliceIsContig.proto //////////
-static int __pyx_memviewslice_is_contig(const {{memviewslice_name}} *mvs,
+static int __pyx_memviewslice_is_contig(const {{memviewslice_name}} mvs,
char order, int ndim);
////////// MemviewSliceIsContig //////////
static int
-__pyx_memviewslice_is_contig(const {{memviewslice_name}} *mvs,
+__pyx_memviewslice_is_contig(const {{memviewslice_name}} mvs,
char order, int ndim)
{
int i, index, step, start;
- Py_ssize_t itemsize = mvs->memview->view.itemsize;
+ Py_ssize_t itemsize = mvs.memview->view.itemsize;
if (order == 'F') {
step = 1;
@@ -622,10 +622,10 @@ __pyx_memviewslice_is_contig(const {{memviewslice_name}} *mvs,
for (i = 0; i < ndim; i++) {
index = start + step * i;
- if (mvs->suboffsets[index] >= 0 || mvs->strides[index] != itemsize)
+ if (mvs.suboffsets[index] >= 0 || mvs.strides[index] != itemsize)
return 0;
- itemsize *= mvs->shape[index];
+ itemsize *= mvs.shape[index];
}
return 1;
@@ -57,11 +57,14 @@ def test_copy_to():
'''
cdef int[:, :, :] from_mvs, to_mvs
from_mvs = np.arange(8, dtype=np.int32).reshape(2,2,2)
+
cdef int *from_data = <int *> from_mvs._data
print ' '.join(str(from_data[i]) for i in range(2*2*2))
+
to_mvs = array((2,2,2), sizeof(int), 'i')
to_mvs[...] = from_mvs
+ # todo: remove this _data attribute
cdef int *to_data = <int*>to_mvs._data
print ' '.join(str(from_data[i]) for i in range(2*2*2))
print ' '.join(str(to_data[i]) for i in range(2*2*2))
@@ -81,6 +84,20 @@ def test_overlapping_copy():
for i in range(10):
assert slice[i] == 10 - 1 - i
+@testcase
+def test_copy_return_type():
+ """
+ >>> test_copy_return_type()
+ 60.0
+ 60.0
+ """
+ cdef double[:, :, :] a = np.arange(5 * 5 * 5, dtype=np.float64).reshape(5, 5, 5)
+ cdef double[:, ::1] c_contig = a[..., 0].copy()
+ cdef double[::1, :] f_contig = a[..., 0].copy_fortran()
+
+ print c_contig[2, 2]
+ print f_contig[2, 2]
+
@testcase
def test_partly_overlapping():
"""
@@ -174,27 +191,29 @@ def test_copy_mismatch():
def test_is_contiguous():
u'''
>>> test_is_contiguous()
- True True
- False True
- True False
- True False
- <BLANKLINE>
- False True
- True False
-'''
+ one sized is_c/f_contig True True
+ is_c/f_contig False True
+ f_contig.copy().is_c/f_contig True False
+ f_contig.copy_fortran().is_c/f_contig False True
+ one sized strided contig True True
+ strided False
+ '''
cdef int[::1, :, :] fort_contig = array((1,1,1), sizeof(int), 'i', mode='fortran')
- print fort_contig.is_c_contig() , fort_contig.is_f_contig()
- fort_contig = array((200,100,100), sizeof(int), 'i', mode='fortran')
- print fort_contig.is_c_contig(), fort_contig.is_f_contig()
- fort_contig = fort_contig.copy()
- print fort_contig.is_c_contig(), fort_contig.is_f_contig()
cdef int[:,:,:] strided = fort_contig
- print strided.is_c_contig(), strided.is_f_contig()
- print
- fort_contig = fort_contig.copy_fortran()
- print fort_contig.is_c_contig(), fort_contig.is_f_contig()
- print strided.is_c_contig(), strided.is_f_contig()
+ print 'one sized is_c/f_contig', fort_contig.is_c_contig(), fort_contig.is_f_contig()
+ fort_contig = array((2,2,2), sizeof(int), 'i', mode='fortran')
+ print 'is_c/f_contig', fort_contig.is_c_contig(), fort_contig.is_f_contig()
+
+ print 'f_contig.copy().is_c/f_contig', fort_contig.copy().is_c_contig(), \
+ fort_contig.copy().is_f_contig()
+ print 'f_contig.copy_fortran().is_c/f_contig', \
+ fort_contig.copy_fortran().is_c_contig(), \
+ fort_contig.copy_fortran().is_f_contig()
+
+ print 'one sized strided contig', strided.is_c_contig(), strided.is_f_contig()
+
+ print 'strided', strided[::2].is_c_contig()
@testcase
def call():
@@ -283,7 +302,8 @@ def fort_two_dee():
1 2 3 -4
'''
cdef array arr = array((2,2), sizeof(long), 'l', mode='fortran')
- cdef long[::1,:] mv1, mv2, mv3
+ cdef long[::1,:] mv1, mv2, mv4
+ cdef long[:, ::1] mv3
cdef long *arr_data
arr_data = <long*>arr.data
@@ -311,6 +331,6 @@ def fort_two_dee():
print (<long*>mv3._data)[0], (<long*>mv3._data)[1], (<long*>mv3._data)[2], (<long*>mv3._data)[3]
- mv3 = mv3.copy_fortran()
+ mv4 = mv3.copy_fortran()
- print (<long*>mv3._data)[0], (<long*>mv3._data)[1], (<long*>mv3._data)[2], (<long*>mv3._data)[3]
+ print (<long*>mv4._data)[0], (<long*>mv4._data)[1], (<long*>mv4._data)[2], (<long*>mv4._data)[3]

0 comments on commit 1df5077

Please sign in to comment.