Skip to content

Commit

Permalink
Merge branch 'master' of git+ssh://github.com/cython/cython
Browse files Browse the repository at this point in the history
  • Loading branch information
scoder committed Oct 17, 2023
2 parents bd5a82f + 8464fb9 commit 575641c
Show file tree
Hide file tree
Showing 24 changed files with 781 additions and 164 deletions.
12 changes: 12 additions & 0 deletions docs/examples/userguide/memoryviews/add_one.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import numpy as np

def add_one(buf: cython.int[:,:]):
for x in range(buf.shape[0]):
for y in range(buf.shape[1]):
buf[x, y] += 1

# exporting_object must be a Python object
# implementing the buffer interface, e.g. a numpy array.
exporting_object = np.zeros((10, 20), dtype=np.intc)

add_one(exporting_object)
13 changes: 13 additions & 0 deletions docs/examples/userguide/memoryviews/copy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import numpy as np

def main():

to_view: cython.int[:, :, :] = np.empty((20, 15, 30), dtype=np.intc)
from_view: cython.int[:, :, :] = np.ones((20, 15, 30), dtype=np.intc)

# copy the elements in from_view to to_view
to_view[...] = from_view
# or
to_view[:] = from_view
# or
to_view[:, :, :] = from_view
1 change: 1 addition & 0 deletions docs/examples/userguide/memoryviews/copy.pyx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numpy as np


cdef int[:, :, :] to_view, from_view
to_view = np.empty((20, 15, 30), dtype=np.intc)
from_view = np.ones((20, 15, 30), dtype=np.intc)
Expand Down
10 changes: 10 additions & 0 deletions docs/examples/userguide/memoryviews/cpython_array.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
def sum_array(view: cython.int[:]):
"""
>>> from array import array
>>> sum_array( array('i', [1,2,3]) )
6
"""
total: cython.int = 0
for i in range(view.shape[0]):
total += view[i]
return total
10 changes: 10 additions & 0 deletions docs/examples/userguide/memoryviews/cpython_array.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
def sum_array(int[:] view):
"""
>>> from array import array
>>> sum_array( array('i', [1,2,3]) )
6
"""
cdef int total = 0
for i in range(view.shape[0]):
total += view[i]
return total
16 changes: 16 additions & 0 deletions docs/examples/userguide/memoryviews/cython_array.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# tag: numpy
import numpy
from cython.cimports.numpy import int32_t

def main():
a: int32_t[:] = numpy.arange(10, dtype=numpy.int32)
a = a[::2]

print(a)
print(numpy.asarray(a))
print(a.base)

# this prints:
# <MemoryView of 'ndarray' object>
# [0 2 4 6 8]
# [0 1 2 3 4 5 6 7 8 9]
16 changes: 16 additions & 0 deletions docs/examples/userguide/memoryviews/cython_array.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# tag: numpy
import numpy
cimport numpy as cnp


cdef cnp.int32_t[:] a = numpy.arange(10, dtype=numpy.int32)
a = a[::2]

print(a)
print(numpy.asarray(a))
print(a.base)

# this prints:
# <MemoryView of 'ndarray' object>
# [0 2 4 6 8]
# [0 1 2 3 4 5 6 7 8 9]
12 changes: 12 additions & 0 deletions docs/examples/userguide/memoryviews/memory_layout.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from cython.cimports.cython import view

def main():
# direct access in both dimensions, strided in the first dimension, contiguous in the last
a: cython.int[:, ::view.contiguous]

# contiguous list of pointers to contiguous lists of ints
b: cython.int[::view.indirect_contiguous, ::1]

# direct or indirect in the first dimension, direct in the second dimension
# strided in both dimensions
c: cython.int[::view.generic, :]
15 changes: 8 additions & 7 deletions docs/examples/userguide/memoryviews/memory_layout.pyx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from cython cimport view

# direct access in both dimensions, strided in the first dimension, contiguous in the last
cdef int[:, ::view.contiguous] a
def main():
# direct access in both dimensions, strided in the first dimension, contiguous in the last
cdef int[:, ::view.contiguous] a

# contiguous list of pointers to contiguous lists of ints
cdef int[::view.indirect_contiguous, ::1] b
# contiguous list of pointers to contiguous lists of ints
cdef int[::view.indirect_contiguous, ::1] b

