uncomplicate.neanderthal.core

Contains type-agnostic linear algebraic functions roughly corresponding to functionality defined in BLAS 123, and functions that create and work with various kinds of vectors and matrices. Typically, you would want to require this namespace regardless of the actual type (real, complex, CPU, GPU, pure Java etc.) of the vectors and matrices that you use.

In cases when you need to repeatedly call a function from this namespace that accesses individual entries, and the entries are primitive, it is better to use a primitive version of the function from uncomplicate.neanderthal.real or uncomplicate.neanderthal.integer namespaces. Constructor functions for different specialized types (native, GPU, pure java) are in respective specialized namespaces (uncomplicate.neanderthal.native, uncomplicate.neanderthal.cuda, etc).

Please take care to only use vectors and matrices of the same type in one call of a linear algebra operation. Compute operations typically (and on purpose!) do not support arguments of mixed types. For example, you can not call the dot function with one double vector (dv) and one float vector (fv), or with one vector in the CPU memory and one in the GPU memory. If you’d try, an ex-info would be thrown. You can use those different types side-by-side and transfer the data between them though.

How to use

(ns test
  (:require [uncomplicate.neanderthal core native]))

(ns test
  (:require [uncomplicate.neanderthal core native cuda]))

Examples

The best and most accurate examples can be found in the comprehensive test suite: see real-test, block-test, mkl-test, cublas-test, and opencl-test. Also, there are tutorial test examples here, the tutorials at the Neanderthal web site, and on my blog dragan.rocks.

For the comprehensive real-world examples, with detailed tutorials and guides, see the Interactive Programming for Artificial intelligence book series.

Cheat Sheet

Most Neanderthal function names are short, and cryptic at the first sight. But there is a very good reason for that! Please see Naming conventions for BLAS routines. The Linear Algebra for Programmers is also a good tutorial-oriented resource that can be very helpful for understanding all that madness.

alter!

(alter! x f)(alter! x i f)(alter! a i j f)

Alters the i-th entry of vector x, or (i, j)-th entry of matrix a by evaluating function f on one or all of its elements.

If no index is passed, the function f will alter all elements. In that case, f can accept indices, too. If the structure holds primitive elements, the function f must accept appropriate primitive unboxed arguments, and it will work faster if it also returns unboxed primitives.

If i or j is not within the dimensions of the object, throws ex-info.

(alter! (dv 1 2 3) 2 (fn ^double [^double x] (inc x)))
(alter! (dge 2 2) (fn ^double [^long i ^long j ^double x] (double (+ i j))))

amax

(amax x)

Absolute value of the first entry of vector space x that has the largest absolute value.

See related info about imax and iamax.

(amax (dv 1 -3 2)) => 3

asum

(asum x)

Sums absolute values of entries of vector or matrix x.

See related info about asum.

(asum (dv -1 2 -3)) => 6.0

ax

(ax alpha x)

Multiplies vector or matrix x by a scalar alpha. Similar to scal!, but does not change x. The result is a new instance. See axpy! and axpy.

axpby!

(axpby! alpha x beta y)(axpby! x beta y)(axpby! x y)(axpby! alpha x beta y & zs)

Multiplies elements of a vector or matrix x by scalar alpha and adds it to vector or matrix y, that was previously scaled by scalar beta.

The contents of y will be changed.

If called with 2 arguments, x and y, adds vector or matrix x to a vector or matrix y. If called with more than 4 arguments, at least every other have to be a vector or matrix. A scalar multiplier may be included before each object.

If the context or dimensions of x and y are not compatible, throws ex-info.

See related info about axpby.

(axpy! 3 x 0.9 y)
(axpy! x y)
(axpy! 3 x 0.2 y 4 z 0.4 v)

axpy

(axpy x y)(axpy x y z)(axpy x y z w & ws)

A pure variant of axpy! that does not change any of the arguments. The result is a new instance.

axpy!

(axpy! alpha x y)(axpy! x y)(axpy! alpha x y & zs)

Multiplies elements of a vector or matrix x by scalar alpha and adds it to a vector or matrix y.

