Use this file to discover all available pages before exploring further.
Tensors are the foundation of every Clorch computation. Each tensor is a multidimensional array backed by a native LibTorch object allocated outside the JVM heap. Clorch exposes the full LibTorch surface through the clorch.torch namespace, so every operation you know from PyTorch maps directly onto an idiomatic Clojure call. Tensor storage can live on CPU or CUDA VRAM, and any tensor whose :requires-grad flag is set participates automatically in Clorch’s autodiff graph.
tensor throws IllegalArgumentException if data is nil or an empty collection. Every element is cast to the target dtype at construction time, so passing integers with {:dtype :float32} is safe.
All four arithmetic operators broadcast scalars automatically:
(def a (t/tensor [1 2 3]))(def b (t/tensor [4 5 6]))(t/add a b) ;; → [5 7 9](t/sub a b) ;; → [-3 -3 -3](t/mul a b) ;; → [4 10 18](t/div a b) ;; → [0.25 0.4 0.5];; Scalar broadcasting(t/add a 10) ;; → [11 12 13](t/mul b 2.0) ;; → [8.0 10.0 12.0]
Clorch exposes the complete set of LibTorch pointwise math functions. Below is the full reference — each function takes a tensor and returns a new tensor of the same shape.
(def v (t/tensor [1 2 3]))(t/unsqueeze v 0) ;; [1×3](t/unsqueeze v 1) ;; [3×1];; Expand a [1×3] to [4×3] without allocating new memory(t/expand (t/unsqueeze v 0) [4 3]);; Repeat tiles the data (allocates new memory)(t/tile v [3]) ;; [1 2 3 1 2 3 1 2 3](t/repeat v [2]) ;; repeat elements
(def a (t/ones [2 1]))(def b (t/ones [2 1]))(t/cat [a b] 1) ;; [2×2] — concatenate along existing dim(t/stack [a b] 0) ;; [2×2×1] — concatenate along a new dim(def x (t/arange 10))(t/split x 3 0) ;; [[0 1 2] [3 4 5] [6 7 8] [9]] — equal-size splits(t/chunk x 4 0) ;; 4 even chunks(t/unbind x 0) ;; sequence of scalar tensors along dim 0
(def m (t/randn [2 3]))(t/transpose m 0 1) ;; [3×2] — swap two dims(t/T m) ;; [3×2] — shorthand for last two dims(t/swapaxes m 0 1) ;; [3×2] — alias for transpose(def cube (t/randn [2 3 4]))(t/permute cube [2 0 1]) ;; [4×2×3] — arbitrary reordering(t/movedim cube 0 2) ;; [3×4×2] — move dim 0 to position 2
ix is Clorch’s ergonomic indexer that mirrors Python’s [] syntax. It accepts integers, Clojure ranges, :_ for “all elements”, keyword :... for ellipsis, and nested vectors for advanced indexing. Full slicing documentation is on the Advanced Slicing page.
(def m (t/arange 12))(def M (t/reshape m [3 4]));; Basic integer indexing(t/ix M 0) ;; first row → [0 1 2 3](t/ix M 1 2) ;; element at row 1, col 2 → 6;; Range slices: [start end] (exclusive end)(t/ix M :_ [1 3]) ;; all rows, cols 1..2;; select: pick a single index along a dimension(t/select M 0 1) ;; row 1;; index-select: pick multiple indices along a dimension(t/index-select M 0 (t/tensor [0 2] {:dtype :int64})) ;; rows 0 and 2;; masked-fill: fill where a boolean mask is true(t/masked-fill M (t/eq M 5) -1.0) ;; replace 5 with -1;; take-along-dim: gather values using an index tensor(t/take-along-dim M (t/tensor [[0 1 0 1]] {:dtype :int64}) 0);; scatter-reduce: reduce-scatter into a target tensor(t/scatter-reduce (t/zeros [3 4]) 0 (t/tensor [[0 1 2 0]] {:dtype :int64}) (t/ones [1 4]) "sum")
The clorch.torch namespace exposes the full torch.linalg surface as linalg- prefixed functions.
(def A (t/randn [3 3]));; Decompositions(t/linalg-cholesky A) ;; lower-triangular Cholesky factor L(t/linalg-svd A) ;; [U S Vh] — full singular value decomp(t/linalg-qr A) ;; [Q R](t/linalg-eig A) ;; [eigenvalues eigenvectors](t/linalg-eigh A) ;; [eigenvalues eigenvectors] (symmetric/Hermitian);; Inverses and determinants(t/linalg-inv A) ;; matrix inverse(t/linalg-det A) ;; determinant(t/linalg-pinv A) ;; Moore-Penrose pseudo-inverse;; Solving linear systems(def b (t/randn [3 1]))(t/linalg-solve A b) ;; solve Ax = b(t/linalg-lstsq A b) ;; least-squares solution;; Norms(t/linalg-norm A) ;; Frobenius norm (default)(t/linalg-norm A 2) ;; spectral norm;; Matrix functions(t/matrix-exp A) ;; matrix exponential(t/linalg-matrix-power A 3) ;; integer matrix power
Clorch picks up the best available LibTorch backend when clorch.torch loads. Move tensors and models to a device explicitly:
(require '[clorch.cuda :as cuda] '[clorch.nn :as nn])(def device (if (cuda/available?) :cuda :cpu));; Create directly on device(def x (t/randn [32 128] {:device device}));; Move an existing tensor(def y (t/to existing-tensor device));; Move a model (all parameters migrate atomically)(nn/to model device)
A model and its input tensors must reside on the same device. Passing a CUDA tensor to a CPU model — or vice versa — throws a runtime error from LibTorch.
All comparison functions return a :bool tensor of the same shape:
(def a (t/tensor [1 2 3]))(def b (t/tensor [3 2 1]))(t/eq a b) ;; [false true false](t/ne a b) ;; [true false true](t/gt a b) ;; [false false true](t/lt a b) ;; [true false false](t/ge a 2) ;; [false true true](t/le a 2) ;; [true true false]
Sample one or more indices according to a probability distribution:
;; Draw 1 token from a probability vector(t/multinomial (t/tensor [0.1 0.8 0.1]) 1);; Draw 3 samples with replacement from a batch row(t/multinomial (t/tensor [[0.2 0.5 0.3]]) 3)
top-p implements the nucleus sampling algorithm used in autoregressive text generation. It applies softmax, accumulates sorted probabilities, masks out tokens beyond the probability threshold p, renormalises, and draws one sample:
;; logits tensor of shape [batch seq] or [1 vocab](t/top-p (t/tensor [[0.1 0.8 0.05 0.05]]) 0.9);; → [[1]] — index of the sampled token
top-p expects raw logits (pre-softmax). The function applies softmax internally before computing the cumulative distribution.
Clorch provides first-class RoPE support for transformer models. precompute-rope-freqs generates the cosine and sine embedding tables once, then apply-rope rotates query and key tensors in-place.
;; Precompute embedding tables for dim=64, seq-len=2048(def [cos-emb sin-emb] (t/precompute-rope-freqs 64 2048));; optionally pass :theta for a custom base frequency:;; (t/precompute-rope-freqs 64 2048 :theta 500000.0);; Apply to query/key tensors of shape [batch seq heads dim](def q (t/randn [1 16 8 64]))(def q-rotated (t/apply-rope q cos-emb sin-emb))
Clorch supports both eager-mode checkpoint save/load and TorchScript JIT modules.
Eager checkpoint: save and load
(require '[clorch.torch :as t]);; Persist a tensor(t/save (t/ones [2 2]) "weights.pt");; Reload into an existing tensor(def w (t/ones [2 2]))(t/load w "weights.pt")
save and load also accept nn/Module and optimizer objects.
TorchScript JIT: jit-save, jit-load, jit-forward
;; Load a TorchScript module exported from Python(def jit-mod (t/jit-load "traced_model.pt"));; Load onto CUDA(def jit-mod-gpu (t/jit-load "traced_model.pt" {:device :cuda}));; Run inference(def output (t/jit-forward jit-mod [(t/ones [1 3 224 224])]));; Re-save the module(t/jit-save jit-mod "traced_model_copy.pt")
jit-forward wraps the input tensors in IValueVector automatically and unwraps the returned IValue back to a tensor.
jit-trace and jit-script are not available at the Clojure level — tracing and scripting must be done in Python and the resulting .pt file loaded into Clorch with jit-load.