# direct or indirect in the first dimension, direct in the second dimension
# strided in both dimensions
cdef int[::view.generic, :] c
# direct or indirect in the first dimension, direct in the second dimension
# strided in both dimensions
cdef int[::view.generic, :] c
16 changes: 16 additions & 0 deletions docs/examples/userguide/memoryviews/memory_layout_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# mode: error
from cython.cimports.cython import view

def main():
# VALID
a: cython.int[::view.indirect, ::1, :]
b: cython.int[::view.indirect, :, ::1]
c: cython.int[::view.indirect_contiguous, ::1, :]

# INVALID
d: cython.int[::view.contiguous, ::view.indirect, :]
e: cython.int[::1, ::view.indirect, :]

_ERRORS = u"""
12:17: Only dimension 2 may be contiguous and direct
"""
19 changes: 15 additions & 4 deletions docs/examples/userguide/memoryviews/memory_layout_2.pyx
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# mode: error
from cython cimport view

# VALID
cdef int[::view.indirect, ::1, :] a
cdef int[::view.indirect, :, ::1] b
cdef int[::view.indirect_contiguous, ::1, :] c
def main():
# VALID
cdef int[::view.indirect, ::1, :] a
cdef int[::view.indirect, :, ::1] b
cdef int[::view.indirect_contiguous, ::1, :] c

# INVALID
cdef int[::view.contiguous, ::view.indirect, :] d
cdef int[::1, ::view.indirect, :] e

_ERRORS = u"""
11:12: Only dimension 2 may be contiguous and direct
12:12: Indirect dimension may not follow Fortran contiguous dimension
"""
6 changes: 6 additions & 0 deletions docs/examples/userguide/memoryviews/memview_to_c.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cdef extern from "C_func_file.c":
# The C file is include directly so that it doesn't need to be compiled separately.
pass

cdef extern from "C_func_file.h":
void multiply_by_10_in_C(double *, unsigned int)
21 changes: 21 additions & 0 deletions docs/examples/userguide/memoryviews/memview_to_c.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import numpy as np

def multiply_by_10(arr): # 'arr' is a one-dimensional numpy array

if not arr.flags['C_CONTIGUOUS']:
arr = np.ascontiguousarray(arr) # Makes a contiguous copy of the numpy array.

arr_memview: cython.double[::1] = arr

multiply_by_10_in_C(cython.address(arr_memview[0]), arr_memview.shape[0])

return arr


a = np.ones(5, dtype=np.double)
print(multiply_by_10(a))

b = np.ones(10, dtype=np.double)
b = b[::2] # b is not contiguous.

print(multiply_by_10(b)) # but our function still works as expected.
4 changes: 2 additions & 2 deletions docs/examples/userguide/memoryviews/memview_to_c.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ cdef extern from "C_func_file.h":

import numpy as np

def multiply_by_10(arr): # 'arr' is a one-dimensional numpy array
def multiply_by_10(arr): # 'arr' is a one-dimensional numpy array

if not arr.flags['C_CONTIGUOUS']:
arr = np.ascontiguousarray(arr) # Makes a contiguous copy of the numpy array.
arr = np.ascontiguousarray(arr) # Makes a contiguous copy of the numpy array.

cdef double[::1] arr_memview = arr

Expand Down
14 changes: 14 additions & 0 deletions docs/examples/userguide/memoryviews/not_none.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import numpy as np
import typing

def process_buffer(input_view: cython.int[:,:],
output_view: typing.Optional[cython.int[:,:]] = None):

if output_view is None:
# Creating a default view, e.g.
output_view = np.empty_like(input_view)

# process 'input_view' into 'output_view'
return output_view

process_buffer(None, None)
13 changes: 8 additions & 5 deletions docs/examples/userguide/memoryviews/not_none.pyx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import numpy as np


def process_buffer(int[:,:] input_view not None,
int[:,:] output_view=None):

if output_view is None:
# Creating a default view, e.g.
output_view = np.empty_like(input_view)
if output_view is None:
# Creating a default view, e.g.
output_view = np.empty_like(input_view)

# process 'input_view' into 'output_view'
return output_view

