easy_cython#

Easy: memoryview sum#

Typed memoryview summation loop.

# cython: language_level=3
# cython: boundscheck=False
# cython: wraparound=False
"""Easy Cython template: typed memoryview loop."""

# import cython


def sum_doubles(double[:] x):
    """Sum a 1D array-like of doubles."""
    cdef Py_ssize_t i, n = x.shape[0]
    cdef double s = 0.0
    for i in range(n):
        s += x[i]
    return s

Sum memoryview (Cython)#

Typed memoryview loop.

# cython: language_level=3

"""Easy Cython template: sum a 1D double memoryview."""

import cython


@cython.boundscheck(False)
@cython.wraparound(False)
def sum1d(double[:] x):
    cdef Py_ssize_t i
    cdef double s = 0.0
    for i in range(x.shape[0]):
        s += x[i]
    return s

Sum 1D memoryview#

Summation over a typed memoryview; works with any buffer provider.

# cython: language_level=3
"""Easy Cython template: summing a 1D typed memoryview."""

from libc.stdint cimport int64_t


def sum_int64(long[:] x):
    """Sum a 1D buffer of integers.

    Notes
    -----
    Accepts objects exporting the buffer protocol (e.g., array('l'), NumPy arrays).
    """
    cdef Py_ssize_t i, n = x.shape[0]
    cdef int64_t s = 0
    for i in range(n):
        s += <int64_t>x[i]
    return s

Dot product on Python sequences#

# cython: language_level=3
"""
Vector dot product on Python lists (no NumPy).

User notes
----------
- Accepts Python sequences (lists/tuples) of numbers.
- Converts elements to `double` inside a typed loop.

Developer notes
--------------
- This is a pedagogical template: speed depends on input types.
- For best performance, see memoryview-based templates.
"""

cpdef double dot_list(object x, object y):
    """
    Compute dot(x, y) for two equally-sized sequences.

    Parameters
    ----------
    x, y : sequence
        Input sequences of numbers.

    Returns
    -------
    double
        Dot product.

    Raises
    ------
    ValueError
        If lengths differ.
    """
    cdef Py_ssize_t n = len(x)
    if len(y) != n:
        raise ValueError("x and y must have the same length")
    cdef Py_ssize_t i
    cdef double acc = 0.0
    for i in range(n):
        acc += <double>x[i] * <double>y[i]
    return acc

Scale vector with double[:] memoryview#

# cython: language_level=3
"""
Scale a vector in-place using a typed memoryview (no NumPy required).

User notes
----------
- Works with any object exposing a writable buffer of doubles, e.g.:
  `array('d')`, `memoryview(array('d'))`, some other buffer providers.
- This does *not* rely on NumPy C-API.

Examples
--------
>>> from array import array
>>> import scikitplot.cython as cy
>>> m = cy.compile_template("easy_cython/t05_vector_scale_memview")
>>> a = array('d', [1.0, 2.0, 3.0])
>>> m.scale(a, 10.0)
>>> list(a)
[10.0, 20.0, 30.0]
"""

cpdef void scale(double[:] x, double alpha):
    """Scale x[i] *= alpha in-place."""
    cdef Py_ssize_t i, n = x.shape[0]
    for i in range(n):
        x[i] = x[i] * alpha

L2 norm with memoryview#

# cython: language_level=3
"""
Compute L2 norm using a typed memoryview (no NumPy required).
"""

from libc.math cimport sqrt

cpdef double norm2(double[:] x):
    """Return sqrt(sum(x[i]^2))."""
    cdef Py_ssize_t i, n = x.shape[0]
    cdef double acc = 0.0
    for i in range(n):
        acc += x[i] * x[i]
    return sqrt(acc)

Vector add on sequences (returns list)#

# cython: language_level=3
"""
Add two numeric sequences and return a Python list.

Notes
-----
This is a learning template that demonstrates:
- typed loop counters (`Py_ssize_t`)
- explicit conversion to `double` for numeric stability.
"""

cpdef list add_list(object x, object y):
    cdef Py_ssize_t n = len(x)
    if len(y) != n:
        raise ValueError("length mismatch")
    cdef list out = [0.0] * n
    cdef Py_ssize_t i
    for i in range(n):
        out[i] = <double>x[i] + <double>y[i]
    return out

Parse unsigned int from ASCII bytes#

# cython: language_level=3
"""
Parse a non-negative integer from ASCII bytes.

User notes
----------
- Useful micro-template for fast parsing in tight loops.
- Accepts `bytes` containing only digits (and optionally leading/trailing spaces).

Raises
------
ValueError on invalid input.
"""

cpdef int parse_uint(bytes s):
    cdef Py_ssize_t i = 0
    cdef Py_ssize_t n = len(s)
    # skip leading spaces
    while i < n and s[i] in (32, 9, 10, 13):
        i += 1
    if i == n:
        raise ValueError("empty")
    cdef int acc = 0
    cdef int d
    while i < n and 48 <= s[i] <= 57:
        d = s[i] - 48
        acc = acc * 10 + d
        i += 1
    # skip trailing spaces
    while i < n and s[i] in (32, 9, 10, 13):
        i += 1
    if i != n:
        raise ValueError("invalid character")
    return acc