The contents of y will be changed.

If called with 2 arguments, x and y, adds vector or matrix x to a vector or matrix y. If called with more than 3 arguments, at least every other have to be a vector or matrix. A scalar multiplier may be included before each object.

If the context or dimensions of x and y are not compatible, throws ex-info.

See related info about axpy.

(axpy! 3 x y)
(axpy! x y)
(axpy! 3 x y 4 z 0.4 v)

col

(col a j)

Returns the j-th column of the matrix a as a vector.

The vector has access to and can change the same data as the original matrix.

If the requested column is not within the dimensions of a, throws ex-info.

cols

(cols a)

Returns a lazy sequence of column vectors of the matrix a.

The vectors has access to and can change the same data as the original matrix.

compatible?

(compatible? x y)

Checks whether x and y are compatible in the sense that they use matching data formats (float, double, half) and computation contexts (native host memory, CUDA contexts etc.).

copy

(copy x)(copy x offset length)

Copies all entries of a vector or a matrix x to the newly created structure. Also see copy!.

copy!

(copy! x y)(copy! x y offset-x length offset-y)

Copies all entries of a vector or a matrix x to the compatible structure y.

Only y will be changed.

If the context or dimensions of x and y are not compatible, throws ex-info.

See related info about copy.

dia

(dia a)(dia a k)

Returns the diagonal elements of the matrix a in a vector. If called with an index k, returns a lower (< k 0) or upper (< 0 k) diagonal.

The vector has access to and can change the same data as the original matrix.

dias

(dias a)

Returns a lazy sequence of diagonal vectors of the matrix a.

The vectors has access to and can change the same data as the original matrix.

dim

(dim x)

Returns the dimension of the vector space x.

dot

(dot x y)

Computes the dot product of vectors or matrices x and y.

If the contexts or dimensions of x and y are not compatible, throws ex-info.

See related info about dot.

(dot (dv 1 2 3) (dv 1 2 3)) => 14.0

dt

(dt factory n source options)(dt factory n arg)(dt factory arg)

Creates a diagonally dominant tridiagonal matrix (DT) in the context of factory, with n rows and columns.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory.

If the provided size is negative, throws ex-info.

entry

(entry x i)(entry a i j)

Returns the boxed i-th entry of vector x, or (i, j)-th entry of matrix a.

For optimally accessing the elements of native objects use the equivalent entry function from uncomplicate.neanderthal.real namespace.

If i or j is not within the dimensions of the object, throws ex-info.

entry!

(entry! x val)(entry! x i val)(entry! a i j val)

Sets the i-th entry of vector x, or (i, j)-th entry of matrix a using a boxed method.

For optimally accessing the elements of native objects use the equivalent entry! function from uncomplicate.neanderthal.real namespace.

If i or j is not within the dimensions of the object, throws ex-info.

gb

(gb factory m n kl ku source options)(gb factory m n kl ku arg)(gb factory m n arg)(gb factory m n kl ku)(gb factory m n)(gb factory a)

Creates a general banded matrix (GB) in the context of factory, with m rows, n columns, kl sub (lower) diagonals and ku super (upper) diagonals.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory. If source is a matrix, dimensions m, n, kl, and ku are not mandatory.

The internal structure can be specified with a map of options: :layout (:column or :row).

If the provided indices or source do not make sense, throws ex-info.

(gb native-float 4 3 1 2 (range 20) {:layout :row})

gd

(gd factory n source options)(gd factory n arg)(gd factory arg)

Creates a diagonal matrix (GD) in the context of factory, with n rows and columns.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory.

If the provided indices or source do not make sense, throws ex-info.

ge

(ge factory m n source options)(ge factory m n arg)(ge factory m n)(ge factory a)

Creates a dense matrix (GE) in the context of factory, with m rows and n columns.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory. If source is a matrix, dimensions m and n are not mandatory.

The internal structure can be specified with a map of options: :layout (:column or :row).

If the provided indices or source do not make sense, throws ex-info.

