Foundry/docs/tensor.md

1243 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# tensor
Tensor operations with automatic differentiation. Python counterpart: PyTorch core functionality.
**Header:** `tensor/tensor.h`
**Source:** `tensor/tensor.c`
**Status:** ✅ Verified - 141 tests passing (100% PyTorch parity including sparse tensors)
---
## Overview
The tensor module provides:
- N-dimensional tensor storage
- Element-wise and matrix operations
- Automatic differentiation (autograd)
- Broadcasting support
- Multiple data types (F32, F64, F16, BF16, I32, I64)
---
## Quick Start
```c
#include "tensor/tensor.h"
// Create tensors
int64_t shape[] = {32, 64};
tm_tensor* a = tm_randn(shape, 2, TM_F32);
tm_tensor* b = tm_randn(shape, 2, TM_F32);
// Enable gradient tracking
tm_set_requires_grad(a, true);
tm_set_requires_grad(b, true);
// Operations
tm_tensor* c = tm_add(a, b);
tm_tensor* d = tm_relu(c);
tm_tensor* loss = tm_mean(d, -1, false);
// Backpropagation
tm_backward(loss);
// Access gradients
float* grad_a = tm_data_f32(a->grad);
// Cleanup
tm_free(loss);
tm_free(d);
tm_free(c);
tm_free(b);
tm_free(a);
```
---
## Data Types
| Type | Constant | Size | Description |
|------|----------|------|-------------|
| float32 | `TM_F32` | 4 bytes | Default, most operations |
| float64 | `TM_F64` | 8 bytes | High precision |
| float16 | `TM_F16` | 2 bytes | Memory efficient |
| bfloat16 | `TM_BF16` | 2 bytes | Training efficient |
| int32 | `TM_I32` | 4 bytes | Indices |
| int64 | `TM_I64` | 8 bytes | Large indices |
---
## API Reference
### Tensor Creation
#### tm_empty
```c
tm_tensor* tm_empty(int64_t* shape, int ndim, tm_dtype dtype);
```
Create tensor with uninitialized data.
#### tm_zeros
```c
tm_tensor* tm_zeros(int64_t* shape, int ndim, tm_dtype dtype);
```
Create tensor filled with zeros.
#### tm_ones
```c
tm_tensor* tm_ones(int64_t* shape, int ndim, tm_dtype dtype);
```
Create tensor filled with ones.
#### tm_full
```c
tm_tensor* tm_full(int64_t* shape, int ndim, tm_dtype dtype, double value);
```
Create tensor filled with specified value.
#### tm_randn
```c
tm_tensor* tm_randn(int64_t* shape, int ndim, tm_dtype dtype);
```
Create tensor with random normal values (mean=0, std=1).
#### tm_rand
```c
tm_tensor* tm_rand(int64_t* shape, int ndim, tm_dtype dtype);
```
Create tensor with random uniform values [0, 1).
#### tm_from_data
```c
tm_tensor* tm_from_data(void* data, int64_t* shape, int ndim, tm_dtype dtype);
```
Create tensor from existing data (does not copy).
#### tm_clone
```c
tm_tensor* tm_clone(tm_tensor* t);
```
Deep copy tensor.
#### tm_zeros_like
```c
tm_tensor* tm_zeros_like(tm_tensor* t);
```
Create zeros tensor with same shape as input.
#### tm_ones_like
```c
tm_tensor* tm_ones_like(tm_tensor* t);
```
Create ones tensor with same shape as input.
#### tm_arange
```c
tm_tensor* tm_arange(double start, double end, double step, tm_dtype dtype);
```
Create tensor with range of values [start, end) with step.
#### tm_eye
```c
tm_tensor* tm_eye(int64_t n, tm_dtype dtype);
```
Create n×n identity matrix.
#### tm_linspace
```c
tm_tensor* tm_linspace(double start, double end, int64_t steps, tm_dtype dtype);
```
Create linearly spaced values from start to end.
#### tm_randint
```c
tm_tensor* tm_randint(int64_t low, int64_t high, int64_t* shape, int ndim);
```
Create tensor with random integers in [low, high).
#### tm_full_like
```c
tm_tensor* tm_full_like(tm_tensor* t, double value);
```
Create tensor filled with value, same shape as input.
#### tm_empty_like
```c
tm_tensor* tm_empty_like(tm_tensor* t);
```
Create uninitialized tensor with same shape as input.
#### tm_rand_like
```c
tm_tensor* tm_rand_like(tm_tensor* t);
```
Create random uniform tensor with same shape as input.
#### tm_randn_like
```c
tm_tensor* tm_randn_like(tm_tensor* t);
```
Create random normal tensor with same shape as input.
---
### Memory Management
#### tm_retain
```c
tm_tensor* tm_retain(tm_tensor* t);
```
Increment reference count.
#### tm_release / tm_free
```c
void tm_release(tm_tensor* t);
#define tm_free(t) tm_release(t)
```
Decrement reference count, free if zero.
---
### Accessors
#### tm_get_f32 / tm_set_f32
```c
float tm_get_f32(tm_tensor* t, int64_t i);
void tm_set_f32(tm_tensor* t, int64_t i, float val);
```
Get/set element by flat index.
#### tm_data_f32
```c
float* tm_data_f32(tm_tensor* t);
```
Get pointer to data.
#### tm_numel
```c
int64_t tm_numel(tm_tensor* t);
```
Get total number of elements.
#### tm_ndim
```c
int tm_ndim(tm_tensor* t);
```
Get number of dimensions.
#### tm_size
```c
int64_t tm_size(tm_tensor* t, int dim);
```
Get size of dimension.
---
### Shape Operations
#### tm_reshape
```c
tm_tensor* tm_reshape(tm_tensor* t, int64_t* shape, int ndim);
```
Reshape tensor (returns view if possible).
#### tm_transpose
```c
tm_tensor* tm_transpose(tm_tensor* t, int dim0, int dim1);
```
Swap two dimensions.
#### tm_squeeze
```c
tm_tensor* tm_squeeze(tm_tensor* t, int dim);
```
Remove dimension of size 1.
#### tm_unsqueeze
```c
tm_tensor* tm_unsqueeze(tm_tensor* t, int dim);
```
Add dimension of size 1.
#### tm_contiguous
```c
tm_tensor* tm_contiguous(tm_tensor* t);
```
Ensure data is contiguous in memory.
#### tm_view
```c
tm_tensor* tm_view(tm_tensor* t, int64_t* shape, int ndim);
```
View tensor with new shape (alias for reshape).
#### tm_permute
```c
tm_tensor* tm_permute(tm_tensor* t, int* dims, int ndim);
```
Permute dimensions (generalized transpose).
#### tm_flatten
```c
tm_tensor* tm_flatten(tm_tensor* t, int start_dim, int end_dim);
```
Flatten dimensions from start_dim to end_dim.
#### tm_select
```c
tm_tensor* tm_select(tm_tensor* t, int dim, int64_t index);
```
Select along dimension (reduces ndim by 1).
#### tm_cat
```c
tm_tensor* tm_cat(tm_tensor** tensors, int num_tensors, int dim);
```
Concatenate tensors along dimension.
#### tm_stack
```c
tm_tensor* tm_stack(tm_tensor** tensors, int num_tensors, int dim);
```
Stack tensors along new dimension.
#### tm_split
```c
tm_tensor** tm_split(tm_tensor* t, int64_t split_size, int dim, int* num_chunks);
```
Split tensor into chunks along dimension.
#### tm_chunk
```c
tm_tensor** tm_chunk(tm_tensor* t, int n, int dim, int* actual);
```
Split tensor into n equal chunks along dimension.
#### tm_expand
```c
tm_tensor* tm_expand(tm_tensor* t, int64_t* shape, int ndim);
```
Expand tensor to larger shape (broadcasting).
#### tm_repeat
```c
tm_tensor* tm_repeat(tm_tensor* t, int64_t* sizes, int ndim);
```
Repeat tensor along dimensions.
#### tm_narrow
```c
tm_tensor* tm_narrow(tm_tensor* t, int dim, int64_t start, int64_t length);
```
Narrow tensor along dimension (slice view).
#### tm_flip
```c
tm_tensor* tm_flip(tm_tensor* t, int* dims, int ndim);
```
Reverse tensor along specified dimensions.
#### tm_roll
```c
tm_tensor* tm_roll(tm_tensor* t, int64_t shift, int dim);
```
Roll tensor elements along dimension.
#### tm_t
```c
tm_tensor* tm_t(tm_tensor* t);
```
Transpose 2D tensor (alias for transpose(0, 1)).
---
### Element-wise Operations
All element-wise operations support broadcasting.
| Function | Operation |
|----------|-----------|
| `tm_add(a, b)` | a + b |
| `tm_sub(a, b)` | a - b |
| `tm_mul(a, b)` | a * b |
| `tm_div(a, b)` | a / b |
| `tm_add_scalar(a, s)` | a + s |
| `tm_sub_scalar(a, s)` | a - s |
| `tm_mul_scalar(a, s)` | a * s |
| `tm_div_scalar(a, s)` | a / s |
| `tm_neg(a)` | -a |
| `tm_abs(a)` | \|a\| |
| `tm_exp(a)` | exp(a) |
| `tm_log(a)` | log(a) |
| `tm_sqrt(a)` | sqrt(a) |
| `tm_rsqrt(a)` | 1/sqrt(a) |
| `tm_reciprocal(a)` | 1/a |
| `tm_pow(a, n)` | a^n |
| `tm_sin(a)` | sin(a) |
| `tm_cos(a)` | cos(a) |
| `tm_tan(a)` | tan(a) |
| `tm_asin(a)` | arcsin(a) |
| `tm_acos(a)` | arccos(a) |
| `tm_atan(a)` | arctan(a) |
| `tm_sinh(a)` | sinh(a) |
| `tm_cosh(a)` | cosh(a) |
| `tm_tanh(a)` | tanh(a) |
| `tm_exp2(a)` | 2^a |
| `tm_expm1(a)` | exp(a) - 1 |
| `tm_log2(a)` | log2(a) |
| `tm_log10(a)` | log10(a) |
| `tm_log1p(a)` | log(1 + a) |
| `tm_floor(a)` | floor(a) |
| `tm_ceil(a)` | ceil(a) |
| `tm_round(a)` | round(a) |
| `tm_trunc(a)` | truncate(a) |
| `tm_sign(a)` | sign(a) |
| `tm_relu(a)` | max(0, a) |
| `tm_leaky_relu(a, slope)` | Leaky ReLU |
| `tm_elu(a, alpha)` | ELU activation |
| `tm_sigmoid(a)` | 1/(1+exp(-a)) |
| `tm_gelu(a)` | GELU activation |
| `tm_silu(a)` | x * sigmoid(x) (SwiGLU) |
| `tm_hardswish(a)` | x * relu6(x+3) / 6 |
| `tm_hardtanh(a, min, max)` | Clamped linear |
| `tm_softplus(a, beta, thresh)` | Smooth ReLU |
| `tm_clamp(a, min, max)` | Clamp values |
| `tm_maximum(a, b)` | Element-wise max |
| `tm_minimum(a, b)` | Element-wise min |
| `tm_where(cond, a, b)` | Conditional select |
| `tm_masked_fill(t, mask, val)` | Fill where mask is true |
| `tm_lerp(a, b, w)` | Linear interpolation |
| `tm_addcmul(t, a, b, val)` | t + val * a * b |
| `tm_addcdiv(t, a, b, val)` | t + val * a / b |
---
### Matrix Operations
#### tm_matmul
```c
tm_tensor* tm_matmul(tm_tensor* a, tm_tensor* b);
```
Matrix multiplication. Supports 2D and batched 3D tensors.
#### tm_bmm
```c
tm_tensor* tm_bmm(tm_tensor* a, tm_tensor* b);
```
Batched matrix multiplication.
#### tm_mm
```c
tm_tensor* tm_mm(tm_tensor* a, tm_tensor* b);
```
2D matrix multiplication (alias for matmul).
#### tm_addmm
```c
tm_tensor* tm_addmm(tm_tensor* t, tm_tensor* a, tm_tensor* b, float beta, float alpha);
```
Additive matrix multiply: beta*t + alpha*(a @ b).
#### tm_dot
```c
tm_tensor* tm_dot(tm_tensor* a, tm_tensor* b);
```
Dot product of 1D tensors.
#### tm_mv
```c
tm_tensor* tm_mv(tm_tensor* mat, tm_tensor* vec);
```
Matrix-vector multiplication.
#### tm_outer
```c
tm_tensor* tm_outer(tm_tensor* a, tm_tensor* b);
```
Outer product of 1D tensors.
#### tm_inner
```c
tm_tensor* tm_inner(tm_tensor* a, tm_tensor* b);
```
Inner product of tensors.
#### tm_inverse
```c
tm_tensor* tm_inverse(tm_tensor* t);
```
Matrix inverse using Gauss-Jordan elimination.
#### tm_det
```c
tm_tensor* tm_det(tm_tensor* t);
```
Matrix determinant using LU decomposition.
#### tm_svd
```c
tm_tensor** tm_svd(tm_tensor* t, int* num_outputs);
```
Singular value decomposition. Returns array of 3 tensors: U, S, V.
#### tm_eig
```c
tm_tensor* tm_eig(tm_tensor* t);
```
Eigenvalues of a square matrix using QR iteration.
---
### Comparison Operations
| Function | Operation |
|----------|-----------|
| `tm_eq(a, b)` | a == b (element-wise) |
| `tm_ne(a, b)` | a != b (element-wise) |
| `tm_lt(a, b)` | a < b (element-wise) |
| `tm_le(a, b)` | a <= b (element-wise) |
| `tm_gt(a, b)` | a > b (element-wise) |
| `tm_ge(a, b)` | a >= b (element-wise) |
| `tm_equal(a, b)` | All elements equal (bool) |
| `tm_allclose(a, b, rtol, atol)` | Approximately equal |
| `tm_isnan(a)` | Check for NaN |
| `tm_isinf(a)` | Check for Inf |
| `tm_isfinite(a)` | Check for finite |
| `tm_logical_and(a, b)` | Logical AND |
| `tm_logical_or(a, b)` | Logical OR |
| `tm_logical_not(a)` | Logical NOT |
| `tm_logical_xor(a, b)` | Logical XOR |
---
### Indexing Operations
#### tm_gather
```c
tm_tensor* tm_gather(tm_tensor* t, int dim, tm_tensor* idx);
```
Gather elements by index along dimension.
#### tm_scatter
```c
tm_tensor* tm_scatter(tm_tensor* t, int dim, tm_tensor* idx, tm_tensor* src);
```
Scatter elements by index along dimension.
#### tm_scatter_add
```c
tm_tensor* tm_scatter_add(tm_tensor* t, int dim, tm_tensor* idx, tm_tensor* src);
```
Scatter with addition.
#### tm_index_select
```c
tm_tensor* tm_index_select(tm_tensor* t, int dim, tm_tensor* idx);
```
Select elements by index along dimension.
#### tm_masked_select
```c
tm_tensor* tm_masked_select(tm_tensor* t, tm_tensor* mask);
```
Select elements where mask is true.
#### tm_take
```c
tm_tensor* tm_take(tm_tensor* t, tm_tensor* idx);
```
Take elements by flat index.
#### tm_index_fill
```c
tm_tensor* tm_index_fill(tm_tensor* t, int dim, tm_tensor* idx, float val);
```
Fill at indices with value.
#### tm_index_copy
```c
tm_tensor* tm_index_copy(tm_tensor* t, int dim, tm_tensor* idx, tm_tensor* src);
```
Copy to indices.
#### tm_index_add
```c
tm_tensor* tm_index_add(tm_tensor* t, int dim, tm_tensor* idx, tm_tensor* src);
```
Add at indices.
#### tm_nonzero
```c
tm_tensor* tm_nonzero(tm_tensor* t);
```
Indices of non-zero elements.
---
### Reductions
#### tm_sum
```c
tm_tensor* tm_sum(tm_tensor* t, int dim, bool keepdim);
```
Sum over dimension. `dim=-1` means sum all elements.
#### tm_mean
```c
tm_tensor* tm_mean(tm_tensor* t, int dim, bool keepdim);
```
Mean over dimension.
#### tm_max / tm_min
```c
tm_tensor* tm_max(tm_tensor* t, int dim, bool keepdim);
tm_tensor* tm_min(tm_tensor* t, int dim, bool keepdim);
```
Max/min over dimension.
#### tm_argmax / tm_argmin
```c
tm_tensor* tm_argmax(tm_tensor* t, int dim, bool keepdim);
tm_tensor* tm_argmin(tm_tensor* t, int dim, bool keepdim);
```
Index of max/min value.
#### tm_logsumexp
```c
tm_tensor* tm_logsumexp(tm_tensor* t, int dim, bool keepdim);
```
Log-sum-exp (numerically stable).
#### tm_prod
```c
tm_tensor* tm_prod(tm_tensor* t, int dim, bool keepdim);
```
Product over dimension.
#### tm_cumsum
```c
tm_tensor* tm_cumsum(tm_tensor* t, int dim);
```
Cumulative sum along dimension.
#### tm_cumprod
```c
tm_tensor* tm_cumprod(tm_tensor* t, int dim);
```
Cumulative product along dimension.
#### tm_std / tm_var
```c
tm_tensor* tm_std(tm_tensor* t, int dim, bool keepdim, bool unbiased);
tm_tensor* tm_var(tm_tensor* t, int dim, bool keepdim, bool unbiased);
```
Standard deviation and variance.
#### tm_any / tm_all
```c
tm_tensor* tm_any(tm_tensor* t, int dim, bool keepdim);
tm_tensor* tm_all(tm_tensor* t, int dim, bool keepdim);
```
Any/all true along dimension.
#### tm_norm
```c
tm_tensor* tm_norm(tm_tensor* t, float p, int dim, bool keepdim);
```
Lp norm along dimension.
#### tm_count_nonzero
```c
tm_tensor* tm_count_nonzero(tm_tensor* t, int dim);
```
Count non-zero elements.
---
### Neural Network Operations
#### tm_softmax
```c
tm_tensor* tm_softmax(tm_tensor* t, int dim);
```
Softmax over dimension.
#### tm_log_softmax
```c
tm_tensor* tm_log_softmax(tm_tensor* t, int dim);
```
Log softmax (numerically stable).
#### tm_layer_norm
```c
tm_tensor* tm_layer_norm(tm_tensor* t, tm_tensor* weight, tm_tensor* bias, float eps);
```
Layer normalization.
#### tm_embedding
```c
tm_tensor* tm_embedding(tm_tensor* weight, tm_tensor* indices);
```
Embedding lookup.
#### tm_dropout
```c
tm_tensor* tm_dropout(tm_tensor* t, float p, bool training);
```
Dropout (training mode).
#### tm_rms_norm
```c
tm_tensor* tm_rms_norm(tm_tensor* t, tm_tensor* weight, float eps);
```
RMS normalization (used in Llama, modern LLMs).
#### tm_linear
```c
tm_tensor* tm_linear(tm_tensor* x, tm_tensor* weight, tm_tensor* bias);
```
Linear layer: x @ weight.T + bias.
#### tm_triu / tm_tril
```c
tm_tensor* tm_triu(tm_tensor* t, int diagonal);
tm_tensor* tm_tril(tm_tensor* t, int diagonal);
```
Upper/lower triangular matrix (for causal masks).
#### tm_batch_norm
```c
tm_tensor* tm_batch_norm(tm_tensor* t, tm_tensor* weight, tm_tensor* bias,
tm_tensor* running_mean, tm_tensor* running_var,
bool training, float momentum, float eps);
```
Batch normalization.
#### tm_group_norm
```c
tm_tensor* tm_group_norm(tm_tensor* t, int num_groups, tm_tensor* weight,
tm_tensor* bias, float eps);
```
Group normalization.
#### tm_instance_norm
```c
tm_tensor* tm_instance_norm(tm_tensor* t, tm_tensor* weight, tm_tensor* bias,
float eps);
```
Instance normalization.
#### tm_scaled_dot_product_attention
```c
tm_tensor* tm_scaled_dot_product_attention(tm_tensor* Q, tm_tensor* K, tm_tensor* V,
tm_tensor* attn_mask, float dropout_p,
bool is_causal);
```
Scaled dot-product attention with optional causal mask.
#### tm_split_heads / tm_merge_heads
```c
tm_tensor* tm_split_heads(tm_tensor* x, int num_heads);
tm_tensor* tm_merge_heads(tm_tensor* x);
```
Multi-head attention helpers.
#### tm_conv1d
```c
tm_tensor* tm_conv1d(tm_tensor* input, tm_tensor* weight, tm_tensor* bias,
int stride, int padding, int dilation, int groups);
```
1D convolution with full parameter support.
#### tm_conv2d
```c
tm_tensor* tm_conv2d(tm_tensor* input, tm_tensor* weight, tm_tensor* bias,
int stride_h, int stride_w, int padding_h, int padding_w,
int dilation_h, int dilation_w, int groups);
```
2D convolution with full parameter support.
#### tm_avg_pool1d / tm_max_pool1d
```c
tm_tensor* tm_avg_pool1d(tm_tensor* input, int kernel_size, int stride, int padding);
tm_tensor* tm_max_pool1d(tm_tensor* input, int kernel_size, int stride, int padding);
```
1D pooling operations.
#### tm_avg_pool2d / tm_max_pool2d
```c
tm_tensor* tm_avg_pool2d(tm_tensor* input, int kernel_h, int kernel_w,
int stride_h, int stride_w, int padding_h, int padding_w);
tm_tensor* tm_max_pool2d(tm_tensor* input, int kernel_h, int kernel_w,
int stride_h, int stride_w, int padding_h, int padding_w);
```
2D pooling operations.
#### tm_adaptive_avg_pool1d / tm_adaptive_avg_pool2d
```c
tm_tensor* tm_adaptive_avg_pool1d(tm_tensor* input, int output_size);
tm_tensor* tm_adaptive_avg_pool2d(tm_tensor* input, int output_h, int output_w);
```
Adaptive average pooling (output size specified).
---
### Loss Functions
#### tm_cross_entropy
```c
tm_tensor* tm_cross_entropy(tm_tensor* logits, tm_tensor* targets);
```
Cross-entropy loss with integer targets.
#### tm_cross_entropy_soft
```c
tm_tensor* tm_cross_entropy_soft(tm_tensor* logits, tm_tensor* targets);
```
Cross-entropy loss with soft targets.
#### tm_mse_loss
```c
tm_tensor* tm_mse_loss(tm_tensor* pred, tm_tensor* target);
```
Mean squared error loss.
#### tm_l1_loss
```c
tm_tensor* tm_l1_loss(tm_tensor* pred, tm_tensor* target);
```
L1 (Mean Absolute Error) loss.
#### tm_smooth_l1_loss
```c
tm_tensor* tm_smooth_l1_loss(tm_tensor* pred, tm_tensor* target, float beta);
```
Smooth L1 (Huber) loss. Uses quadratic for small errors, linear for large.
#### tm_nll_loss
```c
tm_tensor* tm_nll_loss(tm_tensor* log_probs, tm_tensor* targets);
```
Negative log likelihood loss. Expects log probabilities as input.
#### tm_kl_div
```c
tm_tensor* tm_kl_div(tm_tensor* input, tm_tensor* target);
```
KL divergence loss. Input is log probabilities, target is probabilities.
#### tm_binary_cross_entropy
```c
tm_tensor* tm_binary_cross_entropy(tm_tensor* pred, tm_tensor* target);
```
Binary cross entropy loss for binary classification.
#### tm_cosine_embedding_loss
```c
tm_tensor* tm_cosine_embedding_loss(tm_tensor* x1, tm_tensor* x2, tm_tensor* y, float margin);
```
Cosine embedding loss. y=1 encourages similarity, y=-1 encourages dissimilarity.
#### tm_triplet_margin_loss
```c
tm_tensor* tm_triplet_margin_loss(tm_tensor* anchor, tm_tensor* positive, tm_tensor* negative, float margin, float p);
```
Triplet margin loss for metric learning. Encourages anchor-positive distance < anchor-negative distance.
#### tm_cross_entropy_label_smooth
```c
tm_tensor* tm_cross_entropy_label_smooth(tm_tensor* logits, tm_tensor* targets, float smoothing);
```
Cross-entropy loss with label smoothing. Reduces overconfidence.
---
### Autograd
#### tm_set_requires_grad
```c
void tm_set_requires_grad(tm_tensor* t, bool requires);
```
Enable/disable gradient tracking.
#### tm_backward
```c
void tm_backward(tm_tensor* loss);
```
Compute gradients via backpropagation.
#### tm_zero_grad
```c
void tm_zero_grad(tm_tensor** params, int n);
```
Zero gradients for all parameters.
#### tm_detach
```c
tm_tensor* tm_detach(tm_tensor* t);
```
Detach from computation graph.
#### tm_no_grad_begin / tm_no_grad_end
```c
bool tm_no_grad_begin(void);
void tm_no_grad_end(bool prev);
```
Temporarily disable gradient tracking.
#### tm_retain_grad
```c
void tm_retain_grad(tm_tensor* t);
```
Retain gradient for non-leaf tensors. By default, gradients are only kept for leaf tensors.
#### tm_grad
```c
tm_tensor** tm_grad(tm_tensor** outputs, int num_outputs, tm_tensor** inputs, int num_inputs, tm_tensor** grad_outputs);
```
Compute gradients explicitly. Returns array of gradients for each input.
#### tm_checkpoint
```c
tm_tensor* tm_checkpoint(tm_tensor* (*fn)(tm_tensor**, int, void*), tm_tensor** inputs, int num_inputs, void* ctx);
```
Gradient checkpointing for memory-efficient training. Recomputes forward pass during backward.
---
### Higher-Order Gradients
#### tm_hessian
```c
tm_tensor* tm_hessian(tm_tensor** params, int num_params,
tm_tensor* (*loss_fn)(tm_tensor**, int, void*), void* ctx);
```
Compute Hessian matrix of loss w.r.t. parameters using finite differences. Returns n x n matrix.
#### tm_hvp
```c
tm_tensor* tm_hvp(tm_tensor** params, int num_params, tm_tensor** vec, int num_vec,
tm_tensor* (*loss_fn)(tm_tensor**, int, void*), void* ctx);
```
Hessian-vector product without computing full Hessian. More memory efficient for large models.
#### tm_jvp
```c
tm_tensor** tm_jvp(tm_tensor* (*fn)(tm_tensor**, int, void*), tm_tensor** inputs, int num_inputs,
tm_tensor** tangents, void* ctx, int* num_outputs_out);
```
Jacobian-vector product (forward-mode AD). Computes J @ tangents.
---
### Custom Autograd Functions
#### tm_custom_ctx
Context for saving tensors during forward pass for use in backward.
```c
tm_custom_ctx* tm_custom_ctx_new(void);
void tm_save_for_backward(tm_custom_ctx* ctx, tm_tensor* t);
tm_tensor** tm_get_saved_tensors(tm_custom_ctx* ctx, int* num_saved);
void tm_custom_ctx_free(tm_custom_ctx* ctx);
```
#### tm_register_autograd_function
```c
int tm_register_autograd_function(const char* name,
tm_tensor* (*forward)(tm_tensor**, int, tm_custom_ctx*),
tm_tensor** (*backward)(tm_tensor*, tm_custom_ctx*, int*));
```
Register a custom autograd function with forward and backward implementations.
#### tm_apply_custom_function
```c
tm_tensor* tm_apply_custom_function(const char* name, tm_tensor** inputs, int num_inputs);
tm_tensor* tm_apply_custom_function_id(int fn_id, tm_tensor** inputs, int num_inputs);
```
Apply a registered custom function by name or ID.
---
### Type Conversion
#### tm_to
```c
tm_tensor* tm_to(tm_tensor* t, tm_dtype dtype);
```
Convert tensor to specified dtype.
#### tm_float
```c
tm_tensor* tm_float(tm_tensor* t);
```
Convert to float32.
#### tm_double
```c
tm_tensor* tm_double(tm_tensor* t);
```
Convert to float64.
#### tm_half
```c
tm_tensor* tm_half(tm_tensor* t);
```
Convert to float16.
#### tm_int
```c
tm_tensor* tm_int(tm_tensor* t);
```
Convert to int32.
#### tm_long
```c
tm_tensor* tm_long(tm_tensor* t);
```
Convert to int64.
---
### In-place Operations
**Note:** All in-place operations support autograd. When `requires_grad` is true, gradients are properly tracked and computed during backward pass.
#### tm_fill_
```c
void tm_fill_(tm_tensor* t, float value);
```
Fill tensor with value in-place.
#### tm_add_
```c
void tm_add_(tm_tensor* a, tm_tensor* b);
```
Add tensors in-place: `a += b`.
#### tm_scale_
```c
void tm_scale_(tm_tensor* t, float s);
```
Scale tensor in-place: `t *= s`.
#### tm_zero_
```c
void tm_zero_(tm_tensor* t);
```
Zero tensor in-place.
#### tm_copy_
```c
void tm_copy_(tm_tensor* dst, tm_tensor* src);
```
Copy data in-place.
#### tm_clamp_
```c
void tm_clamp_(tm_tensor* t, float min_val, float max_val);
```
Clamp values in-place.
#### tm_sub_
```c
void tm_sub_(tm_tensor* a, tm_tensor* b);
```
Subtract in-place: `a -= b`.
#### tm_mul_
```c
void tm_mul_(tm_tensor* a, tm_tensor* b);
```
Multiply in-place: `a *= b`.
#### tm_div_
```c
void tm_div_(tm_tensor* a, tm_tensor* b);
```
Divide in-place: `a /= b`.
#### tm_exp_
```c
void tm_exp_(tm_tensor* t);
```
Exponentiate in-place.
#### tm_log_
```c
void tm_log_(tm_tensor* t);
```
Logarithm in-place.
#### tm_sqrt_
```c
void tm_sqrt_(tm_tensor* t);
```
Square root in-place.
#### tm_abs_
```c
void tm_abs_(tm_tensor* t);
```
Absolute value in-place.
#### tm_neg_
```c
void tm_neg_(tm_tensor* t);
```
Negate in-place.
#### tm_relu_
```c
void tm_relu_(tm_tensor* t);
```
ReLU in-place.
#### tm_sigmoid_
```c
void tm_sigmoid_(tm_tensor* t);
```
Sigmoid in-place.
---
## Examples
### Matrix Multiplication
```c
int64_t shape_a[] = {32, 64};
int64_t shape_b[] = {64, 128};
tm_tensor* a = tm_randn(shape_a, 2, TM_F32);
tm_tensor* b = tm_randn(shape_b, 2, TM_F32);
tm_tensor* c = tm_matmul(a, b); // [32, 128]
tm_print(c); // Print shape and info
tm_free(c);
tm_free(b);
tm_free(a);
```
### Simple Neural Network Forward
```c
// Input: [batch, features]
// Weights: [features, hidden]
tm_tensor* h = tm_matmul(input, weights);
tm_tensor* h_bias = tm_add(h, bias);
tm_tensor* h_relu = tm_relu(h_bias);
// Cleanup intermediates
tm_free(h);
tm_free(h_bias);
```
### Broadcasting
```c
int64_t shape_a[] = {32, 64};
int64_t shape_b[] = {64}; // Will broadcast to [32, 64]
tm_tensor* a = tm_ones(shape_a, 2, TM_F32);
tm_tensor* b = tm_full(shape_b, 1, TM_F32, 2.0);
tm_tensor* c = tm_add(a, b); // All elements are 3.0
```
---
## Sparse Tensors
Foundry supports sparse tensors in both COO (Coordinate) and CSR (Compressed Sparse Row) formats.
### Sparse Formats
```c
typedef enum {
TM_SPARSE_COO, /* Coordinate format: (row, col, value) triples */
TM_SPARSE_CSR, /* Compressed Sparse Row: row_ptr, col_ind, values */
} tm_sparse_format;
```
### Creating Sparse Tensors
```c
// Create sparse COO tensor from indices and values
// indices: [2, nnz] tensor of (row, col) pairs
// values: [nnz] tensor of non-zero values
tm_tensor* tm_sparse_coo(tm_tensor* indices, tm_tensor* values, int64_t* shape, int ndim);
// Create sparse CSR tensor
tm_tensor* tm_sparse_csr(tm_tensor* row_ptr, tm_tensor* col_ind, tm_tensor* values,
int64_t* shape, int ndim);
// Convert dense to sparse
tm_tensor* tm_to_sparse(tm_tensor* t); // Dense -> COO
tm_tensor* tm_to_sparse_csr(tm_tensor* t); // Dense -> CSR
tm_tensor* tm_to_dense(tm_tensor* t); // Sparse -> Dense
```
### Sparse Operations
```c
// Check if sparse
bool tm_is_sparse(tm_tensor* t);
int64_t tm_sparse_nnz(tm_tensor* t);
tm_sparse_format tm_get_sparse_format(tm_tensor* t);
// Format conversion
tm_tensor* tm_sparse_coo_to_csr(tm_tensor* t);
tm_tensor* tm_sparse_csr_to_coo(tm_tensor* t);
// Sparse-dense matrix multiplication
tm_tensor* tm_spmm(tm_tensor* sparse, tm_tensor* dense); // sparse @ dense
tm_tensor* tm_spmv(tm_tensor* sparse, tm_tensor* vec); // sparse @ vector
// Sparse arithmetic
tm_tensor* tm_sparse_add(tm_tensor* a, tm_tensor* b); // sparse + sparse
tm_tensor* tm_sparse_mul_scalar(tm_tensor* t, double s); // sparse * scalar
// Access components
tm_tensor* tm_sparse_values(tm_tensor* t); // Get values tensor
tm_tensor* tm_sparse_indices(tm_tensor* t); // Get indices (COO only)
tm_tensor* tm_sparse_coalesce(tm_tensor* t); // Combine duplicate indices
```
### Example
```c
// Create sparse identity matrix
tm_tensor* dense_eye = tm_eye(1000, TM_F32); // 1000x1000 identity
tm_tensor* sparse = tm_to_sparse(dense_eye); // Only 1000 non-zeros stored
// Sparse-dense multiplication (efficient for large sparse matrices)
int64_t shape[] = {1000, 64};
tm_tensor* x = tm_randn(shape, 2, TM_F32);
tm_tensor* result = tm_spmm(sparse, x); // I @ x = x
tm_free(result);
tm_free(x);
tm_free(sparse);
tm_free(dense_eye);
```
---
## Differences from PyTorch
| Feature | PyTorch | Foundry | Why |
|---------|---------|---------|-----|
| Device | CPU/CUDA/MPS | CPU only | GPU requires writing CUDA/Metal kernels for every op. Planned. |
| Autocast | Yes | No | Mixed-precision casting. Planned after GPU support. |
| torch.compile | Yes | N/A | PyTorch's JIT for Python. Foundry is already compiled C code. |
| In-place grad | Yes | **Yes** | All in-place ops (add_, mul_, exp_, relu_, etc.) support autograd. |
| Sparse | Yes | **Yes** | COO and CSR formats with spmm, spmv, and sparse arithmetic. |
---
## See Also
- [optim](optim.md) - Optimizers for training
- [attention](attention.md) - Attention with tensor operations
- [Examples](examples.md) - Complete training examples