diff options
Diffstat (limited to 'docs/examples/tutorial')
113 files changed, 1517 insertions, 754 deletions
diff --git a/docs/examples/tutorial/array/clone.py b/docs/examples/tutorial/array/clone.py new file mode 100644 index 000000000..6736c2f67 --- /dev/null +++ b/docs/examples/tutorial/array/clone.py @@ -0,0 +1,8 @@ +from cython.cimports.cpython import array +import array + +int_array_template = cython.declare(array.array, array.array('i', [])) +cython.declare(newarray=array.array) + +# create an array with 3 elements with same type as template +newarray = array.clone(int_array_template, 3, zero=False) diff --git a/docs/examples/tutorial/array/clone.pyx b/docs/examples/tutorial/array/clone.pyx index e2bac0e4a..2eb803499 100644 --- a/docs/examples/tutorial/array/clone.pyx +++ b/docs/examples/tutorial/array/clone.pyx @@ -1,8 +1,8 @@ -from cpython cimport array
-import array
-
-cdef array.array int_array_template = array.array('i', [])
-cdef array.array newarray
-
-# create an array with 3 elements with same type as template
-newarray = array.clone(int_array_template, 3, zero=False)
+from cpython cimport array +import array + +cdef array.array int_array_template = array.array('i', []) +cdef array.array newarray + +# create an array with 3 elements with same type as template +newarray = array.clone(int_array_template, 3, zero=False) diff --git a/docs/examples/tutorial/array/overhead.py b/docs/examples/tutorial/array/overhead.py new file mode 100644 index 000000000..f60c019ce --- /dev/null +++ b/docs/examples/tutorial/array/overhead.py @@ -0,0 +1,17 @@ +from cython.cimports.cpython import array +import array + +a = cython.declare(array.array, array.array('i', [1, 2, 3])) +ca = cython.declare(cython.int[:], a) + +@cython.cfunc +def overhead(a: cython.object) -> cython.int: + ca: cython.int[:] = a + return ca[0] + +@cython.cfunc +def no_overhead(ca: cython.int[:]) -> cython.int: + return ca[0] + +print(overhead(a)) # new memory view will be constructed, overhead +print(no_overhead(ca)) # ca is already a memory view, so no overhead diff --git a/docs/examples/tutorial/array/overhead.pyx b/docs/examples/tutorial/array/overhead.pyx index e385bff3f..a113e8dc9 100644 --- a/docs/examples/tutorial/array/overhead.pyx +++ b/docs/examples/tutorial/array/overhead.pyx @@ -1,15 +1,17 @@ -from cpython cimport array
-import array
-
-cdef array.array a = array.array('i', [1, 2, 3])
-cdef int[:] ca = a
-
-cdef int overhead(object a):
- cdef int[:] ca = a
- return ca[0]
-
-cdef int no_overhead(int[:] ca):
- return ca[0]
-
-print(overhead(a)) # new memory view will be constructed, overhead
-print(no_overhead(ca)) # ca is already a memory view, so no overhead
+from cpython cimport array +import array + +cdef array.array a = array.array('i', [1, 2, 3]) +cdef int[:] ca = a + + +cdef int overhead(object a): + cdef int[:] ca = a + return ca[0] + + +cdef int no_overhead(int[:] ca): + return ca[0] + +print(overhead(a)) # new memory view will be constructed, overhead +print(no_overhead(ca)) # ca is already a memory view, so no overhead diff --git a/docs/examples/tutorial/array/resize.py b/docs/examples/tutorial/array/resize.py new file mode 100644 index 000000000..c2e50472f --- /dev/null +++ b/docs/examples/tutorial/array/resize.py @@ -0,0 +1,10 @@ +from cython.cimports.cpython import array +import array + +a = cython.declare(array.array, array.array('i', [1, 2, 3])) +b = cython.declare(array.array, array.array('i', [4, 5, 6])) + +# extend a with b, resize as needed +array.extend(a, b) +# resize a, leaving just original three elements +array.resize(a, len(a) - len(b)) diff --git a/docs/examples/tutorial/array/resize.pyx b/docs/examples/tutorial/array/resize.pyx index a11fbde7b..7b92958b4 100644 --- a/docs/examples/tutorial/array/resize.pyx +++ b/docs/examples/tutorial/array/resize.pyx @@ -1,10 +1,10 @@ -from cpython cimport array
-import array
-
-cdef array.array a = array.array('i', [1, 2, 3])
-cdef array.array b = array.array('i', [4, 5, 6])
-
-# extend a with b, resize as needed
-array.extend(a, b)
-# resize a, leaving just original three elements
-array.resize(a, len(a) - len(b))
+from cpython cimport array +import array + +cdef array.array a = array.array('i', [1, 2, 3]) +cdef array.array b = array.array('i', [4, 5, 6]) + +# extend a with b, resize as needed +array.extend(a, b) +# resize a, leaving just original three elements +array.resize(a, len(a) - len(b)) diff --git a/docs/examples/tutorial/array/safe_usage.py b/docs/examples/tutorial/array/safe_usage.py new file mode 100644 index 000000000..8b9ffd42c --- /dev/null +++ b/docs/examples/tutorial/array/safe_usage.py @@ -0,0 +1,6 @@ +from cython.cimports.cpython import array +import array +a = cython.declare(array.array, array.array('i', [1, 2, 3])) +ca = cython.declare(cython.int[:], a) + +print(ca[0]) diff --git a/docs/examples/tutorial/array/safe_usage.pyx b/docs/examples/tutorial/array/safe_usage.pyx index 61d6b39eb..15107ae92 100644 --- a/docs/examples/tutorial/array/safe_usage.pyx +++ b/docs/examples/tutorial/array/safe_usage.pyx @@ -1,6 +1,6 @@ -from cpython cimport array
-import array
-cdef array.array a = array.array('i', [1, 2, 3])
-cdef int[:] ca = a
-
-print(ca[0])
+from cpython cimport array +import array +cdef array.array a = array.array('i', [1, 2, 3]) +cdef int[:] ca = a + +print(ca[0]) diff --git a/docs/examples/tutorial/array/unsafe_usage.py b/docs/examples/tutorial/array/unsafe_usage.py new file mode 100644 index 000000000..99b2b1690 --- /dev/null +++ b/docs/examples/tutorial/array/unsafe_usage.py @@ -0,0 +1,11 @@ +from cython.cimports.cpython import array +import array + +a = cython.declare(array.array, array.array('i', [1, 2, 3])) + +# access underlying pointer: +print(a.data.as_ints[0]) + +from cython.cimports.libc.string import memset + +memset(a.data.as_voidptr, 0, len(a) * cython.sizeof(cython.int)) diff --git a/docs/examples/tutorial/array/unsafe_usage.pyx b/docs/examples/tutorial/array/unsafe_usage.pyx index 2aefeb102..d1f498c68 100644 --- a/docs/examples/tutorial/array/unsafe_usage.pyx +++ b/docs/examples/tutorial/array/unsafe_usage.pyx @@ -1,11 +1,11 @@ -from cpython cimport array
-import array
-
-cdef array.array a = array.array('i', [1, 2, 3])
-
-# access underlying pointer:
-print(a.data.as_ints[0])
-
-from libc.string cimport memset
-
-memset(a.data.as_voidptr, 0, len(a) * sizeof(int))
+from cpython cimport array +import array + +cdef array.array a = array.array('i', [1, 2, 3]) + +# access underlying pointer: +print(a.data.as_ints[0]) + +from libc.string cimport memset + +memset(a.data.as_voidptr, 0, len(a) * sizeof(int)) diff --git a/docs/examples/tutorial/cdef_classes/integrate.py b/docs/examples/tutorial/cdef_classes/integrate.py new file mode 100644 index 000000000..cd02554e5 --- /dev/null +++ b/docs/examples/tutorial/cdef_classes/integrate.py @@ -0,0 +1,17 @@ +from cython.cimports.sin_of_square import Function, SinOfSquareFunction + +def integrate(f: Function, a: float, b: float, N: cython.int): + i: cython.int + + if f is None: + raise ValueError("f cannot be None") + + s: float = 0 + dx: float = (b - a) / N + + for i in range(N): + s += f.evaluate(a + i * dx) + + return s * dx + +print(integrate(SinOfSquareFunction(), 0, 1, 10000)) diff --git a/docs/examples/tutorial/cdef_classes/integrate.pyx b/docs/examples/tutorial/cdef_classes/integrate.pyx index a3bbcbfec..ad4c8540b 100644 --- a/docs/examples/tutorial/cdef_classes/integrate.pyx +++ b/docs/examples/tutorial/cdef_classes/integrate.pyx @@ -1,14 +1,17 @@ -from sin_of_square cimport Function, SinOfSquareFunction
-
-def integrate(Function f, double a, double b, int N):
- cdef int i
- cdef double s, dx
- if f is None:
- raise ValueError("f cannot be None")
- s = 0
- dx = (b - a) / N
- for i in range(N):
- s += f.evaluate(a + i * dx)
- return s * dx
-
-print(integrate(SinOfSquareFunction(), 0, 1, 10000))
+from sin_of_square cimport Function, SinOfSquareFunction + +def integrate(Function f, double a, double b, int N): + cdef int i + cdef double s, dx + if f is None: + raise ValueError("f cannot be None") + + s = 0 + dx = (b - a) / N + + for i in range(N): + s += f.evaluate(a + i * dx) + + return s * dx + +print(integrate(SinOfSquareFunction(), 0, 1, 10000)) diff --git a/docs/examples/tutorial/cdef_classes/math_function.py b/docs/examples/tutorial/cdef_classes/math_function.py index 21281cc9b..1a6ee896c 100644 --- a/docs/examples/tutorial/cdef_classes/math_function.py +++ b/docs/examples/tutorial/cdef_classes/math_function.py @@ -1,7 +1,7 @@ -class MathFunction(object):
- def __init__(self, name, operator):
- self.name = name
- self.operator = operator
-
- def __call__(self, *operands):
- return self.operator(*operands)
+class MathFunction(object): + def __init__(self, name, operator): + self.name = name + self.operator = operator + + def __call__(self, *operands): + return self.operator(*operands) diff --git a/docs/examples/tutorial/cdef_classes/math_function_2.py b/docs/examples/tutorial/cdef_classes/math_function_2.py new file mode 100644 index 000000000..ba5917639 --- /dev/null +++ b/docs/examples/tutorial/cdef_classes/math_function_2.py @@ -0,0 +1,5 @@ +@cython.cclass +class Function: + @cython.ccall + def evaluate(self, x: float) -> float: + return 0 diff --git a/docs/examples/tutorial/cdef_classes/math_function_2.pyx b/docs/examples/tutorial/cdef_classes/math_function_2.pyx index 1793ef689..a4bdb7aa2 100644 --- a/docs/examples/tutorial/cdef_classes/math_function_2.pyx +++ b/docs/examples/tutorial/cdef_classes/math_function_2.pyx @@ -1,3 +1,5 @@ -cdef class Function:
- cpdef double evaluate(self, double x) except *:
- return 0
+ +cdef class Function: + + cpdef double evaluate(self, double x) except *: + return 0 diff --git a/docs/examples/tutorial/cdef_classes/nonecheck.py b/docs/examples/tutorial/cdef_classes/nonecheck.py new file mode 100644 index 000000000..dccb97435 --- /dev/null +++ b/docs/examples/tutorial/cdef_classes/nonecheck.py @@ -0,0 +1,20 @@ +# cython: nonecheck=True +# ^^^ Turns on nonecheck globally + +import cython + +@cython.cclass +class MyClass: + pass + +# Turn off nonecheck locally for the function +@cython.nonecheck(False) +def func(): + obj: MyClass = None + try: + # Turn nonecheck on again for a block + with cython.nonecheck(True): + print(obj.myfunc()) # Raises exception + except AttributeError: + pass + print(obj.myfunc()) # Hope for a crash! diff --git a/docs/examples/tutorial/cdef_classes/nonecheck.pyx b/docs/examples/tutorial/cdef_classes/nonecheck.pyx index b9e12c8d5..92c8fa42b 100644 --- a/docs/examples/tutorial/cdef_classes/nonecheck.pyx +++ b/docs/examples/tutorial/cdef_classes/nonecheck.pyx @@ -1,19 +1,20 @@ -# cython: nonecheck=True
-# ^^^ Turns on nonecheck globally
-
-import cython
-
-cdef class MyClass:
- pass
-
-# Turn off nonecheck locally for the function
-@cython.nonecheck(False)
-def func():
- cdef MyClass obj = None
- try:
- # Turn nonecheck on again for a block
- with cython.nonecheck(True):
- print(obj.myfunc()) # Raises exception
- except AttributeError:
- pass
- print(obj.myfunc()) # Hope for a crash!
+# cython: nonecheck=True +# ^^^ Turns on nonecheck globally + +import cython + + +cdef class MyClass: + pass + +# Turn off nonecheck locally for the function +@cython.nonecheck(False) +def func(): + cdef MyClass obj = None + try: + # Turn nonecheck on again for a block + with cython.nonecheck(True): + print(obj.myfunc()) # Raises exception + except AttributeError: + pass + print(obj.myfunc()) # Hope for a crash! diff --git a/docs/examples/tutorial/cdef_classes/sin_of_square.py b/docs/examples/tutorial/cdef_classes/sin_of_square.py new file mode 100644 index 000000000..1904ea934 --- /dev/null +++ b/docs/examples/tutorial/cdef_classes/sin_of_square.py @@ -0,0 +1,13 @@ +from cython.cimports.libc.math import sin + +@cython.cclass +class Function: + @cython.ccall + def evaluate(self, x: float) -> float: + return 0 + +@cython.cclass +class SinOfSquareFunction(Function): + @cython.ccall + def evaluate(self, x: float) -> float: + return sin(x ** 2) diff --git a/docs/examples/tutorial/cdef_classes/sin_of_square.pyx b/docs/examples/tutorial/cdef_classes/sin_of_square.pyx index 7aab96056..67af294b5 100644 --- a/docs/examples/tutorial/cdef_classes/sin_of_square.pyx +++ b/docs/examples/tutorial/cdef_classes/sin_of_square.pyx @@ -1,9 +1,13 @@ -from libc.math cimport sin
-
-cdef class Function:
- cpdef double evaluate(self, double x) except *:
- return 0
-
-cdef class SinOfSquareFunction(Function):
- cpdef double evaluate(self, double x) except *:
- return sin(x ** 2)
+from libc.math cimport sin + + +cdef class Function: + + cpdef double evaluate(self, double x) except *: + return 0 + + +cdef class SinOfSquareFunction(Function): + + cpdef double evaluate(self, double x) except *: + return sin(x ** 2) diff --git a/docs/examples/tutorial/cdef_classes/wave_function.py b/docs/examples/tutorial/cdef_classes/wave_function.py new file mode 100644 index 000000000..7ff59a762 --- /dev/null +++ b/docs/examples/tutorial/cdef_classes/wave_function.py @@ -0,0 +1,22 @@ +from cython.cimports.sin_of_square import Function + +@cython.cclass +class WaveFunction(Function): + + # Not available in Python-space: + offset: float + + # Available in Python-space: + freq = cython.declare(cython.double, visibility='public') + + # Available in Python-space, but only for reading: + scale = cython.declare(cython.double, visibility='readonly') + + # Available in Python-space: + @property + def period(self): + return 1.0 / self.freq + + @period.setter + def period(self, value): + self.freq = 1.0 / value diff --git a/docs/examples/tutorial/cdef_classes/wave_function.pyx b/docs/examples/tutorial/cdef_classes/wave_function.pyx index aa35d954e..34b144667 100644 --- a/docs/examples/tutorial/cdef_classes/wave_function.pyx +++ b/docs/examples/tutorial/cdef_classes/wave_function.pyx @@ -1,21 +1,22 @@ -from sin_of_square cimport Function
-
-cdef class WaveFunction(Function):
-
- # Not available in Python-space:
- cdef double offset
-
- # Available in Python-space:
- cdef public double freq
-
- # Available in Python-space, but only for reading:
- cdef readonly double scale
-
- # Available in Python-space:
- @property
- def period(self):
- return 1.0 / self.freq
-
- @period.setter
- def period(self, value):
- self.freq = 1.0 / value
+from sin_of_square cimport Function + + +cdef class WaveFunction(Function): + + # Not available in Python-space: + cdef double offset + + # Available in Python-space: + cdef public double freq + + # Available in Python-space, but only for reading: + cdef readonly double scale + + # Available in Python-space: + @property + def period(self): + return 1.0 / self.freq + + @period.setter + def period(self, value): + self.freq = 1.0 / value diff --git a/docs/examples/tutorial/clibraries/cqueue.pxd b/docs/examples/tutorial/clibraries/cqueue.pxd index 13a07d317..a657ae331 100644 --- a/docs/examples/tutorial/clibraries/cqueue.pxd +++ b/docs/examples/tutorial/clibraries/cqueue.pxd @@ -1,5 +1,3 @@ -# cqueue.pxd
-
cdef extern from "c-algorithms/src/queue.h":
ctypedef struct Queue:
pass
diff --git a/docs/examples/tutorial/clibraries/queue.py b/docs/examples/tutorial/clibraries/queue.py new file mode 100644 index 000000000..e99b9b32c --- /dev/null +++ b/docs/examples/tutorial/clibraries/queue.py @@ -0,0 +1,8 @@ +from cython.cimports import cqueue + +@cython.cclass +class Queue: + _c_queue: cython.pointer(cqueue.Queue) + + def __cinit__(self): + self._c_queue = cqueue.queue_new() diff --git a/docs/examples/tutorial/clibraries/queue.pyx b/docs/examples/tutorial/clibraries/queue.pyx index 5363ee4f5..654c07b8d 100644 --- a/docs/examples/tutorial/clibraries/queue.pyx +++ b/docs/examples/tutorial/clibraries/queue.pyx @@ -1,9 +1,8 @@ -# queue.pyx
-
-cimport cqueue
-
-cdef class Queue:
- cdef cqueue.Queue* _c_queue
-
- def __cinit__(self):
- self._c_queue = cqueue.queue_new()
+cimport cqueue + + +cdef class Queue: + cdef cqueue.Queue* _c_queue + + def __cinit__(self): + self._c_queue = cqueue.queue_new() diff --git a/docs/examples/tutorial/clibraries/queue2.py b/docs/examples/tutorial/clibraries/queue2.py new file mode 100644 index 000000000..de6d58a99 --- /dev/null +++ b/docs/examples/tutorial/clibraries/queue2.py @@ -0,0 +1,10 @@ +from cython.cimports import cqueue + +@cython.cclass +class Queue: + _c_queue = cython.declare(cython.pointer(cqueue.Queue)) + + def __cinit__(self): + self._c_queue = cqueue.queue_new() + if self._c_queue is cython.NULL: + raise MemoryError() diff --git a/docs/examples/tutorial/clibraries/queue2.pyx b/docs/examples/tutorial/clibraries/queue2.pyx index 9278fbf4b..5dca04c22 100644 --- a/docs/examples/tutorial/clibraries/queue2.pyx +++ b/docs/examples/tutorial/clibraries/queue2.pyx @@ -1,11 +1,10 @@ -# queue.pyx
-
-cimport cqueue
-
-cdef class Queue:
- cdef cqueue.Queue* _c_queue
-
- def __cinit__(self):
- self._c_queue = cqueue.queue_new()
- if self._c_queue is NULL:
- raise MemoryError()
+cimport cqueue + + +cdef class Queue: + cdef cqueue.Queue* _c_queue + + def __cinit__(self): + self._c_queue = cqueue.queue_new() + if self._c_queue is NULL: + raise MemoryError() diff --git a/docs/examples/tutorial/clibraries/queue3.py b/docs/examples/tutorial/clibraries/queue3.py new file mode 100644 index 000000000..79f341254 --- /dev/null +++ b/docs/examples/tutorial/clibraries/queue3.py @@ -0,0 +1,68 @@ +from cython.cimports import cqueue +from cython import cast + +@cython.cclass +class Queue: + """A queue class for C integer values. + + >>> q = Queue() + >>> q.append(5) + >>> q.peek() + 5 + >>> q.pop() + 5 + """ + _c_queue = cython.declare(cython.pointer(cqueue.Queue)) + def __cinit__(self): + self._c_queue = cqueue.queue_new() + if self._c_queue is cython.NULL: + raise MemoryError() + + def __dealloc__(self): + if self._c_queue is not cython.NULL: + cqueue.queue_free(self._c_queue) + + @cython.ccall + def append(self, value: cython.int): + if not cqueue.queue_push_tail(self._c_queue, + cast(cython.p_void, cast(cython.Py_ssize_t, value))): + raise MemoryError() + + # The `cpdef` feature is obviously not available for the original "extend()" + # method, as the method signature is incompatible with Python argument + # types (Python does not have pointers). However, we can rename + # the C-ish "extend()" method to e.g. "extend_ints()", and write + # a new "extend()" method that provides a suitable Python interface by + # accepting an arbitrary Python iterable. + @cython.ccall + def extend(self, values): + for value in values: + self.append(value) + + @cython.cfunc + def extend_ints(self, values: cython.p_int, count: cython.size_t): + value: cython.int + for value in values[:count]: # Slicing pointer to limit the iteration boundaries. + self.append(value) + + @cython.ccall + @cython.exceptval(-1, check=True) + def peek(self) -> cython.int: + value: cython.int = cast(cython.Py_ssize_t, cqueue.queue_peek_head(self._c_queue)) + + if value == 0: + # this may mean that the queue is empty, + # or that it happens to contain a 0 value + if cqueue.queue_is_empty(self._c_queue): + raise IndexError("Queue is empty") + return value + + @cython.ccall + @cython.exceptval(-1, check=True) + def pop(self) -> cython.int: + if cqueue.queue_is_empty(self._c_queue): + raise IndexError("Queue is empty") + return cast(cython.Py_ssize_t, cqueue.queue_pop_head(self._c_queue)) + + def __bool__(self): + return not cqueue.queue_is_empty(self._c_queue) diff --git a/docs/examples/tutorial/clibraries/queue3.pyx b/docs/examples/tutorial/clibraries/queue3.pyx index cc84cf172..c15c48e15 100644 --- a/docs/examples/tutorial/clibraries/queue3.pyx +++ b/docs/examples/tutorial/clibraries/queue3.pyx @@ -1,7 +1,7 @@ -# queue.pyx - cimport cqueue + + cdef class Queue: """A queue class for C integer values. @@ -22,6 +22,7 @@ cdef class Queue: if self._c_queue is not NULL: cqueue.queue_free(self._c_queue) + cpdef append(self, int value): if not cqueue.queue_push_tail(self._c_queue, <void*> <Py_ssize_t> value): @@ -33,15 +34,19 @@ cdef class Queue: # the C-ish "extend()" method to e.g. "extend_ints()", and write # a new "extend()" method that provides a suitable Python interface by # accepting an arbitrary Python iterable. + cpdef extend(self, values): for value in values: self.append(value) + cdef extend_ints(self, int* values, size_t count): cdef int value for value in values[:count]: # Slicing pointer to limit the iteration boundaries. self.append(value) + + cpdef int peek(self) except? -1: cdef int value = <Py_ssize_t> cqueue.queue_peek_head(self._c_queue) @@ -52,6 +57,8 @@ cdef class Queue: raise IndexError("Queue is empty") return value + + cpdef int pop(self) except? -1: if cqueue.queue_is_empty(self._c_queue): raise IndexError("Queue is empty") diff --git a/docs/examples/tutorial/clibraries/test_queue.py b/docs/examples/tutorial/clibraries/test_queue.py index 5390a82c1..41b267395 100644 --- a/docs/examples/tutorial/clibraries/test_queue.py +++ b/docs/examples/tutorial/clibraries/test_queue.py @@ -1,36 +1,36 @@ -from __future__ import print_function
-
-import time
-
-import queue
-
-Q = queue.Queue()
-
-Q.append(10)
-Q.append(20)
-print(Q.peek())
-print(Q.pop())
-print(Q.pop())
-try:
- print(Q.pop())
-except IndexError as e:
- print("Error message:", e) # Prints "Queue is empty"
-
-i = 10000
-
-values = range(i)
-
-start_time = time.time()
-
-Q.extend(values)
-
-end_time = time.time() - start_time
-
-print("Adding {} items took {:1.3f} msecs.".format(i, 1000 * end_time))
-
-for i in range(41):
- Q.pop()
-
-Q.pop()
-print("The answer is:")
-print(Q.pop())
+from __future__ import print_function + +import time + +import queue + +Q = queue.Queue() + +Q.append(10) +Q.append(20) +print(Q.peek()) +print(Q.pop()) +print(Q.pop()) +try: + print(Q.pop()) +except IndexError as e: + print("Error message:", e) # Prints "Queue is empty" + +i = 10000 + +values = range(i) + +start_time = time.time() + +Q.extend(values) + +end_time = time.time() - start_time + +print("Adding {} items took {:1.3f} msecs.".format(i, 1000 * end_time)) + +for i in range(41): + Q.pop() + +Q.pop() +print("The answer is:") +print(Q.pop()) diff --git a/docs/examples/tutorial/cython_tutorial/primes.py b/docs/examples/tutorial/cython_tutorial/primes.py new file mode 100644 index 000000000..645d9479d --- /dev/null +++ b/docs/examples/tutorial/cython_tutorial/primes.py @@ -0,0 +1,27 @@ +def primes(nb_primes: cython.int): + i: cython.int + p: cython.int[1000] + + if nb_primes > 1000: + nb_primes = 1000 + + if not cython.compiled: # Only if regular Python is running + p = [0] * 1000 # Make p work almost like a C array + + len_p: cython.int = 0 # The current number of elements in p. + n: cython.int = 2 + while len_p < nb_primes: + # Is n prime? + for i in p[:len_p]: + if n % i == 0: + break + + # If no break occurred in the loop, we have a prime. + else: + p[len_p] = n + len_p += 1 + n += 1 + + # Let's copy the result into a Python list: + result_as_list = [prime for prime in p[:len_p]] + return result_as_list diff --git a/docs/examples/tutorial/cython_tutorial/primes.pyx b/docs/examples/tutorial/cython_tutorial/primes.pyx index 96ecdb59a..7707e30dc 100644 --- a/docs/examples/tutorial/cython_tutorial/primes.pyx +++ b/docs/examples/tutorial/cython_tutorial/primes.pyx @@ -1,9 +1,13 @@ def primes(int nb_primes): cdef int n, i, len_p - cdef int p[1000] + cdef int[1000] p + if nb_primes > 1000: nb_primes = 1000 + + + len_p = 0 # The current number of elements in p. n = 2 while len_p < nb_primes: @@ -18,6 +22,6 @@ def primes(int nb_primes): len_p += 1 n += 1 - # Let's return the result in a python list: - result_as_list = [prime for prime in p[:len_p]] + # Let's copy the result into a Python list: + result_as_list = [prime for prime in p[:len_p]] return result_as_list diff --git a/docs/examples/tutorial/cython_tutorial/primes_cpp.py b/docs/examples/tutorial/cython_tutorial/primes_cpp.py new file mode 100644 index 000000000..468d00c46 --- /dev/null +++ b/docs/examples/tutorial/cython_tutorial/primes_cpp.py @@ -0,0 +1,22 @@ +# distutils: language=c++ + +import cython +from cython.cimports.libcpp.vector import vector + +def primes(nb_primes: cython.uint): + i: cython.int + p: vector[cython.int] + p.reserve(nb_primes) # allocate memory for 'nb_primes' elements. + + n: cython.int = 2 + while p.size() < nb_primes: # size() for vectors is similar to len() + for i in p: + if n % i == 0: + break + else: + p.push_back(n) # push_back is similar to append() + n += 1 + + # If possible, C values and C++ objects are automatically + # converted to Python objects at need. + return p # so here, the vector will be copied into a Python list. diff --git a/docs/examples/tutorial/cython_tutorial/primes_cpp.pyx b/docs/examples/tutorial/cython_tutorial/primes_cpp.pyx index 57bfe9cc2..afef8bd13 100644 --- a/docs/examples/tutorial/cython_tutorial/primes_cpp.pyx +++ b/docs/examples/tutorial/cython_tutorial/primes_cpp.pyx @@ -1,21 +1,22 @@ -# distutils: language=c++
-
-from libcpp.vector cimport vector
-
-def primes(unsigned int nb_primes):
- cdef int n, i
- cdef vector[int] p
- p.reserve(nb_primes) # allocate memory for 'nb_primes' elements.
-
- n = 2
- while p.size() < nb_primes: # size() for vectors is similar to len()
- for i in p:
- if n % i == 0:
- break
- else:
- p.push_back(n) # push_back is similar to append()
- n += 1
-
- # Vectors are automatically converted to Python
- # lists when converted to Python objects.
- return p
+# distutils: language=c++ + + +from libcpp.vector cimport vector + +def primes(unsigned int nb_primes): + cdef int n, i + cdef vector[int] p + p.reserve(nb_primes) # allocate memory for 'nb_primes' elements. + + n = 2 + while p.size() < nb_primes: # size() for vectors is similar to len() + for i in p: + if n % i == 0: + break + else: + p.push_back(n) # push_back is similar to append() + n += 1 + + # If possible, C values and C++ objects are automatically + # converted to Python objects at need. + return p # so here, the vector will be copied into a Python list. diff --git a/docs/examples/tutorial/cython_tutorial/primes_python.py b/docs/examples/tutorial/cython_tutorial/primes_python.py index f6559d519..845af5bbf 100644 --- a/docs/examples/tutorial/cython_tutorial/primes_python.py +++ b/docs/examples/tutorial/cython_tutorial/primes_python.py @@ -1,4 +1,4 @@ -def primes_python(nb_primes): +def primes(nb_primes): p = [] n = 2 while len(p) < nb_primes: diff --git a/docs/examples/tutorial/cython_tutorial/setup.py b/docs/examples/tutorial/cython_tutorial/setup.py deleted file mode 100644 index 302a08e5f..000000000 --- a/docs/examples/tutorial/cython_tutorial/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -from distutils.core import setup -from Cython.Build import cythonize - -setup( - ext_modules=cythonize("fib.pyx"), -) diff --git a/docs/examples/tutorial/embedding/embedded.pyx b/docs/examples/tutorial/embedding/embedded.pyx new file mode 100644 index 000000000..2ed823945 --- /dev/null +++ b/docs/examples/tutorial/embedding/embedded.pyx @@ -0,0 +1,12 @@ +# embedded.pyx + +# The following two lines are for test purposes only, please ignore them. +# distutils: sources = embedded_main.c +# tag: py3only +# tag: no-cpp + +TEXT_TO_SAY = 'Hello from Python!' + +cdef public int say_hello_from_python() except -1: + print(TEXT_TO_SAY) + return 0 diff --git a/docs/examples/tutorial/embedding/embedded_main.c b/docs/examples/tutorial/embedding/embedded_main.c new file mode 100644 index 000000000..e14901a5e --- /dev/null +++ b/docs/examples/tutorial/embedding/embedded_main.c @@ -0,0 +1,69 @@ +/* embedded_main.c */ + +/* This include file is automatically generated by Cython for 'public' functions. */ +#include "embedded.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int +main(int argc, char *argv[]) +{ + PyObject *pmodule; + wchar_t *program; + + program = Py_DecodeLocale(argv[0], NULL); + if (program == NULL) { + fprintf(stderr, "Fatal error: cannot decode argv[0], got %d arguments\n", argc); + exit(1); + } + + /* Add a built-in module, before Py_Initialize */ + if (PyImport_AppendInittab("embedded", PyInit_embedded) == -1) { + fprintf(stderr, "Error: could not extend in-built modules table\n"); + exit(1); + } + + /* Pass argv[0] to the Python interpreter */ + Py_SetProgramName(program); + + /* Initialize the Python interpreter. Required. + If this step fails, it will be a fatal error. */ + Py_Initialize(); + + /* Optionally import the module; alternatively, + import can be deferred until the embedded script + imports it. */ + pmodule = PyImport_ImportModule("embedded"); + if (!pmodule) { + PyErr_Print(); + fprintf(stderr, "Error: could not import module 'embedded'\n"); + goto exit_with_error; + } + + /* Now call into your module code. */ + if (say_hello_from_python() < 0) { + PyErr_Print(); + fprintf(stderr, "Error in Python code, exception was printed.\n"); + goto exit_with_error; + } + + /* ... */ + + /* Clean up after using CPython. */ + PyMem_RawFree(program); + Py_Finalize(); + + return 0; + + /* Clean up in the error cases above. */ +exit_with_error: + PyMem_RawFree(program); + Py_Finalize(); + return 1; +} + +#ifdef __cplusplus +} +#endif diff --git a/docs/examples/tutorial/external/atoi.py b/docs/examples/tutorial/external/atoi.py new file mode 100644 index 000000000..250b26a5c --- /dev/null +++ b/docs/examples/tutorial/external/atoi.py @@ -0,0 +1,6 @@ +from cython.cimports.libc.stdlib import atoi + +@cython.cfunc +def parse_charptr_to_py_int(s: cython.p_char): + assert s is not cython.NULL, "byte string value is NULL" + return atoi(s) # note: atoi() has no error detection! diff --git a/docs/examples/tutorial/external/atoi.pyx b/docs/examples/tutorial/external/atoi.pyx index 48643bbf2..ef1219854 100644 --- a/docs/examples/tutorial/external/atoi.pyx +++ b/docs/examples/tutorial/external/atoi.pyx @@ -1,5 +1,6 @@ -from libc.stdlib cimport atoi
-
-cdef parse_charptr_to_py_int(char* s):
- assert s is not NULL, "byte string value is NULL"
- return atoi(s) # note: atoi() has no error detection!
+from libc.stdlib cimport atoi + + +cdef parse_charptr_to_py_int(char* s): + assert s is not NULL, "byte string value is NULL" + return atoi(s) # note: atoi() has no error detection! diff --git a/docs/examples/tutorial/external/cpdef_sin.pyx b/docs/examples/tutorial/external/cpdef_sin.pyx index 47e09f433..eee2326a4 100644 --- a/docs/examples/tutorial/external/cpdef_sin.pyx +++ b/docs/examples/tutorial/external/cpdef_sin.pyx @@ -1,7 +1,7 @@ -"""
->>> sin(0)
-0.0
-"""
-
-cdef extern from "math.h":
- cpdef double sin(double x)
+""" +>>> sin(0) +0.0 +""" + +cdef extern from "math.h": + cpdef double sin(double x) diff --git a/docs/examples/tutorial/external/keyword_args.pyx b/docs/examples/tutorial/external/keyword_args.pyx index 327e4e08b..7c2a786cc 100644 --- a/docs/examples/tutorial/external/keyword_args.pyx +++ b/docs/examples/tutorial/external/keyword_args.pyx @@ -1,2 +1,2 @@ -cdef extern from "string.h":
- char* strstr(const char *haystack, const char *needle)
+cdef extern from "string.h": + char* strstr(const char *haystack, const char *needle) diff --git a/docs/examples/tutorial/external/keyword_args_call.py b/docs/examples/tutorial/external/keyword_args_call.py new file mode 100644 index 000000000..b3b3f5049 --- /dev/null +++ b/docs/examples/tutorial/external/keyword_args_call.py @@ -0,0 +1,7 @@ +from cython.cimports.strstr import strstr + +def main(): + data: cython.p_char = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh" + + pos = strstr(needle='akd', haystack=data) + print(pos is not cython.NULL) diff --git a/docs/examples/tutorial/external/keyword_args_call.pyx b/docs/examples/tutorial/external/keyword_args_call.pyx index 4be5f755d..de2b6f2b2 100644 --- a/docs/examples/tutorial/external/keyword_args_call.pyx +++ b/docs/examples/tutorial/external/keyword_args_call.pyx @@ -1,7 +1,7 @@ -cdef extern from "string.h":
- char* strstr(const char *haystack, const char *needle)
-
-cdef char* data = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh"
-
-cdef char* pos = strstr(needle='akd', haystack=data)
-print(pos is not NULL)
+cdef extern from "string.h": + char* strstr(const char *haystack, const char *needle) + +cdef char* data = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh" + +cdef char* pos = strstr(needle='akd', haystack=data) +print(pos is not NULL) diff --git a/docs/examples/tutorial/external/libc_sin.py b/docs/examples/tutorial/external/libc_sin.py new file mode 100644 index 000000000..f4223253d --- /dev/null +++ b/docs/examples/tutorial/external/libc_sin.py @@ -0,0 +1,5 @@ +from cython.cimports.libc.math import sin + +@cython.cfunc +def f(x: cython.double) -> cython.double: + return sin(x * x) diff --git a/docs/examples/tutorial/external/libc_sin.pyx b/docs/examples/tutorial/external/libc_sin.pyx index 25a4430e3..2de8444d6 100644 --- a/docs/examples/tutorial/external/libc_sin.pyx +++ b/docs/examples/tutorial/external/libc_sin.pyx @@ -1,4 +1,5 @@ -from libc.math cimport sin
-
-cdef double f(double x):
- return sin(x * x)
+from libc.math cimport sin + + +cdef double f(double x): + return sin(x * x) diff --git a/docs/examples/tutorial/external/py_version_hex.py b/docs/examples/tutorial/external/py_version_hex.py new file mode 100644 index 000000000..3b19d0d02 --- /dev/null +++ b/docs/examples/tutorial/external/py_version_hex.py @@ -0,0 +1,4 @@ +from cython.cimports.cpython.version import PY_VERSION_HEX + +# Python version >= 3.2 final ? +print(PY_VERSION_HEX >= 0x030200F0) diff --git a/docs/examples/tutorial/external/py_version_hex.pyx b/docs/examples/tutorial/external/py_version_hex.pyx index d732b00e7..e33f207c1 100644 --- a/docs/examples/tutorial/external/py_version_hex.pyx +++ b/docs/examples/tutorial/external/py_version_hex.pyx @@ -1,4 +1,4 @@ -from cpython.version cimport PY_VERSION_HEX
-
-# Python version >= 3.2 final ?
-print(PY_VERSION_HEX >= 0x030200F0)
+from cpython.version cimport PY_VERSION_HEX + +# Python version >= 3.2 final ? +print(PY_VERSION_HEX >= 0x030200F0) diff --git a/docs/examples/tutorial/external/setup.py b/docs/examples/tutorial/external/setup.py index 653214c84..289bc9534 100644 --- a/docs/examples/tutorial/external/setup.py +++ b/docs/examples/tutorial/external/setup.py @@ -1,13 +1,12 @@ -from distutils.core import setup
-from distutils.extension import Extension
-from Cython.Build import cythonize
-
-ext_modules = [
- Extension("demo",
- sources=["demo.pyx"],
- libraries=["m"] # Unix-like specific
- )
-]
-
-setup(name="Demos",
- ext_modules=cythonize(ext_modules))
+from setuptools import Extension, setup +from Cython.Build import cythonize + +ext_modules = [ + Extension("demo", + sources=["demo.pyx"], + libraries=["m"] # Unix-like specific + ) +] + +setup(name="Demos", + ext_modules=cythonize(ext_modules)) diff --git a/docs/examples/tutorial/external/strstr.pxd b/docs/examples/tutorial/external/strstr.pxd new file mode 100644 index 000000000..7c2a786cc --- /dev/null +++ b/docs/examples/tutorial/external/strstr.pxd @@ -0,0 +1,2 @@ +cdef extern from "string.h": + char* strstr(const char *haystack, const char *needle) diff --git a/docs/examples/tutorial/memory_allocation/malloc.py b/docs/examples/tutorial/memory_allocation/malloc.py new file mode 100644 index 000000000..fb7e82236 --- /dev/null +++ b/docs/examples/tutorial/memory_allocation/malloc.py @@ -0,0 +1,24 @@ +import random +from cython.cimports.libc.stdlib import malloc, free + +def random_noise(number: cython.int = 1): + i: cython.int + # allocate number * sizeof(double) bytes of memory + my_array: cython.p_double = cython.cast(cython.p_double, malloc( + number * cython.sizeof(cython.double))) + if not my_array: + raise MemoryError() + + try: + ran = random.normalvariate + for i in range(number): + my_array[i] = ran(0, 1) + + # ... let's just assume we do some more heavy C calculations here to make up + # for the work that it takes to pack the C double values into Python float + # objects below, right after throwing away the existing objects above. + + return [x for x in my_array[:number]] + finally: + # return the previously allocated memory to the system + free(my_array) diff --git a/docs/examples/tutorial/memory_allocation/malloc.pyx b/docs/examples/tutorial/memory_allocation/malloc.pyx index e01a378e3..6aa583aab 100644 --- a/docs/examples/tutorial/memory_allocation/malloc.pyx +++ b/docs/examples/tutorial/memory_allocation/malloc.pyx @@ -1,23 +1,24 @@ -import random
-from libc.stdlib cimport malloc, free
-
-def random_noise(int number=1):
- cdef int i
- # allocate number * sizeof(double) bytes of memory
- cdef double *my_array = <double *> malloc(number * sizeof(double))
- if not my_array:
- raise MemoryError()
-
- try:
- ran = random.normalvariate
- for i in range(number):
- my_array[i] = ran(0, 1)
-
- # ... let's just assume we do some more heavy C calculations here to make up
- # for the work that it takes to pack the C double values into Python float
- # objects below, right after throwing away the existing objects above.
-
- return [x for x in my_array[:number]]
- finally:
- # return the previously allocated memory to the system
- free(my_array)
+import random +from libc.stdlib cimport malloc, free + +def random_noise(int number=1): + cdef int i + # allocate number * sizeof(double) bytes of memory + cdef double *my_array = <double *> malloc( + number * sizeof(double)) + if not my_array: + raise MemoryError() + + try: + ran = random.normalvariate + for i in range(number): + my_array[i] = ran(0, 1) + + # ... let's just assume we do some more heavy C calculations here to make up + # for the work that it takes to pack the C double values into Python float + # objects below, right after throwing away the existing objects above. + + return [x for x in my_array[:number]] + finally: + # return the previously allocated memory to the system + free(my_array) diff --git a/docs/examples/tutorial/memory_allocation/some_memory.py b/docs/examples/tutorial/memory_allocation/some_memory.py new file mode 100644 index 000000000..31ad63a6e --- /dev/null +++ b/docs/examples/tutorial/memory_allocation/some_memory.py @@ -0,0 +1,27 @@ +from cython.cimports.cpython.mem import PyMem_Malloc, PyMem_Realloc, PyMem_Free + +@cython.cclass +class SomeMemory: + data: cython.p_double + + def __cinit__(self, number: cython.size_t): + # allocate some memory (uninitialised, may contain arbitrary data) + self.data = cython.cast(cython.p_double, PyMem_Malloc( + number * cython.sizeof(cython.double))) + if not self.data: + raise MemoryError() + + def resize(self, new_number: cython.size_t): + # Allocates new_number * sizeof(double) bytes, + # preserving the current content and making a best-effort to + # re-use the original data location. + mem = cython.cast(cython.p_double, PyMem_Realloc( + self.data, new_number * cython.sizeof(cython.double))) + if not mem: + raise MemoryError() + # Only overwrite the pointer if the memory was really reallocated. + # On error (mem is NULL), the originally memory has not been freed. + self.data = mem + + def __dealloc__(self): + PyMem_Free(self.data) # no-op if self.data is NULL diff --git a/docs/examples/tutorial/memory_allocation/some_memory.pyx b/docs/examples/tutorial/memory_allocation/some_memory.pyx index 2e639ac4d..e6bb63b77 100644 --- a/docs/examples/tutorial/memory_allocation/some_memory.pyx +++ b/docs/examples/tutorial/memory_allocation/some_memory.pyx @@ -1,25 +1,27 @@ -from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
-
-cdef class SomeMemory:
-
- cdef double* data
-
- def __cinit__(self, size_t number):
- # allocate some memory (uninitialised, may contain arbitrary data)
- self.data = <double*> PyMem_Malloc(number * sizeof(double))
- if not self.data:
- raise MemoryError()
-
- def resize(self, size_t new_number):
- # Allocates new_number * sizeof(double) bytes,
- # preserving the current content and making a best-effort to
- # re-use the original data location.
- mem = <double*> PyMem_Realloc(self.data, new_number * sizeof(double))
- if not mem:
- raise MemoryError()
- # Only overwrite the pointer if the memory was really reallocated.
- # On error (mem is NULL), the originally memory has not been freed.
- self.data = mem
-
- def __dealloc__(self):
- PyMem_Free(self.data) # no-op if self.data is NULL
+from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free + + +cdef class SomeMemory: + cdef double* data + + def __cinit__(self, size_t number): + # allocate some memory (uninitialised, may contain arbitrary data) + self.data = <double*> PyMem_Malloc( + number * sizeof(double)) + if not self.data: + raise MemoryError() + + def resize(self, size_t new_number): + # Allocates new_number * sizeof(double) bytes, + # preserving the current content and making a best-effort to + # re-use the original data location. + mem = <double*> PyMem_Realloc( + self.data, new_number * sizeof(double)) + if not mem: + raise MemoryError() + # Only overwrite the pointer if the memory was really reallocated. + # On error (mem is NULL), the originally memory has not been freed. + self.data = mem + + def __dealloc__(self): + PyMem_Free(self.data) # no-op if self.data is NULL diff --git a/docs/examples/tutorial/numpy/convolve2.pyx b/docs/examples/tutorial/numpy/convolve2.pyx index be7512fe1..b77b92f53 100644 --- a/docs/examples/tutorial/numpy/convolve2.pyx +++ b/docs/examples/tutorial/numpy/convolve2.pyx @@ -1,4 +1,4 @@ -# tag: numpy_old +# tag: numpy # You can ignore the previous line. # It's for internal testing of the cython documentation. @@ -9,6 +9,12 @@ import numpy as np # currently part of the Cython distribution). cimport numpy as np +# It's necessary to call "import_array" if you use any part of the +# numpy PyArray_* API. From Cython 3, accessing attributes like +# ".shape" on a typed Numpy array use this API. Therefore we recommend +# always calling "import_array" whenever you "cimport numpy" +np.import_array() + # We now need to fix a datatype for our arrays. I've used the variable # DTYPE for this, which is assigned to the usual NumPy runtime # type info object. diff --git a/docs/examples/tutorial/numpy/convolve_py.py b/docs/examples/tutorial/numpy/convolve_py.py index c3cbc5f86..39b276a04 100644 --- a/docs/examples/tutorial/numpy/convolve_py.py +++ b/docs/examples/tutorial/numpy/convolve_py.py @@ -1,43 +1,43 @@ -import numpy as np
-
-
-def naive_convolve(f, g):
- # f is an image and is indexed by (v, w)
- # g is a filter kernel and is indexed by (s, t),
- # it needs odd dimensions
- # h is the output image and is indexed by (x, y),
- # it is not cropped
- if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1:
- raise ValueError("Only odd dimensions on filter supported")
- # smid and tmid are number of pixels between the center pixel
- # and the edge, ie for a 5x5 filter they will be 2.
- #
- # The output size is calculated by adding smid, tmid to each
- # side of the dimensions of the input image.
- vmax = f.shape[0]
- wmax = f.shape[1]
- smax = g.shape[0]
- tmax = g.shape[1]
- smid = smax // 2
- tmid = tmax // 2
- xmax = vmax + 2 * smid
- ymax = wmax + 2 * tmid
- # Allocate result image.
- h = np.zeros([xmax, ymax], dtype=f.dtype)
- # Do convolution
- for x in range(xmax):
- for y in range(ymax):
- # Calculate pixel value for h at (x,y). Sum one component
- # for each pixel (s, t) of the filter g.
- s_from = max(smid - x, -smid)
- s_to = min((xmax - x) - smid, smid + 1)
- t_from = max(tmid - y, -tmid)
- t_to = min((ymax - y) - tmid, tmid + 1)
- value = 0
- for s in range(s_from, s_to):
- for t in range(t_from, t_to):
- v = x - smid + s
- w = y - tmid + t
- value += g[smid - s, tmid - t] * f[v, w]
- h[x, y] = value
- return h
+import numpy as np + + +def naive_convolve(f, g): + # f is an image and is indexed by (v, w) + # g is a filter kernel and is indexed by (s, t), + # it needs odd dimensions + # h is the output image and is indexed by (x, y), + # it is not cropped + if g.shape[0] % 2 != 1 or g.shape[1] % 2 != 1: + raise ValueError("Only odd dimensions on filter supported") + # smid and tmid are number of pixels between the center pixel + # and the edge, ie for a 5x5 filter they will be 2. + # + # The output size is calculated by adding smid, tmid to each + # side of the dimensions of the input image. + vmax = f.shape[0] + wmax = f.shape[1] + smax = g.shape[0] + tmax = g.shape[1] + smid = smax // 2 + tmid = tmax // 2 + xmax = vmax + 2 * smid + ymax = wmax + 2 * tmid + # Allocate result image. + h = np.zeros([xmax, ymax], dtype=f.dtype) + # Do convolution + for x in range(xmax): + for y in range(ymax): + # Calculate pixel value for h at (x,y). Sum one component + # for each pixel (s, t) of the filter g. + s_from = max(smid - x, -smid) + s_to = min((xmax - x) - smid, smid + 1) + t_from = max(tmid - y, -tmid) + t_to = min((ymax - y) - tmid, tmid + 1) + value = 0 + for s in range(s_from, s_to): + for t in range(t_from, t_to): + v = x - smid + s + w = y - tmid + t + value += g[smid - s, tmid - t] * f[v, w] + h[x, y] = value + return h diff --git a/docs/examples/tutorial/parallelization/manual_work.py b/docs/examples/tutorial/parallelization/manual_work.py new file mode 100644 index 000000000..d6b0167d9 --- /dev/null +++ b/docs/examples/tutorial/parallelization/manual_work.py @@ -0,0 +1,24 @@ +# tag: openmp + +from cython.parallel import parallel +from cython.cimports.openmp import omp_get_thread_num +import cython + +@cython.cfunc +@cython.nogil +def long_running_task1() -> cython.void: + pass + +@cython.cfunc +@cython.nogil +def long_running_task2() -> cython.void: + pass + +def do_two_tasks(): + thread_num: cython.int + with cython.nogil, parallel(num_threads=2): + thread_num = omp_get_thread_num() + if thread_num == 0: + long_running_task1() + elif thread_num == 1: + long_running_task2() diff --git a/docs/examples/tutorial/parallelization/manual_work.pyx b/docs/examples/tutorial/parallelization/manual_work.pyx new file mode 100644 index 000000000..886015839 --- /dev/null +++ b/docs/examples/tutorial/parallelization/manual_work.pyx @@ -0,0 +1,25 @@ +# tag: openmp + +from cython.parallel cimport parallel +from openmp cimport omp_get_thread_num + + + + +cdef void long_running_task1() nogil: + pass + + + +cdef void long_running_task2() nogil: + pass + +def do_two_tasks(): + cdef int thread_num + with nogil, parallel(num_threads=2): + thread_num = omp_get_thread_num() + if thread_num == 0: + long_running_task1() + elif thread_num == 1: + long_running_task2() + diff --git a/docs/examples/tutorial/parallelization/median.py b/docs/examples/tutorial/parallelization/median.py new file mode 100644 index 000000000..535a2b136 --- /dev/null +++ b/docs/examples/tutorial/parallelization/median.py @@ -0,0 +1,35 @@ +# distutils: language = c++ + +from cython.parallel import parallel, prange +from cython.cimports.libc.stdlib import malloc, free +from cython.cimports.libcpp.algorithm import nth_element +import cython +from cython.operator import dereference + +import numpy as np + +@cython.boundscheck(False) +@cython.wraparound(False) +def median_along_axis0(x: cython.double[:,:]): + out: cython.double[::1] = np.empty(x.shape[1]) + i: cython.Py_ssize_t + j: cython.Py_ssize_t + scratch: cython.pointer(cython.double) + median_it: cython.pointer(cython.double) + with cython.nogil, parallel(): + # allocate scratch space per loop + scratch = cython.cast( + cython.pointer(cython.double), + malloc(cython.sizeof(cython.double)*x.shape[0])) + try: + for i in prange(x.shape[1]): + # copy row into scratch space + for j in range(x.shape[0]): + scratch[j] = x[j, i] + median_it = scratch + x.shape[0]//2 + nth_element(scratch, median_it, scratch + x.shape[0]) + # for the sake of a simple example, don't handle even lengths... + out[i] = dereference(median_it) + finally: + free(scratch) + return np.asarray(out) diff --git a/docs/examples/tutorial/parallelization/median.pyx b/docs/examples/tutorial/parallelization/median.pyx new file mode 100644 index 000000000..242cb6091 --- /dev/null +++ b/docs/examples/tutorial/parallelization/median.pyx @@ -0,0 +1,34 @@ +# distutils: language = c++ + +from cython.parallel cimport parallel, prange +from libcpp.vector cimport vector +from libcpp.algorithm cimport nth_element +cimport cython +from cython.operator cimport dereference + +import numpy as np + +@cython.boundscheck(False) +@cython.wraparound(False) +def median_along_axis0(const double[:,:] x): + cdef double[::1] out = np.empty(x.shape[1]) + cdef Py_ssize_t i, j + + cdef vector[double] *scratch + cdef vector[double].iterator median_it + with nogil, parallel(): + # allocate scratch space per loop + scratch = new vector[double](x.shape[0]) + try: + for i in prange(x.shape[1]): + # copy row into scratch space + for j in range(x.shape[0]): + dereference(scratch)[j] = x[j, i] + median_it = scratch.begin() + scratch.size()//2 + nth_element(scratch.begin(), median_it, scratch.end()) + # for the sake of a simple example, don't handle even lengths... + out[i] = dereference(median_it) + finally: + del scratch + return np.asarray(out) + diff --git a/docs/examples/tutorial/parallelization/norm.py b/docs/examples/tutorial/parallelization/norm.py new file mode 100644 index 000000000..1d8c2758a --- /dev/null +++ b/docs/examples/tutorial/parallelization/norm.py @@ -0,0 +1,12 @@ +from cython.parallel import prange +import cython +from cython.cimports.libc.math import sqrt + +@cython.boundscheck(False) +@cython.wraparound(False) +def l2norm(x: cython.double[:]): + total: cython.double = 0 + i: cython.Py_ssize_t + for i in prange(x.shape[0], nogil=True): + total += x[i]*x[i] + return sqrt(total) diff --git a/docs/examples/tutorial/parallelization/norm.pyx b/docs/examples/tutorial/parallelization/norm.pyx new file mode 100644 index 000000000..5a702f975 --- /dev/null +++ b/docs/examples/tutorial/parallelization/norm.pyx @@ -0,0 +1,12 @@ +from cython.parallel cimport prange +cimport cython +from libc.math cimport sqrt + +@cython.boundscheck(False) +@cython.wraparound(False) +def l2norm(double[:] x): + cdef double total = 0 + cdef Py_ssize_t i + for i in prange(x.shape[0], nogil=True): + total += x[i]*x[i] + return sqrt(total) diff --git a/docs/examples/tutorial/parallelization/normalize.py b/docs/examples/tutorial/parallelization/normalize.py new file mode 100644 index 000000000..0519be4d4 --- /dev/null +++ b/docs/examples/tutorial/parallelization/normalize.py @@ -0,0 +1,16 @@ +from cython.parallel import parallel, prange +import cython +from cython.cimports.libc.math import sqrt + +@cython.boundscheck(False) +@cython.wraparound(False) +def normalize(x: cython.double[:]): + i: cython.Py_ssize_t + total: cython.double = 0 + norm: cython.double + with cython.nogil, parallel(): + for i in prange(x.shape[0]): + total += x[i]*x[i] + norm = sqrt(total) + for i in prange(x.shape[0]): + x[i] /= norm diff --git a/docs/examples/tutorial/parallelization/normalize.pyx b/docs/examples/tutorial/parallelization/normalize.pyx new file mode 100644 index 000000000..e167ad7ad --- /dev/null +++ b/docs/examples/tutorial/parallelization/normalize.pyx @@ -0,0 +1,17 @@ +from cython.parallel cimport parallel, prange +cimport cython +from libc.math cimport sqrt + +@cython.boundscheck(False) +@cython.wraparound(False) +def normalize(double[:] x): + cdef Py_ssize_t i + cdef double total = 0 + cdef double norm + with nogil, parallel(): + for i in prange(x.shape[0]): + total += x[i]*x[i] + norm = sqrt(total) + for i in prange(x.shape[0]): + x[i] /= norm + diff --git a/docs/examples/tutorial/parallelization/parallel_sin.py b/docs/examples/tutorial/parallelization/parallel_sin.py new file mode 100644 index 000000000..be6cbc030 --- /dev/null +++ b/docs/examples/tutorial/parallelization/parallel_sin.py @@ -0,0 +1,16 @@ +from cython.parallel import prange +import cython +from cython.cimports.libc.math import sin + +import numpy as np + +@cython.boundscheck(False) +@cython.wraparound(False) +def do_sine(input: cython.double[:,:]): + output : cython.double[:,:] = np.empty_like(input) + i : cython.Py_ssize_t + j : cython.Py_ssize_t + for i in prange(input.shape[0], nogil=True): + for j in range(input.shape[1]): + output[i, j] = sin(input[i, j]) + return np.asarray(output) diff --git a/docs/examples/tutorial/parallelization/parallel_sin.pyx b/docs/examples/tutorial/parallelization/parallel_sin.pyx new file mode 100644 index 000000000..c3091541e --- /dev/null +++ b/docs/examples/tutorial/parallelization/parallel_sin.pyx @@ -0,0 +1,16 @@ +from cython.parallel cimport prange +cimport cython +from libc.math cimport sin + +import numpy as np + +@cython.boundscheck(False) +@cython.wraparound(False) +def do_sine(double[:,:] input): + cdef double[:,:] output = np.empty_like(input) + cdef Py_ssize_t i, j + + for i in prange(input.shape[0], nogil=True): + for j in range(input.shape[1]): + output[i, j] = sin(input[i, j]) + return np.asarray(output) diff --git a/docs/examples/tutorial/parallelization/setup.py b/docs/examples/tutorial/parallelization/setup.py new file mode 100644 index 000000000..eb343e5da --- /dev/null +++ b/docs/examples/tutorial/parallelization/setup.py @@ -0,0 +1,29 @@ +from setuptools import Extension, setup +from Cython.Build import cythonize +import sys + +if sys.platform.startswith("win"): + openmp_arg = '/openmp' +else: + openmp_arg = '-fopenmp' + + +ext_modules = [ + Extension( + "*", + ["*.pyx"], + extra_compile_args=[openmp_arg], + extra_link_args=[openmp_arg], + ), + Extension( + "*", + ["*.pyx"], + extra_compile_args=[openmp_arg], + extra_link_args=[openmp_arg], + ) +] + +setup( + name='parallel-tutorial', + ext_modules=cythonize(ext_modules), +) diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi.py b/docs/examples/tutorial/profiling_tutorial/calc_pi.py index bc265e560..3775eb816 100644 --- a/docs/examples/tutorial/profiling_tutorial/calc_pi.py +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi.py @@ -1,10 +1,8 @@ -# calc_pi.py
-
-def recip_square(i):
- return 1. / i ** 2
-
-def approx_pi(n=10000000):
- val = 0.
- for k in range(1, n + 1):
- val += recip_square(k)
- return (6 * val) ** .5
+def recip_square(i): + return 1. / i ** 2 + +def approx_pi(n=10000000): + val = 0. + for k in range(1, n + 1): + val += recip_square(k) + return (6 * val) ** .5 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_2.py b/docs/examples/tutorial/profiling_tutorial/calc_pi_2.py new file mode 100644 index 000000000..b05eeedb5 --- /dev/null +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_2.py @@ -0,0 +1,12 @@ +# cython: profile=True +import cython + +def recip_square(i: cython.longlong): + return 1. / i ** 2 + +def approx_pi(n: cython.int = 10000000): + val: cython.double = 0. + k: cython.int + for k in range(1, n + 1): + val += recip_square(k) + return (6 * val) ** .5 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_2.pyx b/docs/examples/tutorial/profiling_tutorial/calc_pi_2.pyx index dab8d238d..485bbabf8 100644 --- a/docs/examples/tutorial/profiling_tutorial/calc_pi_2.pyx +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_2.pyx @@ -1,13 +1,11 @@ -# cython: profile=True
-
-# calc_pi.pyx
-
-def recip_square(int i):
- return 1. / i ** 2
-
-def approx_pi(int n=10000000):
- cdef double val = 0.
- cdef int k
- for k in range(1, n + 1):
- val += recip_square(k)
- return (6 * val) ** .5
+# cython: profile=True + +def recip_square(int i): + return 1. / i ** 2 + +def approx_pi(int n=10000000): + cdef double val = 0. + cdef int k + for k in range(1, n + 1): + val += recip_square(k) + return (6 * val) ** .5 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_3.py b/docs/examples/tutorial/profiling_tutorial/calc_pi_3.py new file mode 100644 index 000000000..df3dfa3a1 --- /dev/null +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_3.py @@ -0,0 +1,15 @@ +# cython: profile=True +import cython + +@cython.cfunc +@cython.inline +@cython.exceptval(-1.0) +def recip_square(i: cython.longlong) -> cython.double: + return 1. / (i * i) + +def approx_pi(n: cython.int = 10000000): + val: cython.double = 0. + k: cython.int + for k in range(1, n + 1): + val += recip_square(k) + return (6 * val) ** .5 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_3.pyx b/docs/examples/tutorial/profiling_tutorial/calc_pi_3.pyx index 0f0bdb18a..742991b1a 100644 --- a/docs/examples/tutorial/profiling_tutorial/calc_pi_3.pyx +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_3.pyx @@ -1,13 +1,14 @@ -# cython: profile=True
-
-# calc_pi.pyx
-
-cdef inline double recip_square(int i):
- return 1. / (i * i)
-
-def approx_pi(int n=10000000):
- cdef double val = 0.
- cdef int k
- for k in range(1, n + 1):
- val += recip_square(k)
- return (6 * val) ** .5
+# cython: profile=True + + + + +cdef inline double recip_square(long long i) except -1.0: + return 1. / (i * i) + +def approx_pi(int n=10000000): + cdef double val = 0. + cdef int k + for k in range(1, n + 1): + val += recip_square(k) + return (6 * val) ** .5 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_4.py b/docs/examples/tutorial/profiling_tutorial/calc_pi_4.py new file mode 100644 index 000000000..b457cd99d --- /dev/null +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_4.py @@ -0,0 +1,17 @@ +# cython: profile=True + +import cython + +@cython.profile(False) +@cython.cfunc +@cython.inline +@cython.exceptval(-1.0) +def recip_square(i: cython.longlong) -> float: + return 1. / (i * i) + +def approx_pi(n: cython.int = 10000000): + val: cython.double = 0. + k: cython.int + for k in range(1, n + 1): + val += recip_square(k) + return (6 * val) ** .5 diff --git a/docs/examples/tutorial/profiling_tutorial/calc_pi_4.pyx b/docs/examples/tutorial/profiling_tutorial/calc_pi_4.pyx index ab3f9ea9f..415ac4a22 100644 --- a/docs/examples/tutorial/profiling_tutorial/calc_pi_4.pyx +++ b/docs/examples/tutorial/profiling_tutorial/calc_pi_4.pyx @@ -1,16 +1,17 @@ -# cython: profile=True
-
-# calc_pi.pyx
-
-cimport cython
-
-@cython.profile(False)
-cdef inline double recip_square(int i):
- return 1. / (i * i)
-
-def approx_pi(int n=10000000):
- cdef double val = 0.
- cdef int k
- for k in range(1, n + 1):
- val += recip_square(k)
- return (6 * val) ** .5
+# cython: profile=True + +cimport cython + + + + +@cython.profile(False) +cdef inline double recip_square(long long i) except -1.0: + return 1. / (i * i) + +def approx_pi(int n=10000000): + cdef double val = 0. + cdef int k + for k in range(1, n + 1): + val += recip_square(k) + return (6 * val) ** .5 diff --git a/docs/examples/tutorial/profiling_tutorial/often_called.py b/docs/examples/tutorial/profiling_tutorial/often_called.py new file mode 100644 index 000000000..15197cb97 --- /dev/null +++ b/docs/examples/tutorial/profiling_tutorial/often_called.py @@ -0,0 +1,5 @@ +import cython + +@cython.profile(False) +def my_often_called_function(): + pass diff --git a/docs/examples/tutorial/profiling_tutorial/often_called.pyx b/docs/examples/tutorial/profiling_tutorial/often_called.pyx index 77c689c9c..3699dce4f 100644 --- a/docs/examples/tutorial/profiling_tutorial/often_called.pyx +++ b/docs/examples/tutorial/profiling_tutorial/often_called.pyx @@ -1,5 +1,5 @@ -cimport cython
-
-@cython.profile(False)
-def my_often_called_function():
- pass
+cimport cython + +@cython.profile(False) +def my_often_called_function(): + pass diff --git a/docs/examples/tutorial/profiling_tutorial/profile.py b/docs/examples/tutorial/profiling_tutorial/profile.py index 1c12bf971..c0b76472a 100644 --- a/docs/examples/tutorial/profiling_tutorial/profile.py +++ b/docs/examples/tutorial/profiling_tutorial/profile.py @@ -1,10 +1,8 @@ -# profile.py
-
-import pstats, cProfile
-
-import calc_pi
-
-cProfile.runctx("calc_pi.approx_pi()", globals(), locals(), "Profile.prof")
-
-s = pstats.Stats("Profile.prof")
-s.strip_dirs().sort_stats("time").print_stats()
+import pstats, cProfile + +import calc_pi + +cProfile.runctx("calc_pi.approx_pi()", globals(), locals(), "Profile.prof") + +s = pstats.Stats("Profile.prof") +s.strip_dirs().sort_stats("time").print_stats() diff --git a/docs/examples/tutorial/profiling_tutorial/profile_2.py b/docs/examples/tutorial/profiling_tutorial/profile_2.py index 38fb50104..ca5ca514b 100644 --- a/docs/examples/tutorial/profiling_tutorial/profile_2.py +++ b/docs/examples/tutorial/profiling_tutorial/profile_2.py @@ -1,13 +1,11 @@ -# profile.py
-
-import pstats, cProfile
-
-import pyximport
-pyximport.install()
-
-import calc_pi
-
-cProfile.runctx("calc_pi.approx_pi()", globals(), locals(), "Profile.prof")
-
-s = pstats.Stats("Profile.prof")
-s.strip_dirs().sort_stats("time").print_stats()
+import pstats, cProfile + +import pyximport +pyximport.install() + +import calc_pi + +cProfile.runctx("calc_pi.approx_pi()", globals(), locals(), "Profile.prof") + +s = pstats.Stats("Profile.prof") +s.strip_dirs().sort_stats("time").print_stats() diff --git a/docs/examples/tutorial/pure/A.py b/docs/examples/tutorial/pure/A.py index 1e0cea950..98d5530c8 100644 --- a/docs/examples/tutorial/pure/A.py +++ b/docs/examples/tutorial/pure/A.py @@ -1,14 +1,14 @@ -def myfunction(x, y=2):
- a = x - y
- return a + x * y
-
-def _helper(a):
- return a + 1
-
-class A:
- def __init__(self, b=0):
- self.a = 3
- self.b = b
-
- def foo(self, x):
- print(x + _helper(1.0))
+def myfunction(x, y=2): + a = x - y + return a + x * y + +def _helper(a): + return a + 1 + +class A: + def __init__(self, b=0): + self.a = 3 + self.b = b + + def foo(self, x): + print(x + _helper(1.0)) diff --git a/docs/examples/tutorial/pure/A_equivalent.pyx b/docs/examples/tutorial/pure/A_equivalent.pyx index 1b256a010..ab9e0081c 100644 --- a/docs/examples/tutorial/pure/A_equivalent.pyx +++ b/docs/examples/tutorial/pure/A_equivalent.pyx @@ -1,15 +1,15 @@ -cpdef int myfunction(int x, int y=2):
- a = x - y
- return a + x * y
-
-cdef double _helper(double a):
- return a + 1
-
-cdef class A:
- cdef public int a, b
- def __init__(self, b=0):
- self.a = 3
- self.b = b
-
- cpdef foo(self, double x):
- print(x + _helper(1.0))
+cpdef int myfunction(int x, int y=2): + a = x - y + return a + x * y + +cdef double _helper(double a): + return a + 1 + +cdef class A: + cdef public int a, b + def __init__(self, b=0): + self.a = 3 + self.b = b + + cpdef foo(self, double x): + print(x + _helper(1.0)) diff --git a/docs/examples/tutorial/pure/annotations.py b/docs/examples/tutorial/pure/annotations.py index 2b8487c0b..09682c352 100644 --- a/docs/examples/tutorial/pure/annotations.py +++ b/docs/examples/tutorial/pure/annotations.py @@ -1,5 +1,5 @@ -import cython
-
-def func(foo: dict, bar: cython.int) -> tuple:
- foo["hello world"] = 3 + bar
- return foo, 5
+import cython + +def func(foo: dict, bar: cython.int) -> tuple: + foo["hello world"] = 3 + bar + return foo, 5 diff --git a/docs/examples/tutorial/pure/c_arrays.py b/docs/examples/tutorial/pure/c_arrays.py index 33067da68..f221b7ae8 100644 --- a/docs/examples/tutorial/pure/c_arrays.py +++ b/docs/examples/tutorial/pure/c_arrays.py @@ -1,15 +1,15 @@ -import cython
-
-
-@cython.locals(counts=cython.int[10], digit=cython.int)
-def count_digits(digits):
- """
- >>> digits = '01112222333334445667788899'
- >>> count_digits(map(int, digits))
- [1, 3, 4, 5, 3, 1, 2, 2, 3, 2]
- """
- counts = [0] * 10
- for digit in digits:
- assert 0 <= digit <= 9
- counts[digit] += 1
- return counts
+import cython + + +@cython.locals(counts=cython.int[10], digit=cython.int) +def count_digits(digits): + """ + >>> digits = '01112222333334445667788899' + >>> count_digits(map(int, digits)) + [1, 3, 4, 5, 3, 1, 2, 2, 3, 2] + """ + counts = [0] * 10 + for digit in digits: + assert 0 <= digit <= 9 + counts[digit] += 1 + return counts diff --git a/docs/examples/tutorial/pure/cclass.py b/docs/examples/tutorial/pure/cclass.py index 61c65183d..7f9cb1a04 100644 --- a/docs/examples/tutorial/pure/cclass.py +++ b/docs/examples/tutorial/pure/cclass.py @@ -1,16 +1,16 @@ -import cython
-
-
-@cython.cclass
-class A:
- cython.declare(a=cython.int, b=cython.int)
- c = cython.declare(cython.int, visibility='public')
- d = cython.declare(cython.int) # private by default.
- e = cython.declare(cython.int, visibility='readonly')
-
- def __init__(self, a, b, c, d=5, e=3):
- self.a = a
- self.b = b
- self.c = c
- self.d = d
- self.e = e
+import cython + + +@cython.cclass +class A: + cython.declare(a=cython.int, b=cython.int) + c = cython.declare(cython.int, visibility='public') + d = cython.declare(cython.int) # private by default. + e = cython.declare(cython.int, visibility='readonly') + + def __init__(self, a, b, c, d=5, e=3): + self.a = a + self.b = b + self.c = c + self.d = d + self.e = e diff --git a/docs/examples/tutorial/pure/compiled_switch.py b/docs/examples/tutorial/pure/compiled_switch.py index 47d62a3e6..a35cac2c6 100644 --- a/docs/examples/tutorial/pure/compiled_switch.py +++ b/docs/examples/tutorial/pure/compiled_switch.py @@ -1,6 +1,6 @@ -import cython
-
-if cython.compiled:
- print("Yep, I'm compiled.")
-else:
- print("Just a lowly interpreted script.")
+import cython + +if cython.compiled: + print("Yep, I'm compiled.") +else: + print("Just a lowly interpreted script.") diff --git a/docs/examples/tutorial/pure/cython_declare.py b/docs/examples/tutorial/pure/cython_declare.py index cf6d58bba..50a4ab8aa 100644 --- a/docs/examples/tutorial/pure/cython_declare.py +++ b/docs/examples/tutorial/pure/cython_declare.py @@ -1,4 +1,4 @@ -import cython
-
-x = cython.declare(cython.int) # cdef int x
-y = cython.declare(cython.double, 0.57721) # cdef double y = 0.57721
+import cython + +x = cython.declare(cython.int) # cdef int x +y = cython.declare(cython.double, 0.57721) # cdef double y = 0.57721 diff --git a/docs/examples/tutorial/pure/cython_declare2.py b/docs/examples/tutorial/pure/cython_declare2.py index 35fae7d7b..ee491d62b 100644 --- a/docs/examples/tutorial/pure/cython_declare2.py +++ b/docs/examples/tutorial/pure/cython_declare2.py @@ -1,3 +1,3 @@ -import cython
-
-cython.declare(x=cython.int, y=cython.double) # cdef int x; cdef double y
+import cython + +cython.declare(x=cython.int, y=cython.double) # cdef int x; cdef double y diff --git a/docs/examples/tutorial/pure/disabled_annotations.py b/docs/examples/tutorial/pure/disabled_annotations.py new file mode 100644 index 000000000..c92b4cf8e --- /dev/null +++ b/docs/examples/tutorial/pure/disabled_annotations.py @@ -0,0 +1,33 @@ +import cython + +@cython.annotation_typing(False) +def function_without_typing(a: int, b: int) -> int: + """Cython is ignoring annotations in this function""" + c: int = a + b + return c * a + + +@cython.annotation_typing(False) +@cython.cclass +class NotAnnotatedClass: + """Cython is ignoring annotatons in this class except annotated_method""" + d: dict + + def __init__(self, dictionary: dict): + self.d = dictionary + + @cython.annotation_typing(True) + def annotated_method(self, key: str, a: cython.int, b: cython.int): + prefixed_key: str = 'prefix_' + key + self.d[prefixed_key] = a + b + + +def annotated_function(a: cython.int, b: cython.int): + s: cython.int = a + b + with cython.annotation_typing(False): + # Cython is ignoring annotations within this code block + c: list = [] + c.append(a) + c.append(b) + c.append(s) + return c diff --git a/docs/examples/tutorial/pure/dostuff.py b/docs/examples/tutorial/pure/dostuff.py index 748c31b10..7a88533c5 100644 --- a/docs/examples/tutorial/pure/dostuff.py +++ b/docs/examples/tutorial/pure/dostuff.py @@ -1,5 +1,5 @@ -def dostuff(n):
- t = 0
- for i in range(n):
- t += i
- return t
+def dostuff(n): + t = 0 + for i in range(n): + t += i + return t diff --git a/docs/examples/tutorial/pure/exceptval.py b/docs/examples/tutorial/pure/exceptval.py index 8bf564040..3d991f7c1 100644 --- a/docs/examples/tutorial/pure/exceptval.py +++ b/docs/examples/tutorial/pure/exceptval.py @@ -1,7 +1,7 @@ -import cython
-
-@cython.exceptval(-1)
-def func(x: cython.int) -> cython.int:
- if x < 0:
- raise ValueError("need integer >= 0")
- return x + 1
+import cython + +@cython.exceptval(-1) +def func(x: cython.int) -> cython.int: + if x < 0: + raise ValueError("need integer >= 0") + return x + 1 diff --git a/docs/examples/tutorial/pure/locals.py b/docs/examples/tutorial/pure/locals.py index 8eda7114a..b273a9ebe 100644 --- a/docs/examples/tutorial/pure/locals.py +++ b/docs/examples/tutorial/pure/locals.py @@ -1,6 +1,6 @@ -import cython
-
-@cython.locals(a=cython.long, b=cython.long, n=cython.longlong)
-def foo(a, b, x, y):
- n = a * b
- # ...
+import cython + +@cython.locals(a=cython.long, b=cython.long, n=cython.longlong) +def foo(a, b, x, y): + n = a * b + # ... diff --git a/docs/examples/tutorial/pure/mymodule.py b/docs/examples/tutorial/pure/mymodule.py index 62d4c76ac..83f5cdc28 100644 --- a/docs/examples/tutorial/pure/mymodule.py +++ b/docs/examples/tutorial/pure/mymodule.py @@ -1,10 +1,10 @@ -# mymodule.py
-
-import cython
-
-# override with Python import if not in compiled code
-if not cython.compiled:
- from math import sin
-
-# calls sin() from math.h when compiled with Cython and math.sin() in Python
-print(sin(0))
+# mymodule.py + +import cython + +# override with Python import if not in compiled code +if not cython.compiled: + from math import sin + +# calls sin() from math.h when compiled with Cython and math.sin() in Python +print(sin(0)) diff --git a/docs/examples/tutorial/pure/pep_526.py b/docs/examples/tutorial/pure/pep_526.py index 163d97859..ecb3bfcdf 100644 --- a/docs/examples/tutorial/pure/pep_526.py +++ b/docs/examples/tutorial/pure/pep_526.py @@ -1,22 +1,22 @@ -import cython
-
-def func():
- # Cython types are evaluated as for cdef declarations
- x: cython.int # cdef int x
- y: cython.double = 0.57721 # cdef double y = 0.57721
- z: cython.float = 0.57721 # cdef float z = 0.57721
-
- # Python types shadow Cython types for compatibility reasons
- a: float = 0.54321 # cdef double a = 0.54321
- b: int = 5 # cdef object b = 5
- c: long = 6 # cdef object c = 6
- pass
-
-@cython.cclass
-class A:
- a: cython.int
- b: cython.int
-
- def __init__(self, b=0):
- self.a = 3
- self.b = b
+import cython + +def func(): + # Cython types are evaluated as for cdef declarations + x: cython.int # cdef int x + y: cython.double = 0.57721 # cdef double y = 0.57721 + z: cython.float = 0.57721 # cdef float z = 0.57721 + + # Python types shadow Cython types for compatibility reasons + a: float = 0.54321 # cdef double a = 0.54321 + b: int = 5 # cdef object b = 5 + c: long = 6 # cdef object c = 6 + pass + +@cython.cclass +class A: + a: cython.int + b: cython.int + + def __init__(self, b=0): + self.a = 3 + self.b = b diff --git a/docs/examples/tutorial/pure/py_cimport.py b/docs/examples/tutorial/pure/py_cimport.py new file mode 100644 index 000000000..233ddde7e --- /dev/null +++ b/docs/examples/tutorial/pure/py_cimport.py @@ -0,0 +1,5 @@ + +from cython.cimports.libc import math + +def use_libc_math(): + return math.ceil(5.5) diff --git a/docs/examples/tutorial/string/api_func.pyx b/docs/examples/tutorial/string/api_func.pyx index ec6b27751..c9e05f9e3 100644 --- a/docs/examples/tutorial/string/api_func.pyx +++ b/docs/examples/tutorial/string/api_func.pyx @@ -1,5 +1,5 @@ -from to_unicode cimport _text
-
-def api_func(s):
- text_input = _text(s)
- # ...
+from to_unicode cimport _text + +def api_func(s): + text_input = _text(s) + # ... diff --git a/docs/examples/tutorial/string/arg_memview.pyx b/docs/examples/tutorial/string/arg_memview.pyx index 63a18f943..e2b6d75be 100644 --- a/docs/examples/tutorial/string/arg_memview.pyx +++ b/docs/examples/tutorial/string/arg_memview.pyx @@ -1,5 +1,5 @@ -def process_byte_data(unsigned char[:] data):
- length = data.shape[0]
- first_byte = data[0]
- slice_view = data[1:-1]
- # ...
+def process_byte_data(unsigned char[:] data): + length = data.shape[0] + first_byte = data[0] + slice_view = data[1:-1] + # ... diff --git a/docs/examples/tutorial/string/auto_conversion_1.pyx b/docs/examples/tutorial/string/auto_conversion_1.pyx index 929c03d68..ee2b116e4 100644 --- a/docs/examples/tutorial/string/auto_conversion_1.pyx +++ b/docs/examples/tutorial/string/auto_conversion_1.pyx @@ -1,9 +1,9 @@ -# cython: c_string_type=unicode, c_string_encoding=utf8
-
-cdef char* c_string = 'abcdefg'
-
-# implicit decoding:
-cdef object py_unicode_object = c_string
-
-# explicit conversion to Python bytes:
-py_bytes_object = <bytes>c_string
+# cython: c_string_type=unicode, c_string_encoding=utf8 + +cdef char* c_string = 'abcdefg' + +# implicit decoding: +cdef object py_unicode_object = c_string + +# explicit conversion to Python bytes: +py_bytes_object = <bytes>c_string diff --git a/docs/examples/tutorial/string/auto_conversion_2.pyx b/docs/examples/tutorial/string/auto_conversion_2.pyx index 84436661d..9f7a5ad04 100644 --- a/docs/examples/tutorial/string/auto_conversion_2.pyx +++ b/docs/examples/tutorial/string/auto_conversion_2.pyx @@ -1,12 +1,12 @@ -# cython: c_string_type=str, c_string_encoding=ascii
-
-cdef char* c_string = 'abcdefg'
-
-# implicit decoding in Py3, bytes conversion in Py2:
-cdef object py_str_object = c_string
-
-# explicit conversion to Python bytes:
-py_bytes_object = <bytes>c_string
-
-# explicit conversion to Python unicode:
-py_bytes_object = <unicode>c_string
+# cython: c_string_type=str, c_string_encoding=ascii + +cdef char* c_string = 'abcdefg' + +# implicit decoding in Py3, bytes conversion in Py2: +cdef object py_str_object = c_string + +# explicit conversion to Python bytes: +py_bytes_object = <bytes>c_string + +# explicit conversion to Python unicode: +py_bytes_object = <unicode>c_string diff --git a/docs/examples/tutorial/string/auto_conversion_3.pyx b/docs/examples/tutorial/string/auto_conversion_3.pyx index 509d7e324..b9a1b7517 100644 --- a/docs/examples/tutorial/string/auto_conversion_3.pyx +++ b/docs/examples/tutorial/string/auto_conversion_3.pyx @@ -1,6 +1,6 @@ -# cython: c_string_type=unicode, c_string_encoding=ascii
-
-def func():
- ustring = u'abc'
- cdef char* s = ustring
- return s[0] # returns u'a'
+# cython: c_string_type=unicode, c_string_encoding=ascii + +def func(): + ustring = u'abc' + cdef char* s = ustring + return s[0] # returns u'a' diff --git a/docs/examples/tutorial/string/c_func.pyx b/docs/examples/tutorial/string/c_func.pyx index a456b815b..4763f2671 100644 --- a/docs/examples/tutorial/string/c_func.pyx +++ b/docs/examples/tutorial/string/c_func.pyx @@ -1,22 +1,23 @@ -from libc.stdlib cimport malloc
-from libc.string cimport strcpy, strlen
-
-cdef char* hello_world = 'hello world'
-cdef Py_ssize_t n = strlen(hello_world)
-
-
-cdef char* c_call_returning_a_c_string():
- cdef char* c_string = <char *> malloc((n + 1) * sizeof(char))
- if not c_string:
- raise MemoryError()
- strcpy(c_string, hello_world)
- return c_string
-
-
-cdef void get_a_c_string(char** c_string_ptr, Py_ssize_t *length):
- c_string_ptr[0] = <char *> malloc((n + 1) * sizeof(char))
- if not c_string_ptr[0]:
- raise MemoryError()
-
- strcpy(c_string_ptr[0], hello_world)
- length[0] = n
+from libc.stdlib cimport malloc +from libc.string cimport strcpy, strlen + +cdef char* hello_world = 'hello world' +cdef Py_ssize_t n = strlen(hello_world) + + +cdef char* c_call_returning_a_c_string(): + cdef char* c_string = <char *> malloc((n + 1) * sizeof(char)) + if not c_string: + return NULL # malloc failed + + strcpy(c_string, hello_world) + return c_string + + +cdef void get_a_c_string(char** c_string_ptr, Py_ssize_t *length): + c_string_ptr[0] = <char *> malloc((n + 1) * sizeof(char)) + if not c_string_ptr[0]: + return # malloc failed + + strcpy(c_string_ptr[0], hello_world) + length[0] = n diff --git a/docs/examples/tutorial/string/const.pyx b/docs/examples/tutorial/string/const.pyx index e066c77ac..0b89b9e41 100644 --- a/docs/examples/tutorial/string/const.pyx +++ b/docs/examples/tutorial/string/const.pyx @@ -1,4 +1,4 @@ -cdef extern from "someheader.h":
- ctypedef const char specialChar
- int process_string(const char* s)
- const unsigned char* look_up_cached_string(const unsigned char* key)
+cdef extern from "someheader.h": + ctypedef const char specialChar + int process_string(const char* s) + const unsigned char* look_up_cached_string(const unsigned char* key) diff --git a/docs/examples/tutorial/string/cpp_string.pyx b/docs/examples/tutorial/string/cpp_string.pyx index b6c9e44f9..313e72a67 100644 --- a/docs/examples/tutorial/string/cpp_string.pyx +++ b/docs/examples/tutorial/string/cpp_string.pyx @@ -1,12 +1,12 @@ -# distutils: language = c++
-
-from libcpp.string cimport string
-
-def get_bytes():
- py_bytes_object = b'hello world'
- cdef string s = py_bytes_object
-
- s.append('abc')
- py_bytes_object = s
- return py_bytes_object
-
+# distutils: language = c++ + +from libcpp.string cimport string + +def get_bytes(): + py_bytes_object = b'hello world' + cdef string s = py_bytes_object + + s.append('abc') + py_bytes_object = s + return py_bytes_object + diff --git a/docs/examples/tutorial/string/decode.pyx b/docs/examples/tutorial/string/decode.pyx index c3e2faf68..79fc41835 100644 --- a/docs/examples/tutorial/string/decode.pyx +++ b/docs/examples/tutorial/string/decode.pyx @@ -1,9 +1,9 @@ -from c_func cimport get_a_c_string
-
-cdef char* c_string = NULL
-cdef Py_ssize_t length = 0
-
-# get pointer and length from a C function
-get_a_c_string(&c_string, &length)
-
-ustring = c_string[:length].decode('UTF-8')
+from c_func cimport get_a_c_string + +cdef char* c_string = NULL +cdef Py_ssize_t length = 0 + +# get pointer and length from a C function +get_a_c_string(&c_string, &length) + +ustring = c_string[:length].decode('UTF-8') diff --git a/docs/examples/tutorial/string/decode_cpp_string.pyx b/docs/examples/tutorial/string/decode_cpp_string.pyx index 8f1d01af8..52861c209 100644 --- a/docs/examples/tutorial/string/decode_cpp_string.pyx +++ b/docs/examples/tutorial/string/decode_cpp_string.pyx @@ -1,10 +1,10 @@ -# distutils: language = c++
-
-from libcpp.string cimport string
-
-def get_ustrings():
- cdef string s = string(b'abcdefg')
-
- ustring1 = s.decode('UTF-8')
- ustring2 = s[2:-2].decode('UTF-8')
- return ustring1, ustring2
+# distutils: language = c++ + +from libcpp.string cimport string + +def get_ustrings(): + cdef string s = string(b'abcdefg') + + ustring1 = s.decode('UTF-8') + ustring2 = s[2:-2].decode('UTF-8') + return ustring1, ustring2 diff --git a/docs/examples/tutorial/string/for_bytes.pyx b/docs/examples/tutorial/string/for_bytes.pyx index 69e9202ae..d4d3e1f81 100644 --- a/docs/examples/tutorial/string/for_bytes.pyx +++ b/docs/examples/tutorial/string/for_bytes.pyx @@ -1,6 +1,6 @@ -cdef bytes bytes_string = b"hello to A bytes' world"
-
-cdef char c
-for c in bytes_string:
- if c == 'A':
- print("Found the letter A")
+cdef bytes bytes_string = b"hello to A bytes' world" + +cdef char c +for c in bytes_string: + if c == 'A': + print("Found the letter A") diff --git a/docs/examples/tutorial/string/for_char.pyx b/docs/examples/tutorial/string/for_char.pyx index adc16bcd8..81abae97c 100644 --- a/docs/examples/tutorial/string/for_char.pyx +++ b/docs/examples/tutorial/string/for_char.pyx @@ -1,6 +1,6 @@ -cdef char* c_string = "Hello to A C-string's world"
-
-cdef char c
-for c in c_string[:11]:
- if c == 'A':
- print("Found the letter A")
+cdef char* c_string = "Hello to A C-string's world" + +cdef char c +for c in c_string[:11]: + if c == 'A': + print("Found the letter A") diff --git a/docs/examples/tutorial/string/for_unicode.pyx b/docs/examples/tutorial/string/for_unicode.pyx index aabd562e4..0f8ab0c7d 100644 --- a/docs/examples/tutorial/string/for_unicode.pyx +++ b/docs/examples/tutorial/string/for_unicode.pyx @@ -1,6 +1,6 @@ -cdef unicode ustring = u'Hello world'
-
-# NOTE: no typing required for 'uchar' !
-for uchar in ustring:
- if uchar == u'A':
- print("Found the letter A")
+cdef unicode ustring = u'Hello world' + +# NOTE: no typing required for 'uchar' ! +for uchar in ustring: + if uchar == u'A': + print("Found the letter A") diff --git a/docs/examples/tutorial/string/if_char_in.pyx b/docs/examples/tutorial/string/if_char_in.pyx index 73521b2de..e33e18d59 100644 --- a/docs/examples/tutorial/string/if_char_in.pyx +++ b/docs/examples/tutorial/string/if_char_in.pyx @@ -1,5 +1,5 @@ -cpdef void is_in(Py_UCS4 uchar_val):
- if uchar_val in u'abcABCxY':
- print("The character is in the string.")
- else:
- print("The character is not in the string")
+cpdef void is_in(Py_UCS4 uchar_val): + if uchar_val in u'abcABCxY': + print("The character is in the string.") + else: + print("The character is not in the string") diff --git a/docs/examples/tutorial/string/naive_decode.pyx b/docs/examples/tutorial/string/naive_decode.pyx index 186d2affa..b3c44d9af 100644 --- a/docs/examples/tutorial/string/naive_decode.pyx +++ b/docs/examples/tutorial/string/naive_decode.pyx @@ -1,4 +1,4 @@ -from c_func cimport c_call_returning_a_c_string
-
-cdef char* some_c_string = c_call_returning_a_c_string()
-ustring = some_c_string.decode('UTF-8')
+from c_func cimport c_call_returning_a_c_string + +cdef char* some_c_string = c_call_returning_a_c_string() +ustring = some_c_string.decode('UTF-8') diff --git a/docs/examples/tutorial/string/return_memview.pyx b/docs/examples/tutorial/string/return_memview.pyx index f6233436a..be9b597a4 100644 --- a/docs/examples/tutorial/string/return_memview.pyx +++ b/docs/examples/tutorial/string/return_memview.pyx @@ -1,9 +1,9 @@ -def process_byte_data(unsigned char[:] data):
- # ... process the data, here, dummy processing.
- cdef bint return_all = (data[0] == 108)
-
- if return_all:
- return bytes(data)
- else:
- # example for returning a slice
- return bytes(data[5:7])
+def process_byte_data(unsigned char[:] data): + # ... process the data, here, dummy processing. + cdef bint return_all = (data[0] == 108) + + if return_all: + return bytes(data) + else: + # example for returning a slice + return bytes(data[5:7]) diff --git a/docs/examples/tutorial/string/slicing_c_string.pyx b/docs/examples/tutorial/string/slicing_c_string.pyx index 2e937430e..f8d272e32 100644 --- a/docs/examples/tutorial/string/slicing_c_string.pyx +++ b/docs/examples/tutorial/string/slicing_c_string.pyx @@ -1,15 +1,15 @@ -from libc.stdlib cimport free
-from c_func cimport get_a_c_string
-
-
-def main():
- cdef char* c_string = NULL
- cdef Py_ssize_t length = 0
-
- # get pointer and length from a C function
- get_a_c_string(&c_string, &length)
-
- try:
- py_bytes_string = c_string[:length] # Performs a copy of the data
- finally:
- free(c_string)
+from libc.stdlib cimport free +from c_func cimport get_a_c_string + + +def main(): + cdef char* c_string = NULL + cdef Py_ssize_t length = 0 + + # get pointer and length from a C function + get_a_c_string(&c_string, &length) + + try: + py_bytes_string = c_string[:length] # Performs a copy of the data + finally: + free(c_string) diff --git a/docs/examples/tutorial/string/to_char.pyx b/docs/examples/tutorial/string/to_char.pyx index 5e4a16161..7912ea485 100644 --- a/docs/examples/tutorial/string/to_char.pyx +++ b/docs/examples/tutorial/string/to_char.pyx @@ -1,8 +1,8 @@ -# define a global name for whatever char type is used in the module
-ctypedef unsigned char char_type
-
-cdef char_type[:] _chars(s):
- if isinstance(s, unicode):
- # encode to the specific encoding used inside of the module
- s = (<unicode>s).encode('utf8')
- return s
+# define a global name for whatever char type is used in the module +ctypedef unsigned char char_type + +cdef char_type[:] _chars(s): + if isinstance(s, unicode): + # encode to the specific encoding used inside of the module + s = (<unicode>s).encode('utf8') + return s diff --git a/docs/examples/tutorial/string/to_unicode.pyx b/docs/examples/tutorial/string/to_unicode.pyx index 8ab8f2662..188a8776e 100644 --- a/docs/examples/tutorial/string/to_unicode.pyx +++ b/docs/examples/tutorial/string/to_unicode.pyx @@ -1,22 +1,22 @@ -# to_unicode.pyx
-
-from cpython.version cimport PY_MAJOR_VERSION
-
-cdef unicode _text(s):
- if type(s) is unicode:
- # Fast path for most common case(s).
- return <unicode>s
-
- elif PY_MAJOR_VERSION < 3 and isinstance(s, bytes):
- # Only accept byte strings as text input in Python 2.x, not in Py3.
- return (<bytes>s).decode('ascii')
-
- elif isinstance(s, unicode):
- # We know from the fast path above that 's' can only be a subtype here.
- # An evil cast to <unicode> might still work in some(!) cases,
- # depending on what the further processing does. To be safe,
- # we can always create a copy instead.
- return unicode(s)
-
- else:
- raise TypeError("Could not convert to unicode.")
+# to_unicode.pyx + +from cpython.version cimport PY_MAJOR_VERSION + +cdef unicode _text(s): + if type(s) is unicode: + # Fast path for most common case(s). + return <unicode>s + + elif PY_MAJOR_VERSION < 3 and isinstance(s, bytes): + # Only accept byte strings as text input in Python 2.x, not in Py3. + return (<bytes>s).decode('ascii') + + elif isinstance(s, unicode): + # We know from the fast path above that 's' can only be a subtype here. + # An evil cast to <unicode> might still work in some(!) cases, + # depending on what the further processing does. To be safe, + # we can always create a copy instead. + return unicode(s) + + else: + raise TypeError("Could not convert to unicode.") diff --git a/docs/examples/tutorial/string/try_finally.pyx b/docs/examples/tutorial/string/try_finally.pyx index aea786f5b..4cf943e56 100644 --- a/docs/examples/tutorial/string/try_finally.pyx +++ b/docs/examples/tutorial/string/try_finally.pyx @@ -1,9 +1,9 @@ -from libc.stdlib cimport free
-from c_func cimport c_call_returning_a_c_string
-
-cdef bytes py_string
-cdef char* c_string = c_call_returning_a_c_string()
-try:
- py_string = c_string
-finally:
- free(c_string)
+from libc.stdlib cimport free +from c_func cimport c_call_returning_a_c_string + +cdef bytes py_string +cdef char* c_string = c_call_returning_a_c_string() +try: + py_string = c_string +finally: + free(c_string) diff --git a/docs/examples/tutorial/string/utf_eight.pyx b/docs/examples/tutorial/string/utf_eight.pyx index 7113947f4..654c51ae8 100644 --- a/docs/examples/tutorial/string/utf_eight.pyx +++ b/docs/examples/tutorial/string/utf_eight.pyx @@ -1,15 +1,15 @@ -from libc.stdlib cimport free
-
-cdef unicode tounicode(char* s):
- return s.decode('UTF-8', 'strict')
-
-cdef unicode tounicode_with_length(
- char* s, size_t length):
- return s[:length].decode('UTF-8', 'strict')
-
-cdef unicode tounicode_with_length_and_free(
- char* s, size_t length):
- try:
- return s[:length].decode('UTF-8', 'strict')
- finally:
+from libc.stdlib cimport free + +cdef unicode tounicode(char* s): + return s.decode('UTF-8', 'strict') + +cdef unicode tounicode_with_length( + char* s, size_t length): + return s[:length].decode('UTF-8', 'strict') + +cdef unicode tounicode_with_length_and_free( + char* s, size_t length): + try: + return s[:length].decode('UTF-8', 'strict') + finally: free(s)
\ No newline at end of file |