(ge native-float 2 3)
(ge opencl-double 2 3 (range 6))
(ge opencl-float (ge native-double 2 3 (range 6)))
(ge native-float [[1 2 3] [4 5] [] [6 7 8 9]])

gt

(gt factory n source options)(gt factory n arg)(gt factory arg)

Creates a tridiagonal matrix (GT) in the context of factory, with n rows and columns.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory.

If the provided indices or source do not make sense, throws ex-info.

iamax

(iamax x)

The index of the first entry of vector x that has the largest absolute value.

See related info about iamax.

(iamax (dv 1 -3 2)) => 1

iamin

(iamin x)

The index of the first entry of vector x that has the smallest absolute value.

See related info about iamin.

(iamin (dv 1 -3 2)) => 0

imax

(imax x)

The index of the first entry of vector space x that has the largest value.

See related info about iamax.

(imax (dv 1 -3 2)) => 2

imin

(imin x)

The index of the first entry of vector x that has the smallest value.

See related info about iamin iamin.

(imin (dv 1 -3 2)) => 2

matrix-type

(matrix-type a)

Returns the type of the matrix implementation represented by the corresponding keyword (:ge, :tr, :sy, etc.).

matrix?

(matrix? x)

Tests if x is a matrix of any kind.

mm

(mm a b c & ds)(mm a b)

Pure matrix multiplication that returns the resulting matrix in a new instance. Computes alpha a * b, if alpha is scalar, or alpha * a * b * c * ... * ds if alpha is a vector. Does matrix composition by optimally multiplying the chain of matrices.

If any consecutive pair’s dimensions do not fit for matrix multiplication, throws ex-info.

mm!

(mm! alpha a b beta c)(mm! alpha a b c)(mm! alpha a b)(mm! a b)

Matrix-matrix multiplication. Multiplies matrix a, scaled by scalar alpha, by matrix b, and adds it to matrix c previously scaled by scalar beta.

If called with only 2 matrices, a and b, multiplies matrix a by a matrix b, and puts the result in the one that is a GE matrix. In this case, exactly one of a or b has to be, and one not be a GE matrix, but TR, or a matrix type that supports in-place multiplication. Scaling factors alpha and/or beta may be left out.

The contents of the destination matrix will be changed.

If the context or dimensions of a, b and c are not compatible, throws ex-info.

See related info about cblas_?gemm, and trmm.

(def a (dge 2 3 (range 6)))
(def b (dge 3 2 (range 2 8)))
(def c (dge 2 2 [1 1 1 1]))
(def e (dtr 3 (range 6)))

(mm! 1.5 a b 2.5 c)
(mm! 2.3 a e)
(mm! e a)

mmt

(mmt alpha a)(mmt a)

Pure variant of mmt!, multiplies matrix a by its transpose and return the scaled result in a new instance of SY matrix c.

If alpha is not provided, the scaling factor is 1.0.

mmt!

(mmt! alpha a beta c)(mmt! alpha a c)(mmt! a c)

Multiplies matrix a by its transpose, scales the result by alpha, and adds it to a symmetric matrix c scaled by beta.

If alpha and/or beta are not provided, scales by 1.0.

mrows

(mrows a)

Returns the number of rows of the matrix a.

mv

(mv alpha a x beta y)(mv alpha a x y)(mv alpha a x)(mv a x)

Matrix-vector multiplication. A pure version of mv! that returns the result in a new vector instance. Computes alpha * a * x.

mv!

(mv! alpha a x beta y)(mv! alpha a x y)(mv! a x y)(mv! a x)

Matrix-vector multiplication. Multiplies matrix a, scaled by scalar alpha, by vector x, and adds it to vector y previously scaled by scalar beta.

If called with 2 arguments, a and x, multiplies matrix a by a vector x, and puts the result in the vector x. Scaling factors alpha and/or beta may be left out.

The contents of the destination vector will be changed.

If the context or dimensions of a, x and y are not compatible, throws ex-info.

See related info about gemv, trmv, and similar XXmv functions.

