[Numpy-discussion] A little about XND (original) (raw)

Stefan Krah skrah at bytereef.org
Mon Jun 18 10:02:18 EDT 2018


On Sun, Jun 17, 2018 at 08:47:02PM -0400, Marten van Kerkwijk wrote:

More of a detailed question, but as we are currently thinking about extending the signature of gufuncs (i.e., things like (m,n),(n,p)->(m,p) for matrix multiplication), and as you must have thought about this for libgufunc, could you point me to how one would document the signature in your new system? (I briefly tried but there's no docs yet and I couldn't immediately find it in the code).

The docs are a bit scattered across the three libraries, here is something about types and pattern matching:

http://ndtypes.readthedocs.io/en/latest/ndtypes/types.html http://ndtypes.readthedocs.io/en/latest/ndtypes/pattern-matching.html

A couple of example signatures:

https://github.com/plures/gumath/blob/5f1f6de3d2c9a003b9dfb224fe09c63ae81bf18b/libgumath/extending/quaternion.c#L121 https://github.com/plures/gumath/blob/5f1f6de3d2c9a003b9dfb224fe09c63ae81bf18b/libgumath/extending/pdist.c#L115

The function signature for float64-specialized matrix multiplication is:

"... * N * M * float64, ... * M * P * float64 -> ... * N * P * float64"

The function signature for generic matrix multiplication is:

"... * N * M * T, ... * M * P * T -> ... * N * P * T"

A function that only accepts scalars:

"... * N * M * Scalar, ... * M * P * Scalar -> ... * N * P * Scalar"

A couple of observations: Functions are multimethods, so function dispatch on concrete arguments works by trying to locate a matching kernel.

For example, if only the above "float64" kernel is present, all other dtypes will fail.

Casting

It is still under debate how we handle casting. The current examples libgumath/kernels simply generate all signatures that allow exact casting of the input for a specific function.

This is feasible for unary and binary kernels, but could lead to case explosion for functions with many arguments.

The kernel writer however is always free to use the above type variable or Scalar signatures and handle casting inside the kernel.

Explicit gufuncs

Gufuncs are explicit and require leading ellipses. A signature of "N * M * float64" is not a gufunc and does not allow outer dimensions.

Disable broadcasting

"D... * N * M * float64, D... * M * P * float64 -> D... * N * P * float64"

Dimension variables match a sequence of dimensions, so in the above example all outer dimensions must be exactly the same.

Non-symbolic matches

"... * 2 * 3 * int8" only accepts "2 * 3 * int8" as the inner dimensions.

Sorry for the long mail, I hope this clears up a bit what function signatures generally look like.

Stefan Krah



More information about the NumPy-Discussion mailing list