23 API Reference
Complete reference for the scicloj.lalinea public API:
scicloj.lalinea.tensor— tensor construction, structural operations, EJML interopscicloj.lalinea.linalg— products, decompositions, solvescicloj.lalinea.elementwise— tape-aware element-wise functionsscicloj.lalinea.transform— FFT and real-valued transformsscicloj.lalinea.tape— computation tape and memory inspectionscicloj.lalinea.grad— reverse-mode automatic differentiationscicloj.lalinea.vis— visualization helpers
scicloj.lalinea.tensor
matrix
[rows]
Create a matrix (rank-2 tensor) from nested sequences.
(matrix [[1 2] [3 4]])(t/matrix [[1 2] [3 4]])#la/R [:float64 [2 2]
[[1.000 2.000]
[3.000 4.000]]]
eye
[n]
Identity matrix of size \(n \times n\).
(t/eye 3)#la/R [:float64 [3 3]
[[1.000 0.000 0.000]
[0.000 1.000 0.000]
[0.000 0.000 1.000]]]
zeros
[r c]
Zero matrix of size \(r \times c\).
(t/zeros 2 3)#la/R [:float64 [2 3]
[[0.000 0.000 0.000]
[0.000 0.000 0.000]]]
ones
[r c]
Matrix of ones, size \(r \times c\).
(t/ones 2 3)#la/R [:float64 [2 3]
[[1.000 1.000 1.000]
[1.000 1.000 1.000]]]
diag
[a]
Diagonal operations:
- Given a 2D matrix: extract the main diagonal as a 1D tensor.
- Given a 1D sequence/tensor: create a diagonal matrix.
(t/diag [3 5 7])#la/R [:float64 [3 3]
[[3.000 0.000 0.000]
[0.000 5.000 0.000]
[0.000 0.000 7.000]]]
Extract diagonal from a 2D matrix:
(t/diag (t/matrix [[1 2 3] [4 5 6] [7 8 9]]))#la/R [:float64 [3] [1.000 5.000 9.000]]column
[xs]
Create a column vector (shape [n 1]) from a sequence.
(t/column [1 2 3])#la/R [:float64 [3 1]
[[1.000]
[2.000]
[3.000]]]
row
[xs]
Create a row vector (shape [1 n]) from a sequence.
(t/row [1 2 3])#la/R [:float64 [1 3]
[[1.000 2.000 3.000]]]
compute-matrix
[r c f]
Build an [r c] matrix from a function of row and column indices. f takes two longs (row, col) and returns a double.
(t/compute-matrix 3 3 (fn [i j] (if (== i j) 1.0 0.0)))#la/R [:float64 [3 3]
[[1.000 0.000 0.000]
[0.000 1.000 0.000]
[0.000 0.000 1.000]]]
compute-tensor
[shape-vec f datatype]
Create a tensor by calling a function at each index. Returns a RealTensor for 1D and 2D shapes, raw tensor for 3D+. Use materialize or clone to force evaluation when needed.
(t/compute-tensor [2 3] (fn [i j] (+ (* 10.0 i) j)) :float64)#la/R [:float64 [2 3]
[[0.000 1.000 2.000]
[10.00 11.00 12.00]]]
complex-tensor
[tensor-or-re]
[re-data im-data]
Create a ComplexTensor.
Arities: (complex-tensor tensor) — wrap an existing tensor with last dim = 2 (complex-tensor re-data im-data) — from separate real and imaginary parts
re-data and im-data can be: double arrays, seqs, dtype readers, or tensors. They must have the same shape.
(t/complex-tensor [1.0 2.0 3.0] [4.0 5.0 6.0])#la/C [:float64 [3] [1.000 + 4.000 i 2.000 + 5.000 i 3.000 + 6.000 i]]complex-tensor-real
[re-data]
Create a ComplexTensor from real data only (imaginary parts = 0).
(t/complex-tensor-real [5.0 6.0 7.0])#la/C [:float64 [3] [5.000 + 0.000 i 6.000 + 0.000 i 7.000 + 0.000 i]]complex
[re im]
Create a scalar ComplexTensor from real and imaginary parts.
(t/complex 3.0 4.0)#la/C [:float64 [] [3.000 + 4.000 i]]wrap-tensor
Wrap a raw interleaved [… 2] tensor as a ComplexTensor. Inverse of ->tensor on ComplexTensors.
(let [raw (t/matrix [[1.0 2.0] [3.0 4.0]])
ct (t/wrap-tensor raw)]
[(t/complex? ct) (t/complex-shape ct)])[true [2]]real-tensor?
[x]
True if x is a RealTensor.
(t/real-tensor? (t/matrix [[1 2] [3 4]]))true(t/real-tensor? [1 2 3])falsecomplex?
True if x is a ComplexTensor.
(t/complex? (t/complex 3.0 4.0))true(t/complex? (t/eye 2))falsescalar?
True if this ComplexTensor represents a scalar complex number.
(t/scalar? (t/complex 3.0 4.0))trueshape
[a]
Return the logical shape of a tensor as a vector. For ComplexTensors, returns the complex shape (without the trailing interleaved dimension).
(t/shape (t/matrix [[1 2 3] [4 5 6]]))[2 3]For ComplexTensors, returns the logical shape (without the trailing interleaved dimension):
(t/shape (t/complex-tensor [1.0 2.0] [3.0 4.0]))[2]complex-shape
The complex shape (underlying shape without trailing 2).
(t/complex-shape (t/complex-tensor [[1.0 2.0] [3.0 4.0]]
[[5.0 6.0] [7.0 8.0]]))[2 2]reshape
[a new-shape]
Reshape a tensor to a new shape. Zero-copy when possible. Returns a RealTensor for real input, ComplexTensor for complex.
(t/reshape (t/matrix [[1 2] [3 4]]) [4])#la/R [:float64 [4] [1.000 2.000 3.000 4.000]]select
[a & args]
Slice a tensor along dimensions. Each argument selects along one axis: an index (long), :all, or a sequence of indices. Returns a RealTensor for real input, ComplexTensor for complex.
Row 0 of a matrix:
(t/select (t/matrix [[1 2] [3 4] [5 6]]) 0 :all)#la/R [:float64 [2] [1.000 2.000]]submatrix
[m rows cols]
Extract a contiguous submatrix. rows and cols can be :all or a range.
For ComplexTensors, operates on the complex dimensions and preserves the ComplexTensor type.
(t/submatrix (t/eye 4) :all (range 2))#la/R [:float64 [4 2]
[[1.000 0.000]
[0.000 1.000]
[0.000 0.000]
[0.000 0.000]]]
flatten
[a]
Reshape a tensor to 1D, preserving element order. Column vectors [n 1] become [n], matrices [r c] become [r*c]. For ComplexTensors, flattens the logical dimensions (trailing 2 preserved).
(t/flatten (t/column [1 2 3]))#la/R [:float64 [3] [1.000 2.000 3.000]]hstack
[cols]
Assemble a matrix by placing column vectors side by side. Each element should be a column vector [n 1] or a 1D tensor [n]. Returns an [n k] matrix where k is the number of columns.
(t/hstack [(t/column [1 2]) (t/column [3 4])])#la/R [:float64 [2 2]
[[1.000 3.000]
[2.000 4.000]]]
reduce-axis
[a reduce-fn axis]
Reduce a tensor along an axis.
reduce-fn is applied to each slice along the given axis (e.g. elem/sum, elem/reduce-max).
For a 2D matrix: axis 0 reduces across rows (one result per column), axis 1 reduces across columns (one result per row).
Returns a RealTensor for real input, ComplexTensor for complex input.
Row sums (axis 1) and column sums (axis 0):
(t/reduce-axis (t/matrix [[1 2 3] [4 5 6]]) el/sum 1)#la/R [:float64 [2] [6.000 15.00]]clone
[a]
Deep-copy a tensor into a fresh contiguous array. Always allocates, even when the input is already concrete. Use materialize when you only need to ensure the result is concrete without a redundant copy.
Always allocates a fresh copy:
(let [m (t/matrix [[1 2] [3 4]])]
(identical? m (t/clone m)))falseconcrete?
[a]
True if the tensor is backed by a contiguous array (not a lazy reader chain).
Concrete (backed by array):
(t/concrete? (t/matrix [[1 2] [3 4]]))trueLazy (reader chain from el/+):
(t/concrete? (el/+ (t/matrix [[1 2] [3 4]])
(t/matrix [[10 20] [30 40]])))falsematerialize
[a]
Ensure a tensor is backed by a contiguous array. Returns the input unchanged if already concrete; clones if lazy. Use clone when you need a guaranteed independent copy.
No-op on concrete:
(let [m (t/matrix [[1 2] [3 4]])]
(identical? m (t/materialize m)))trueMaterializes lazy results:
(t/materialize (el/+ (t/matrix [[1 2] [3 4]])
(t/matrix [[10 20] [30 40]])))#la/R [:float64 [2 2]
[[11.00 22.00]
[33.00 44.00]]]
->tensor
[x]
Extract the underlying dtype-next tensor from a RealTensor or ComplexTensor. Returns x unchanged if it is neither.
(t/->tensor (t/matrix [[1 2] [3 4]]))#tech.v3.tensor<float64>[2 2]
[[1.000 2.000]
[3.000 4.000]]For ComplexTensors, returns the underlying [... 2] tensor:
(t/shape (t/->tensor (t/complex-tensor [1.0 2.0] [3.0 4.0])))[2 2]->real-tensor
[t]
Wrap a dtype-next tensor in a RealTensor.
(t/->real-tensor (t/matrix [[1 2] [3 4]]))#la/R [:float64 [2 2]
[[1.000 2.000]
[3.000 4.000]]]
->double-array
[a]
Get the backing double[] of a tensor. Zero-copy when the tensor is backed by a contiguous array; copies for subviews or lazy tensors. Works for both RealTensors and ComplexTensors.
(let [arr (t/->double-array (t/matrix [[1 2] [3 4]]))]
(alength arr))4For ComplexTensors, returns the interleaved [re im ...] array:
(let [ct (t/complex-tensor [1.0 2.0] [3.0 4.0])]
(seq (t/->double-array ct)))(1.0 3.0 2.0 4.0)backing-array
[t]
Return the shared backing double[] of a tensor, or nil if the tensor is lazy or not array-backed. Never copies. Useful for checking whether two tensors share memory.
(let [A (t/matrix [[1 2] [3 4]])
B (t/clone A)]
[(some? (t/backing-array A))
(identical? (t/backing-array A)
(t/backing-array B))])[true false]->reader
[a]
[a datatype]
Get a read-only indexed view of a tensor’s elements.
(let [rdr (t/->reader (t/column [10 20 30]))]
(rdr 2))30.0array-buffer
[a]
Return the array buffer backing a tensor, or nil if none exists (e.g. for lazy or strided tensors).
(some? (t/array-buffer (t/clone (t/eye 3))))truemake-reader
[datatype n body]
Create a lazy functional buffer that computes values on the fly. idx is bound in the body expression. Returns a raw dtype-next reader (not a RealTensor) for compatibility with dataset pipelines.
(t/make-reader :float64 10 (* 2.0 idx))(t/make-reader :float64 5 (* idx idx))[0.0 1.0 4.0 9.0 16.0]make-container
[datatype n-or-data]
Create a mutable buffer of the given dtype and size (or from data). Returns a RealTensor wrapping a concrete buffer.
(t/make-container :float64 4)#la/R [:float64 [4] [0.000 0.000 0.000 0.000]]elemwise-cast
[a datatype]
Cast a tensor or buffer to a different element type. Returns a raw dtype-next buffer.
(t/elemwise-cast (t/matrix [[1 2] [3 4]]) :int32)#tech.v3.tensor<int32>[2 2]
[[1 2]
[3 4]]mset!
[a & args-and-val]
Mutate a tensor element in place. Takes a tensor, indices, and a value. For RealTensors, unwraps to the backing tensor before mutation.
(let [m (t/clone (t/matrix [[1 2] [3 4]]))]
(t/mset! m 0 0 99.0)
(m 0 0))99.0set-value!
[a idx val]
Set a value at a flat (linear) index. Mutates in place.
(let [buf (t/make-container :float64 3)]
(t/set-value! buf 1 42.0)
(buf 1))42.0tensor->dmat
[tensor]
Zero-copy: convert a [r c] tensor to an EJML DMatrixRMaj sharing the same double[]. Falls back to a copy for lazy/strided tensors.
(let [t (t/matrix [[1 2] [3 4]])
dm (t/tensor->dmat t)]
(= org.ejml.data.DMatrixRMaj (type dm)))truedmat->tensor
[dm]
Zero-copy: convert an EJML DMatrixRMaj to a raw [r c] dtype-next tensor sharing the same double[]. Wrap with ->real-tensor if needed.
(let [dm (t/tensor->dmat (t/eye 2))
t (t/dmat->tensor dm)]
(= [2 2] (t/shape t)))truecomplex-tensor->zmat
[ct]
Zero-copy: convert a ComplexTensor to an EJML ZMatrixRMaj sharing the same double[]. Falls back to a copy for lazy ComplexTensors.
(let [ct (t/complex-tensor [1.0 2.0] [3.0 4.0])
zm (t/complex-tensor->zmat ct)]
(= org.ejml.data.ZMatrixRMaj (type zm)))truezmat->complex-tensor
[zm]
Zero-copy: convert an EJML ZMatrixRMaj to a ComplexTensor [r c] sharing the same double[].
(let [zm (t/complex-tensor->zmat (t/complex-tensor [1.0 2.0] [3.0 4.0]))
ct (t/zmat->complex-tensor zm)]
(t/complex? ct))truescicloj.lalinea.linalg
Most la/ functions are polymorphic — they accept both real tensors and ComplexTensors.
mmul
[a b]
Matrix multiply. Accepts dtype-next tensors or ComplexTensors.
For real matrices: \(C = A B\). For complex matrices: delegates to EJML’s ZMatrixRMaj multiply.
(la/mmul (t/matrix [[1 2] [3 4]])
(t/column [5 6]))#la/R [:float64 [2 1]
[[17.00]
[39.00]]]
dot
[u v]
Inner product. For real vectors: \(\sum u_i v_i\) (returns double). For complex vectors: Hermitian \(\langle u,v \rangle = \sum u_i \overline{v_i}\) (returns scalar ComplexTensor).
(la/dot (t/column [1 2 3]) (t/column [4 5 6]))32.0dot-conj
[u v]
Hermitian inner product: \(\sum u_i \overline{v_i}\). For real vectors: same as dot (\(\sum u_i v_i\)). For complex vectors: \(\sum u_i \overline{v_i}\) (returns scalar ComplexTensor).
Hermitian inner product: \(\langle a, a \rangle = \|a\|^2\).
(let [a (t/complex-tensor [3.0 1.0] [4.0 2.0])
result (la/dot-conj a a)]
(la/close-scalar? (el/re result) 30.0))truempow
[a k]
Matrix power \(A^k\) for non-negative integer \(k\). Uses exponentiation by squaring — \(O(\log k)\) multiplications. Returns the identity for \(k=0\).
(la/mpow (t/matrix [[1 1] [0 1]]) 5)#la/R [:float64 [2 2]
[[1.000 5.000]
[0.000 1.000]]]
transpose
[a]
Matrix transpose (real) or conjugate transpose (complex).
For real matrices: returns a zero-copy strided view sharing the same backing data. For complex matrices: \(B = A^\dagger\) (Hermitian adjoint).
(la/transpose (t/matrix [[1 2 3] [4 5 6]]))#la/R [:float64 [3 2]
[[1.000 4.000]
[2.000 5.000]
[3.000 6.000]]]
trace
[a]
Matrix trace. Returns a double for real matrices, a scalar ComplexTensor for complex matrices.
(la/trace (t/matrix [[1 2] [3 4]]))5.0det
[a]
Matrix determinant. Returns a double for real matrices, a scalar ComplexTensor for complex matrices.
(la/det (t/matrix [[1 2] [3 4]]))-2.0norm
[a]
Frobenius norm.
(la/norm (t/matrix [[3 0] [0 4]]))5.0rank
[a]
[a tol]
Matrix rank: number of singular values above tol (default 1e-10).
(la/rank (t/matrix [[1 2] [2 4]]))1condition-number
[a]
Condition number \(\kappa(A) = \sigma_{\max} / \sigma_{\min}\) from the SVD.
(la/condition-number (t/matrix [[2 1] [1 3]]))2.618033988749894solve
[a b]
Solve \(AX = B\) for \(X\). Returns nil if singular. \(A\) is [n n], \(B\) is [n m]. Returns \(X\) as a RealTensor or ComplexTensor.
Solve \(Ax = b\):
(let [A (t/matrix [[2 1] [1 3]])
b (t/column [5 7])]
(la/solve A b))#la/R [:float64 [2 1]
[[1.600]
[1.800]]]
invert
[a]
Matrix inverse. Returns nil if singular.
(let [A (t/matrix [[1 2] [3 5]])]
(la/close? (la/mmul A (la/invert A)) (t/eye 2)))truelstsq
[a b]
[a b tol]
Least-squares solve: minimise \(\|Ax - b\|_2\). Returns a map with :x, :residuals (\(\|Ax-b\|^2\)), and :rank.
(let [{:keys [x rank]} (la/lstsq (t/matrix [[1 1] [1 2] [1 3]])
(t/column [1 2 3]))]
{:rank rank :close? (la/close? x (t/column [0 1]))}){:rank 2, :close? true}pinv
[a]
[a tol]
Moore-Penrose pseudoinverse via SVD: \(V \Sigma^{-1} U^T\). Singular values below tol (default 1e-10) are treated as zero.
(let [A (t/matrix [[2 1] [1 3]])]
(la/close? (la/mmul A (la/pinv A)) (t/eye 2)))trueeigen
[a]
Eigendecomposition of a real matrix. Returns a map: :eigenvalues — ComplexTensor of shape [n] (complex vector) :eigenvectors — vector of column eigenvectors as real tensors (or nil)
Use (el/re (:eigenvalues result)) for the real parts, or real-eigenvalues for a sorted real tensor.
(let [result (la/eigen (t/matrix [[2 1] [1 2]]))]
[(count (:eigenvectors result))
(t/complex-shape (:eigenvalues result))])[2 [2]]real-eigenvalues
[a]
Sorted real eigenvalues of a symmetric/Hermitian matrix. Returns a real [n] tensor, sorted ascending.
(la/real-eigenvalues (t/matrix [[2 1] [1 2]]))#la/R [:float64 [2] [1.000 3.000]]svd
[a]
Singular value decomposition of a real matrix: \(A = U \Sigma V^T\). Returns a map with :U, :S (singular values), :Vt.
(let [{:keys [U S Vt]} (la/svd (t/matrix [[1 0] [0 2] [0 0]]))]
[(t/shape U)
(count S)
(t/shape Vt)])[[3 3] 2 [2 2]]qr
[a]
QR decomposition: \(A = QR\). Returns a map with :Q and :R.
(let [{:keys [Q R]} (la/qr (t/matrix [[1 1] [1 2] [0 1]]))]
(la/close? (la/mmul Q R) (t/matrix [[1 1] [1 2] [0 1]])))truecholesky
[a]
Cholesky decomposition: \(A = LL^T\) (real) or \(A = LL^\dagger\) (complex). Returns the lower-triangular \(L\), or nil if not SPD/HPD.
(let [A (t/matrix [[4 2] [2 3]])
L (la/cholesky A)]
(la/close? (la/mmul L (la/transpose L)) A))truenull-space
[a]
[a tol]
Null space basis: columns of \(V\) corresponding to singular values \(\approx 0\). Returns a matrix whose columns span \(\mathrm{Null}(A)\), or nil if full rank.
(let [ns (la/null-space (t/matrix [[1 2] [2 4]]))]
(la/close? (la/mmul (t/matrix [[1 2] [2 4]]) ns)
(t/zeros 2 1)))truecol-space
[a]
[a tol]
Column space basis: first \(r\) columns of \(U\) from the SVD, where \(r\) is the number of singular values above tol.
(second (t/shape (la/col-space (t/matrix [[1 2] [2 4]]))))1close?
[a b]
[a b tol]
True when two matrices (or ComplexTensors) are approximately equal: \(\|a - b\|_F < \mathrm{tol}\). Default tolerance is 1e-10.
(la/close? (t/eye 2) (t/eye 2))true(la/close? (t/eye 2) (t/zeros 2 2))falseclose-scalar?
[a b]
[a b tol]
True when two scalars are approximately equal: \(|a - b| < \mathrm{tol}\). Default tolerance is 1e-10.
(la/close-scalar? 1.00000000001 1.0)truelift
[f-or-var & args]
Apply an external function to La Linea tensors (one-shot).
Unwraps RealTensor/ComplexTensor arguments, applies f, and re-wraps the result. Pass a Var for tape recording: (la/lift #’dfn/sqrt A) ;; tape-recorded (la/lift dfn/sqrt A) ;; not recorded
One-shot bridge: unwrap, apply, re-wrap. Pass a Var for tape recording.
(la/lift el/sqrt (t/matrix [[4 9] [16 25]]))#la/R [:float64 [2 2]
[[2.000 3.000]
[4.000 5.000]]]
lifted
[f-or-var]
Return a lifted version of an external function (curried).
Pass a Var for tape recording: (def my-sqrt (la/lifted #’dfn/sqrt)) ;; tape-aware (def my-sqrt (la/lifted dfn/sqrt)) ;; not recorded
Curried version — returns a reusable function.
(let [my-sqrt (la/lifted el/sqrt)]
(my-sqrt (t/column [4 9 16])))#la/R [:float64 [3 1]
[[2.000]
[3.000]
[4.000]]]
scicloj.lalinea.elementwise
The canonical namespace for element-wise operations. All functions are tape-aware and dispatch on t/complex? for complex inputs. Naming follows dtype-next’s dfn/ conventions (+, -, *, /).
+
[a b]
Element-wise addition.
(el/+ (t/column [1 2 3]) (t/column [10 20 30]))#la/R [:float64 [3 1]
[[11.00]
[22.00]
[33.00]]]
Complex addition:
(let [a (t/complex-tensor [1.0 2.0] [3.0 4.0])
b (t/complex-tensor [10.0 20.0] [30.0 40.0])]
(el/re (el/+ a b)))#la/R [:float64 [2] [11.00 22.00]]-
[a b]
Element-wise subtraction.
(el/- (t/column [10 20 30]) (t/column [1 2 3]))#la/R [:float64 [3 1]
[[9.000]
[18.00]
[27.00]]]
scale
[a alpha]
Scalar multiply. Returns α · a.
(el/scale (t/column [2 3 4]) 5.0)#la/R [:float64 [3 1]
[[10.00]
[15.00]
[20.00]]]
*
[a b]
Element-wise multiply (Hadamard product for real, pointwise complex multiply for complex).
(el/* (t/column [2 3 4]) (t/column [10 20 30]))#la/R [:float64 [3 1]
[[20.00]
[60.00]
[120.0]]]
Complex multiplication: \((1+3i)(2+4i) = -10 + 10i\)
(let [a (t/complex-tensor [1.0] [3.0])
b (t/complex-tensor [2.0] [4.0])
c (el/* a b)]
[(el/re (c 0)) (el/im (c 0))])[-10.0 10.0]/
[a b]
Element-wise division. Supports both real and complex inputs.
(el// (t/column [10 20 30]) (t/column [2 4 5]))#la/R [:float64 [3 1]
[[5.000]
[5.000]
[6.000]]]
Complex division:
(el// (t/complex 3.0 4.0) (t/complex 1.0 2.0))#la/C [:float64 [] [2.200 - 0.4000 i]]re
[a]
Real part(s). For complex: returns a RealTensor view (or double for scalars). For real: returns the input unchanged.
(el/re (t/complex-tensor [1.0 2.0] [3.0 4.0]))#la/R [:float64 [2] [1.000 2.000]]im
[a]
Imaginary part(s). For complex: returns a RealTensor view (or double for scalars). For real: returns zeros matching the input shape.
(el/im (t/complex-tensor [1.0 2.0] [3.0 4.0]))#la/R [:float64 [2] [3.000 4.000]]conj
[a]
Complex conjugate. For complex: negates imaginary parts. For real: returns the input unchanged.
(let [z (t/complex 3.0 4.0)]
(el/im (el/conj z)))-4.0sq
[a]
Element-wise square.
(el/sq (t/column [2 3 4]))#la/R [:float64 [3 1]
[[4.000]
[9.000]
[16.00]]]
sqrt
[a]
Element-wise square root.
(el/sqrt (t/column [4 9 16]))#la/R [:float64 [3 1]
[[2.000]
[3.000]
[4.000]]]
pow
[a exponent]
Element-wise power. Real only.
((el/pow (t/column [2]) 3) 0 0)8.0cbrt
[a]
Element-wise cube root. Real only.
(la/close-scalar? ((el/cbrt (t/column [27])) 0 0) 3.0)trueexp
[a]
Element-wise exponential.
(la/close-scalar? ((el/exp (t/column [0])) 0 0) 1.0)truelog
[a]
Element-wise natural logarithm.
(la/close-scalar? ((el/log (t/column [math/E])) 0 0) 1.0)truelog10
[a]
Element-wise base-10 logarithm. Real only.
(la/close-scalar? ((el/log10 (t/column [100])) 0 0) 2.0)truelog1p
[a]
Element-wise log(1 + x), accurate for small x. Real only.
((el/log1p (t/column [0.0])) 0 0)0.0expm1
[a]
Element-wise exp(x) - 1, accurate for small x. Real only.
((el/expm1 (t/column [0.0])) 0 0)0.0sin
[a]
Element-wise sine.
(la/close-scalar? ((el/sin (t/column [(/ math/PI 2)])) 0 0) 1.0)truecos
[a]
Element-wise cosine.
(la/close-scalar? ((el/cos (t/column [0])) 0 0) 1.0)truetan
[a]
Element-wise tangent. Real only.
(la/close-scalar? ((el/tan (t/column [(/ math/PI 4)])) 0 0) 1.0)trueasin
[a]
Element-wise arcsine. Real only.
((el/asin (t/column [0.5])) 0 0)0.5235987755982989acos
[a]
Element-wise arccosine. Real only.
((el/acos (t/column [0.5])) 0 0)1.0471975511965979atan
[a]
Element-wise arctangent. Real only.
((el/atan (t/column [1.0])) 0 0)0.7853981633974483sinh
[a]
Element-wise hyperbolic sine.
(la/close-scalar? ((el/sinh (t/column [0])) 0 0) 0.0)truecosh
[a]
Element-wise hyperbolic cosine.
(la/close-scalar? ((el/cosh (t/column [0])) 0 0) 1.0)truetanh
[a]
Element-wise hyperbolic tangent. Real only.
(la/close-scalar? ((el/tanh (t/column [0])) 0 0) 0.0)truefloor
[a]
Element-wise floor. Real only.
((el/floor (t/column [2.7])) 0 0)2.0ceil
[a]
Element-wise ceiling. Real only.
((el/ceil (t/column [2.3])) 0 0)3.0round
[a]
Element-wise rounding to nearest integer. Real only.
((el/round (t/column [2.7])) 0 0)3.0clip
[a lo hi]
Element-wise clipping to [lo, hi]. Real only.
(t/flatten (el/clip (t/column [-2 0.5 3]) -1 1))#la/R [:float64 [3] [-1.000 0.5000 1.000]]abs
[a]
Element-wise absolute value (magnitude for complex). Returns a RealTensor.
((el/abs (t/column [-5])) 0 0)5.0Complex magnitude: \(|3+4i| = 5\)
(let [m (el/abs (t/complex-tensor [3.0] [4.0]))]
(la/close-scalar? (double (m 0)) 5.0))truesum
[a]
Sum of all elements. Returns double for real, scalar ComplexTensor for complex.
(el/sum (t/column [1 2 3 4]))10.0Complex sum:
(let [ct (t/complex-tensor [1.0 2.0 3.0] [4.0 5.0 6.0])
s (el/sum ct)]
[(el/re s) (el/im s)])[6.0 15.0]mean
[a]
Mean of all elements. Real only.
(el/mean (t/column [2 4 6]))4.0reduce-*
[a]
Product of all elements. Returns a double. Real only.
(el/reduce-* (t/column [2 3 4]))24.0reduce-max
[a]
Maximum element value. Returns double. Real only.
(el/reduce-max (t/column [3 7 2 9 1]))9.0reduce-min
[a]
Minimum element value. Returns double. Real only.
(el/reduce-min (t/column [3 7 2 9 1]))1.0>
[a b]
Element-wise greater-than. Returns a RealTensor of 0.0/1.0. Real only.
(el/> (t/column [1 5 3]) (t/column [2 4 3]))#la/R [:float64 [3 1]
[[0.000]
[1.000]
[0.000]]]
<
[a b]
Element-wise less-than. Returns a RealTensor of 0.0/1.0. Real only.
(el/< (t/column [1 5 3]) (t/column [2 4 3]))#la/R [:float64 [3 1]
[[1.000]
[0.000]
[0.000]]]
>=
[a b]
Element-wise greater-or-equal. Returns a RealTensor of 0.0/1.0. Real only.
(el/>= (t/column [1 5 3]) (t/column [2 4 3]))#la/R [:float64 [3 1]
[[0.000]
[1.000]
[1.000]]]
<=
[a b]
Element-wise less-or-equal. Returns a RealTensor of 0.0/1.0. Real only.
(el/<= (t/column [1 5 3]) (t/column [2 4 3]))#la/R [:float64 [3 1]
[[1.000]
[0.000]
[1.000]]]
eq
[a b]
Element-wise equality. Returns a RealTensor of 0.0/1.0. Real only.
(el/eq (t/column [1 5 3]) (t/column [2 4 3]))#la/R [:float64 [3 1]
[[0.000]
[0.000]
[1.000]]]
not-eq
[a b]
Element-wise not-equal. Returns a RealTensor of 0.0/1.0. Real only.
(el/not-eq (t/column [1 5 3]) (t/column [2 4 3]))#la/R [:float64 [3 1]
[[1.000]
[1.000]
[0.000]]]
min
[a b]
Element-wise minimum. Real only.
((el/min (t/column [3]) (t/column [5])) 0 0)3.0max
[a b]
Element-wise maximum. Real only.
((el/max (t/column [3]) (t/column [5])) 0 0)5.0argmax
[a]
Index of the maximum element. Returns long. Real only.
(el/argmax (t/column [3 7 2 9 1]))3argmin
[a]
Index of the minimum element. Returns long. Real only.
(el/argmin (t/column [3 7 2 9 1]))4argsort
[a]
[comp a]
Indices that would sort the tensor in ascending order. Returns a Clojure vector of longs. Real only. With comparator: (argsort > a) for descending.
Ascending:
(el/argsort (t/column [3 7 2 9 1]))[4 2 0 1 3]Descending:
(el/argsort > (t/column [3 7 2 9 1]))[3 1 0 2 4]sort
[a]
[comp a]
Sorted copy of the tensor. Returns RealTensor. Real only. With comparator: (sort > a) for descending.
Ascending:
(el/sort (t/column [3 7 2 9 1]))#la/R [:float64 [5] [1.000 2.000 3.000 7.000 9.000]]Descending:
(el/sort > (t/column [3 7 2 9 1]))#la/R [:float64 [5] [9.000 7.000 3.000 2.000 1.000]]scicloj.lalinea.transform
Bridge between Fastmath transforms and La Linea tensors. The FFT takes a real signal and returns a ComplexTensor spectrum.
forward
[signal]
Forward FFT of a real signal. Returns a ComplexTensor of the spectrum.
The input can be a Clojure seq, double[], or dtype-next buffer. The output is a ComplexTensor of shape [n] where n = length of input.
(let [signal [1.0 0.0 0.0 0.0]
spectrum (ft/forward signal)]
(t/complex-shape spectrum))[4]inverse
[spectrum]
Inverse FFT from a ComplexTensor spectrum back to a ComplexTensor signal.
(let [spectrum (ft/forward [1.0 2.0 3.0 4.0])
roundtrip (ft/inverse spectrum)]
(la/close-scalar? (el/re (roundtrip 0)) 1.0))trueinverse-real
[spectrum]
Inverse FFT from a ComplexTensor spectrum, returning only the real part. Useful when you know the result should be purely real.
(let [signal [1.0 2.0 3.0 4.0]
roundtrip (ft/inverse-real (ft/forward signal))]
(la/close-scalar? (roundtrip 0) 1.0))trueforward-complex
[signal]
Forward FFT of a ComplexTensor signal. Returns a ComplexTensor spectrum.
(let [ct (t/complex-tensor-real [1.0 0.0 0.0 0.0])
spectrum (ft/forward-complex ct)]
(t/complex-shape spectrum))[4]dct-forward
[signal]
Forward Discrete Cosine Transform. Real -> real.
(ft/dct-forward [1.0 2.0 3.0 4.0])#la/R [:float64 [4] [5.000 -2.230 0.000 -0.1585]]dct-inverse
[spectrum]
Inverse Discrete Cosine Transform. Real -> real.
(let [signal [1.0 2.0 3.0 4.0]
roundtrip (ft/dct-inverse (ft/dct-forward signal))]
(la/close-scalar? (roundtrip 0) 1.0))truedst-forward
[signal]
Forward Discrete Sine Transform. Real -> real.
(ft/dst-forward [1.0 2.0 3.0 4.0])#la/R [:float64 [4] [4.619 -2.000 1.913 -1.000]]dst-inverse
[spectrum]
Inverse Discrete Sine Transform. Real -> real.
(let [signal [1.0 2.0 3.0 4.0]
roundtrip (ft/dst-inverse (ft/dst-forward signal))]
(la/close-scalar? (roundtrip 0) 1.0))truedht-forward
[signal]
Forward Discrete Hartley Transform. Real -> real.
(ft/dht-forward [1.0 2.0 3.0 4.0])#la/R [:float64 [4] [10.00 -4.000 -2.000 0.000]]dht-inverse
[spectrum]
Inverse Discrete Hartley Transform. Real -> real.
(let [signal [1.0 2.0 3.0 4.0]
roundtrip (ft/dht-inverse (ft/dht-forward signal))]
(la/close-scalar? (roundtrip 0) 1.0))truescicloj.lalinea.tape
Computation DAG recording and memory inspection.
memory-status
[t]
Classify a tensor’s memory backing.
Returns:
:contiguous— backed by a full double[] (fast, mutable):strided— shares a double[] but with non-standard strides (e.g. transpose):lazy— no backing array, recomputes on each access
Works on both real tensors and ComplexTensors.
(tape/memory-status (t/matrix [[1 2] [3 4]])):contiguous(tape/memory-status (la/transpose (t/matrix [[1 2] [3 4]]))):strided(tape/memory-status (el/+ (t/eye 2) (t/eye 2))):lazymemory-relation
[a b]
Classify the memory relationship between two tensors.
Returns:
:shared— same backing double[]:independent— separate backing arrays:unknown-lazy— at least one is lazy; relationship indeterminate
For lazy tensors, the relationship depends on whether the lazy reader reads through to the other tensor’s backing array — but dtype-next does not expose this dependency chain. Use the tape (detect-memory-status) for the full picture.
(let [A (t/matrix [[1 2] [3 4]])]
(tape/memory-relation A (la/transpose A))):shared(tape/memory-relation (t/matrix [[1 0] [0 1]]) (t/matrix [[5 6] [7 8]])):independent(tape/memory-relation (t/matrix [[1 2] [3 4]]) (el/+ (t/eye 2) (t/eye 2))):unknown-lazywith-tape
[& body]
Execute body while recording a computation tape. Returns {:result <body-result> :entries <tape-entries>}.
(def tape-example
(tape/with-tape
(let [A (t/matrix [[1 2] [3 4]])
B (el/scale A 2.0)]
(la/mmul B (la/transpose A)))))(select-keys tape-example [:result :entries]){:result #la/R [:float64 [2 2]
[[10.00 22.00]
[22.00 50.00]]]
,
:entries
[{:id "t1",
:op :t/matrix,
:inputs [{:external true}],
:input-tensors [[[1 2] [3 4]]],
:output #la/R [:float64 [2 2]
[[1.000 2.000]
[3.000 4.000]]]
,
:shape [2 2],
:complex? false}
{:id "t2",
:op :el/scale,
:inputs [{:id "t1"} {:external true}],
:input-tensors [#la/R [:float64 [2 2]
[[1.000 2.000]
[3.000 4.000]]]
2.0],
:output #la/R [:float64 [2 2]
[[2.000 4.000]
[6.000 8.000]]]
,
:shape [2 2],
:complex? false}
{:id "t3",
:op :la/transpose,
:inputs [{:id "t1"}],
:input-tensors [#la/R [:float64 [2 2]
[[1.000 2.000]
[3.000 4.000]]]
],
:output #la/R [:float64 [2 2]
[[1.000 3.000]
[2.000 4.000]]]
,
:shape [2 2],
:complex? false}
{:id "t4",
:op :la/mmul,
:inputs [{:id "t2"} {:id "t3"}],
:input-tensors [#la/R [:float64 [2 2]
[[2.000 4.000]
[6.000 8.000]]]
#la/R [:float64 [2 2]
[[1.000 3.000]
[2.000 4.000]]]
],
:output #la/R [:float64 [2 2]
[[10.00 22.00]
[22.00 50.00]]]
,
:shape [2 2],
:complex? false}]}summary
[tape-result]
Aggregate stats about a tape result.
Returns a map with:
:total— total operations recorded:by-op— count per operation type:by-memory— count per memory status (:reads-through, :shared, :independent)
(tape/summary tape-example){:total 4,
:by-op {:t/matrix 1, :el/scale 1, :la/transpose 1, :la/mmul 1},
:by-memory {:independent 2, :reads-through 1, :shared 1}}origin
[tape-result value]
Walk the tape backwards from a value to build its computation DAG.
Returns a nested map: each node has :id, :op, :shape, and :inputs. Inputs that were not recorded on the tape appear as {:external true}. Shared nodes (DAG diamonds) appear as {:ref <id>} after the first occurrence.
(tape/origin tape-example (:result tape-example)){:id "t4",
:op :la/mmul,
:shape [2 2],
:inputs
[{:id "t2",
:op :el/scale,
:shape [2 2],
:inputs
[{:id "t1", :op :t/matrix, :shape [2 2], :inputs [{:external true}]}
{:external true}]}
{:id "t3", :op :la/transpose, :shape [2 2], :inputs [{:ref "t1"}]}]}mermaid
[tape-result value]
Render the computation DAG for a value as a Mermaid diagram.
Memory status is annotated on each node:
~reads-through (lazy, recomputes on access)=shared (shares backing array with an input)+independent (fresh allocation)
Returns a kind/mermaid value, renderable in notebooks.
Returns a renderable Mermaid diagram.
(tape/mermaid tape-example (:result tape-example))detect-memory-status
[entry]
Classify a tape entry’s output relative to its inputs.
Returns:
:shared— output shares backing array with an input:independent— output has its own backing array (fresh allocation):reads-through— output has no backing array; reads from inputs on access
Classifies a tape entry’s output relative to its inputs: :reads-through, :shared, or :independent.
(mapv tape/detect-memory-status (:entries tape-example))[:independent :reads-through :shared :independent]scicloj.lalinea.grad
Reverse-mode automatic differentiation on the computation tape.
grad
[tape-result target wrt]
Gradient of a scalar w.r.t. one or more inputs.
tape-result — map returned by tape/with-tape target — scalar output (must be on the tape) wrt — input tensor, or vector of input tensors
For a single input, returns its gradient tensor directly. For a vector of inputs, returns a map {input gradient}.
Example: clojure (let [A (t/matrix [[1 2] [3 4]]) tape-result (tape/with-tape (la/trace (la/mmul A A)))] (grad/grad tape-result (:result tape-result) A))
(let [A (t/matrix [[1 2] [3 4]])
tape-result (tape/with-tape
(la/trace (la/mmul (la/transpose A) A)))]
(la/close? (grad/grad tape-result
(:result tape-result) A)
(el/scale A 2)))truescicloj.lalinea.vis
SVG and image helpers for visual linear algebra.
arrow-plot
[arrows opts]
Render 2D vectors as arrows on an SVG grid.
arrows is a sequence of maps, each with: :xy — [dx dy] displacement vector (required) :color — CSS color string (required) :label — text label (optional) :from — [fx fy] origin offset, default [0 0] (optional) :dashed? — dashed stroke (optional)
opts is a map with: :width — SVG width in pixels, default 600 (optional)
(vis/arrow-plot [{:xy [2 1] :color "#2266cc" :label "u"}
{:xy [-1 1.5] :color "#cc4422" :label "v"}]
{:width 600})graph-plot
[positions edges opts]
Render a graph as an SVG diagram with nodes and edges.
positions is a vector of [x y] coordinates for each node. edges is a sequence of [i j] index pairs. opts is a map with: :width — SVG width in pixels, default 300 (optional) :labels — vector of node labels, default [“0” “1” …] (optional) :node-colors — vector of CSS colors per node (optional) :edge-highlight — set of [i j] pairs to highlight in red (optional)
(vis/graph-plot [[0 0] [1 0] [0.5 0.87]]
[[0 1] [1 2] [2 0]]
{:width 600 :labels ["A" "B" "C"]})matrix->gray-image
[m]
Convert a numeric [h w] matrix to a [h w 3] uint8 grayscale tensor suitable for display as an image. Values are clamped to [0, 255].
(let [m (t/compute-tensor [200 200]
(fn [r c] (* 255.0 (/ (+ r c) 400.0)))
:float64)]
(bufimg/tensor->image (vis/matrix->gray-image m)))
extract-channel
[img ch]
Extract a single channel from an [h w c] image tensor and return it as a [h w 3] grayscale tensor (the channel replicated three times).
(let [img (t/compute-tensor [200 200 3]
(fn [r c ch]
(case (int ch) 0 (int (* 255 (/ r 200.0))) 1 128 2 64))
:uint8)]
(bufimg/tensor->image (vis/extract-channel img 0)))