(mv! 3 a x y)
(mv! a x y)
(mv! a x)

native

(native x)

Ensures that x is in the native main memory, and if not, transfers it there. x continues to live until explicitly released. See native!.

(let [v (fv [1 2 3])]
  (identical? (native v) v)) => true

native!

(native! x)

Ensures that x is in the native main memory, and if not, transfers it there and releases x. See native.

ncols

(ncols a)

Returns the number of columns of the matrix a.

nrm1

(nrm1 x)

Computes the 1-norm of vector or matrix x.

nrm2

(nrm2 x)

Computes the Euclidan norm of vector x, or Frobenius norm of matrix x.

See related info about nrm2.

(nrm2 (dv 1 2 3)) => 3.7416573867739413

nrmi

(nrmi x)

Computes the infinity-norm of vector or matrix x.

raw

(raw x)(raw factory x)

Returns an uninitialized instance of the same type and dimension(s) as x.

rk

(rk alpha x y a)(rk alpha x y)(rk alpha-or-x y)(rk x)

Pure outer product of two vectors. A pure version of rk! that returns the result in a new matrix instance.

rk!

(rk! alpha x y a)(rk! alpha-or-x y a)(rk! y a)

The outer product of two vectors. Multiplies vector x with transposed vector y, scales the resulting matrix by scalar alpha, and adds it to the matrix a.

The contents of a will be changed.

If the context or dimensions of a, x and y are not compatible, throws ex-info.

If y is not provided, uses x in its place, and computes a symmetric outer product.

See related info about ger.

(rk! 1.5 (dv 1 2 3) (dv 4 5) a)

rot!

(rot! x y c s)(rot! x y c)

Rotates points of vectors x and y in the plane by cos c and sin s.

If the context or dimensions of x and y are not compatible, throws ex-info.

See related info about rot.

rotg!

(rotg! abcs)

Computes the parameters for a givens rotation and puts them as entries of a 4-element vector abcs, that can be used as parameters in rot!.

If abcs does not have at least 4 entries, throws ex-info.

See related info about rotg.

rotm!

(rotm! x y param)

Rotates points of vectors x and y in the plane using Givens rotation.

param must be a vector of at least 4 entries.

See related info about rotm.

rotmg!

(rotmg! d1d2xy param)

Generate modified plane rotation.

If the context or dimensions of d1d2xy and param are not compatible, or d1d2xy does not have at least at least 4 entries, or param does not have at least 5 entries, throws ex-info.

See related info about rotmg.

row

(row a i)

Returns the i-th row of the matrix a as a vector.

The vector has access to and can change the same data as the original matrix.

If the requested column is not within the dimensions of a, throws ex-info.

rows

(rows a)

Returns a lazy sequence of row vectors of the matrix a.

The vectors has access to and can change the same data as the original matrix.

sb

(sb factory n k source options)(sb factory n source arg)(sb factory n arg)(sb factory source)

Creates a symmetric banded matrix (SB) in the context of factory, with n rows and columns, k sub (lower) and ‘k’ super (upper) diagonals.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory. If source is a matrix, dimensions n and k are not mandatory.

The internal structure can be specified with a map of options: :layout (:column or :row), and :uplo (:upper or :lower).

If the provided indices or source do not make sense, throws ex-info.

(sb native-float 4 2 (range 20) {:layout :row})

scal

(scal alpha x)

Multiplies all entries of a copy a vector or matrix x by scalar alpha. Also see scal!.

scal!

(scal! alpha x)

Multiplies all entries of a vector or matrix x by scalar alpha.

After scal!, x will be changed.

See related info about scal.

sp

(sp factory n source options)(sp factory n arg)(sp factory arg)

Creates a symmetric packed matrix (SP) in the context of factory, with n rows and columns.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory. If source is a matrix, dimension n is not mandatory.

The internal structure can be specified with a map of options: :layout (:column or :row), and :uplo (:upper or :lower).

If the provided indices or source do not make sense, throws ex-info.

(sp native-float 4 2 (range 20) {:uplo :upper})

st