# process 'input_view' into 'output_view'
return output_view
process_buffer(None, None)
10 changes: 10 additions & 0 deletions docs/examples/userguide/memoryviews/old_sum3d.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cpdef int old_sum3d(object[int, ndim=3, mode='strided'] arr):
cdef int I, J, K, total = 0
I = arr.shape[0]
J = arr.shape[1]
K = arr.shape[2]
for i in range(I):
for j in range(J):
for k in range(K):
total += arr[i, j, k]
return total
59 changes: 59 additions & 0 deletions docs/examples/userguide/memoryviews/quickstart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from cython.cimports.cython.view import array as cvarray
import numpy as np

# Memoryview on a NumPy array
narr = np.arange(27, dtype=np.dtype("i")).reshape((3, 3, 3))
narr_view = cython.declare(cython.int[:, :, :], narr)

# Memoryview on a C array
carr = cython.declare(cython.int[3][3][3])
carr_view = cython.declare(cython.int[:, :, :], carr)

# Memoryview on a Cython array
cyarr = cvarray(shape=(3, 3, 3), itemsize=cython.sizeof(cython.int), format="i")
cyarr_view = cython.declare(cython.int[:, :, :], cyarr)

# Show the sum of all the arrays before altering it
print("NumPy sum of the NumPy array before assignments: %s" % narr.sum())

# We can copy the values from one memoryview into another using a single
# statement, by either indexing with ... or (NumPy-style) with a colon.
carr_view[...] = narr_view
cyarr_view[:] = narr_view
# NumPy-style syntax for assigning a single value to all elements.
narr_view[:, :, :] = 3

# Just to distinguish the arrays
carr_view[0, 0, 0] = 100
cyarr_view[0, 0, 0] = 1000

# Assigning into the memoryview on the NumPy array alters the latter
print("NumPy sum of NumPy array after assignments: %s" % narr.sum())

# A function using a memoryview does not usually need the GIL
@cython.nogil
@cython.ccall
def sum3d(arr: cython.int[:, :, :]) -> cython.int:
i: cython.size_t
j: cython.size_t
k: cython.size_t
I: cython.size_t
J: cython.size_t
K: cython.size_t
total: cython.int = 0
I = arr.shape[0]
J = arr.shape[1]
K = arr.shape[2]
for i in range(I):
for j in range(J):
for k in range(K):
total += arr[i, j, k]
return total

# A function accepting a memoryview knows how to use a NumPy array,
# a C array, a Cython array...
print("Memoryview sum of NumPy array is %s" % sum3d(narr))
print("Memoryview sum of C array is %s" % sum3d(carr))
print("Memoryview sum of Cython array is %s" % sum3d(cyarr))
# ... and of course, a memoryview.
print("Memoryview sum of C memoryview is %s" % sum3d(carr_view))
7 changes: 7 additions & 0 deletions docs/examples/userguide/memoryviews/quickstart.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ cpdef int sum3d(int[:, :, :] arr) nogil:
total += arr[i, j, k]
return total








# A function accepting a memoryview knows how to use a NumPy array,
# a C array, a Cython array...
print("Memoryview sum of NumPy array is %s" % sum3d(narr))
Expand Down
11 changes: 11 additions & 0 deletions docs/examples/userguide/memoryviews/slicing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import numpy as np

def main():
exporting_object = np.arange(0, 15 * 10 * 20, dtype=np.intc).reshape((15, 10, 20))

my_view: cython.int[:, :, :] = exporting_object

# These are all equivalent
my_view[10]
my_view[10, :, :]
my_view[10, ...]
1 change: 1 addition & 0 deletions docs/examples/userguide/memoryviews/slicing.pyx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numpy as np


exporting_object = np.arange(0, 15 * 10 * 20, dtype=np.intc).reshape((15, 10, 20))

cdef int[:, :, :] my_view = exporting_object
Expand Down
7 changes: 7 additions & 0 deletions docs/examples/userguide/memoryviews/transpose.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import numpy as np

def main():
array = np.arange(20, dtype=np.intc).reshape((2, 10))

c_contig: cython.int[:, ::1] = array
f_contig: cython.int[::1, :] = c_contig.T
1 change: 1 addition & 0 deletions docs/examples/userguide/memoryviews/transpose.pyx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numpy as np


array = np.arange(20, dtype=np.intc).reshape((2, 10))

cdef int[:, ::1] c_contig = array
Expand Down

0 comments on commit 575641c

Please sign in to comment.