(st factory n source options)(st factory n arg)(st factory arg)

Creates a symmetric tridiagonal matrix (ST) in the context of factory, with n rows and columns.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory.

If the provided size is negative, throws ex-info.

subband

(subband a kl ku)

Returns a part of the banded matrix a starting from row 0, column 0, that has kl subdiagonals and ku superdiagonals.

The resulting submatrix has a live connection to a’s data. Any change to the subband data will affect the original data.

If the requested region is not within the dimensions of a, throws ex-info.

submatrix

(submatrix a i j k l)(submatrix a k l)

Returns a submatrix of the matrix a starting from row i, column j, that has k rows and l columns.

The resulting submatrix has a live connection to a’s data. Any change to the subvector data will affect the original data. If you wish to disconnect the submatrix from the parent matrix, make a copy prior to any destructive operation.

If the requested region is not within the dimensions of a, throws ex-info.

(submatrix (ge double-factroy 4 3 (range 12)) 1 1 2 1)

subvector

(subvector x k l)

Returns a subvector starting witk k, l entries long, which is a part of the neanderthal vector x.

The resulting subvector has a live connection to x’s data. Any change to the subvector data will affect the vector data. If you wish to disconnect the subvector from the parent vector, make a copy prior to any destructive operation.

If the requested region is not within the dimensions of x, throws ex-info.

sum

(sum x)

Sums values of entries of a vector or matrix x. See asum.

(sum (dv -1 2 -3)) => -2.0

swp!

(swp! x y)

Swaps all entries of vectors or matrices x and y.

Both x and y will be changed.

If the context or dimensions of x and y are not compatible, throws ex-info.

See related info about swap.

sy

(sy factory n source options)(sy factory n arg)(sy factory source)

Creates a dense symmetric matrix (SY) in the context of factory, with n rows and n columns.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory. If source is a matrix, dimension n is not mandatory

The internal structure can be specified with a map of options: :layout (:column or :row), and :uplo (:upper or :lower).

If the provided indices or source do not make sense, throws ExceptionInfo.

(sy native-float 2)
(sy opencl-float 3 (range 6))
(sy cuda-float (ge native-double 2 3 (range 6)))

symmetric?

(symmetric? a)

Tests if x is a symmetric matrix of any kind.

tb

(tb factory n k source options)(tb factory n source arg)(tb factory n arg)(tb factory source)

Creates a triangular banded matrix (TB) in the context of factory, with n rows and columns, k sub (lower) or super (upper) diagonals.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory. If source is a matrix, dimensions n and k are not mandatory.

The internal structure can be specified with a map of options: :layout (:column or :row), :uplo (:upper or :lower), and :diag (:unit or :non-unit).

If the provided indices or source do not make sense, throws ex-info.

(tb native-float 4 2 (range 20) {:layout :row})

tp

(tp factory n source options)(tp factory n arg)(tp factory source)

Creates a triangular packed matrix (TP) in the context of factory, with n rows and columns.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory. If source is a matrix, dimension n is not mandatory.

The internal structure can be specified with a map of options: :layout (:column or :row), :uplo (:upper or :lower), and :diag (:unit or :non-unit).

If the provided indices or source do not make sense, throws ex-info.

(tp native-float 4 2 (range 20) {:uplo :upper :diag :unit})

tr

(tr factory n source options)(tr factory n arg)(tr factory source)

Creates a dense triangular matrix (TR) in the context of factory, with n rows and n columns.

If source is provided, transfers the data to the result. source is typically a sequence, a matrix, or another structure that can be transferred to the context of factory. If source is a matrix, dimension n is not mandatory.

The internal structure can be specified with a map of options: :layout (:column or :row), :uplo (:upper or :lower), and :diag (:unit or :non-unit).

If the provided dimensions or source do not make sense, throws ex-info.

(tr native-float 2)
(tr opencl-float 3 (range 6))
(tr cuda-float (ge native-double 2 3 (range 6)))

trans

(trans a)

Transposes matrix a, i.e returns a matrix that has m’s columns as rows.

The transpose does not affect the internal structure of a. The resulting matrix has a live connection to a’s data.

trans!

(trans! a)

Transposes matrix a’s data in-place. For the ‘real’ transpose, use the trans function.

The transpose affects the internal structure of a.

(trans! (dge 2 3 [1 2, 3 4, 5 6])) => (dge 2 3 [1 3, 5 2, 4 ,6])

transfer

(transfer factory x)(transfer x)

Transfers the data to the memory context defined by factory (native, OpenCL, CUDA, etc.).

If factory is not provided, moves the data to the main host memory. If x is already in the main memory, makes a fresh copy.

(transfer *opencl-factory* (fv [1 2 3]))
(transfer cuda-double (fge 2 3 (range 6)))
(transfer *cuda-factory* (dge 2 3 (range 6)))
(transfer (fv [1 2 3]))

transfer!

multimethod

Transfers the data from source to destination regardless of the structure type or memory context.

Typically you would use it when you want to move data between the host memory and external device memory, or between incompatible data types. If you want to simply move homogenous data from one object to another in the same memory context, you should prefer copy!. If possible, the data will simply be copied anyway, but this is a multimethod so mind the slight call overhead.

(transfer! (fv 1 2 3) (cuv 3))
(transfer! (dv 3) (fv 3))

triangular?

(triangular? a)

Tests if x is a triangular matrix of any kind.

vctr

(vctr factory source)(vctr factory x & xs)

Creates a dense vector in the context of factory, from the provided source.

If source is an integer, creates a vector of zeroes. If source is a real number, wraps it in the resulting vector. Otherwise, transfers the data from source (a sequence, vector, etc.) to the resulting vector.

If the provided source does not make sense, throws ex-info.

(vctr double-factory 3)
(vctr float-factory 1 2 3)
(vctr opencl-factory [1 2 3])
(vctr opencl-factory (vctr float-factory [1 2 3]))

vctr?

(vctr? x)

Tests if x is a (neanderthal) vector.

view-ge

(view-ge a)(view-ge a stride-mult)(view-ge a m n)

View raw data of a through a GE matrix structure, with optional dimensions and/or stride multiplier.

Changes to the resulting object affect the underlying memory of a, even the parts that might not be accessible by a. Use with caution!

If a is already a GE matrix, view-ge returns a. Otherwise it creates a new instance that reuses the master’s data.

(view-ge (tr float-factory 3 (range 6)))

view-sy

(view-sy a)(view-sy a options)

View raw data of a through a SY matrix structure.

Changes to the resulting object affect the underlying memory of a, even the parts that might not be accessible by a. Use with caution! If a is already a SY matrix, view-sy returns a. Otherwise it creates a new instance that reuses the master’s data.

Options: :uplo (upper or :lower).

view-sy creates a new instance that reuses the master’s data.

(view-sy (tr float-factory 3 (range 6)))

view-tr

(view-tr a)(view-tr a options)

View raw data of a through a TR matrix structure.

Changes to the resulting object affect the underlying memory of a, even the parts that might not be accessible by a. Use with caution! If a is already a TR matrix, view-tr returns a. Otherwise it creates a new instance that reuses the master’s data.

Options: :uplo (upper or :lower), and :diag (:unit or :non-unit).

(view-tr (ge float-factory 3 2 (range 6)))

view-vctr

(view-vctr x)(view-vctr x stride-mult)

Attach a dense vector to the raw data of x, with optional stride multiplier stride-mult.

Changes to the resulting object affect the source x, even the parts of data that might not be accessible by x. Use with caution!

view-vctr might return the master object itself, or create a new instance that reuses the master’s data.

(view-vctr (ge float-factory 2 3 (range 6)))

vspace?

(vspace? x)

Tests if x is a vector space.

xpy

(xpy x y)(xpy x y & zs)

Sums vectors or matrices x, y, and zs. The result is a new instance. See axpy! and axpy.

zero

(zero x)(zero factory x)

Returns an instance of the same type and dimension(s) as the x, initialized with zeroes.