Science

vtensor

Vectors and matrices with a declared shape and dtype, in one or two dimensions.

Released v1.0.0 · 2026-09-28
Import
use "stdlib/tensor.ven"

Create, reshape, index and add them, with complex dtype arithmetic.

vtensor.ven
print tensor_element_count([3, 4])
:: 12
Reference (34 functions)

API reference

Shape and dtype validation

tensor_check_rank(shape_dims, who)

attempt
    tensor_check_rank([2, 2, 2], "tensor_zeros")
rescue e
    print(e)
:: prints: tensor_zeros: only 1D and 2D tensors are supported, got rank 3

tensor_element_count(shape_dims)

tensor_element_count([3, 4])
:: 12
tensor_element_count([5])
:: 5

tensor_check_dtype_name(dtype, who)

Rejects any dtype Text other than the three this module supports.

attempt
    tensor_check_dtype_name("float", "tensor_zeros")
rescue e
    print(e)
:: prints: tensor_zeros: dtype must be 'integer', 'number', or 'complex', got 'float'

tensor_element_matches_dtype(value, dtype)

tensor_element_matches_dtype(3, "integer")
:: yes
tensor_element_matches_dtype(3.5, "integer")
:: no
tensor_element_matches_dtype((1.0, 2.0), "complex")
:: yes

tensor_check_data_dtype(data, dtype, who)

Walks data in order and raises at the first element that fails tensor_element_matches_dtype, naming its exact index so a caller can find the offending value without scanning the List themselves.

attempt
    tensor_check_data_dtype([1, 2.5], "integer", "tensor_make")
rescue e
    print(e)
:: prints: tensor_make: element at index 1 does not match declared dtype 'integer'

tensor_dtype_zero(dtype)

tensor_dtype_zero("complex")
:: (0.0, 0.0)

tensor_dtype_one(dtype)

tensor_dtype_one("number")
:: 1.0

tensor_make(shape_dims, data, dtype)

t = tensor_make([2, 2], [1, 2, 3, 4], "number")
tensor_get(t, [1, 1])
:: 4

Complex element arithmetic on (real, imag) tuples

tensor_complex_add(a, b)

Adds two complex elements, each a (real, imag) Tuple, component by component.

tensor_complex_add((1.0, 2.0), (3.0, 4.0))
:: (4.0, 6.0)

tensor_complex_subtract(a, b)

Subtracts one complex element from another, component by component.

tensor_complex_subtract((5.0, 3.0), (2.0, 1.0))
:: (3.0, 2.0)

tensor_complex_multiply(a, b)

Multiplies two complex elements using the standard complex product rule ((ar + ai*i) * (br + bi*i) = (ar*br - ai*bi) + (ar*bi + ai*br)*i).

tensor_complex_multiply((1.0, 2.0), (3.0, 4.0))
:: (-5.0, 10.0)

tensor_complex_divide(a, b)

tensor_complex_divide((1.0, 2.0), (3.0, 4.0))
:: (0.44, 0.08)

tensor_complex_scale(z, scalar)

Scales a complex element by a plain real number, multiplying both its real and imaginary parts by scalar.

tensor_complex_scale((2.0, 3.0), 2)
:: (4.0, 6.0)

Construction

tensor_zeros(shape_dims, dtype = "number")

tensor_to_nested_list(tensor_zeros([2, 2]))
:: [[0.0, 0.0], [0.0, 0.0]]

tensor_ones(shape_dims, dtype = "number")

tensor_to_nested_list(tensor_ones([2, 2], "integer"))
:: [[1, 1], [1, 1]]

tensor_from_nested_list(values, dtype = "number")

tensor_to_nested_list(tensor_from_nested_list([[1, 2], [3, 4]]))
:: [[1, 2], [3, 4]]

tensor_to_nested_list(t)

The inverse of tensor_from_nested_list: unpacks a Tensor's flat, row-major data back into an ordinary Venutian List.

tensor_to_nested_list(tensor_from_nested_list([5, 6, 7]))
:: [5, 6, 7]

Shape / dtype introspection

tensor_shape(t)

tensor_shape(tensor_zeros([3, 2]))
:: [3, 2]

tensor_dtype(t)

A tensor's own dtype Text, exactly as stored on its dtype field.

tensor_dtype(tensor_ones([2], "integer"))
:: "integer"

tensor_reshape(t, new_shape_dims)

t = tensor_from_nested_list([[1, 2, 3], [4, 5, 6]], "integer")
tensor_to_nested_list(tensor_reshape(t, [3, 2]))
:: [[1, 2], [3, 4], [5, 6]]

tensor_flat_offset(t, indices)

Converts a per-dimension index (one Integer for a vector, or [row, column] for a matrix) into the single position inside t's own flat data List that element lives at.

t = tensor_zeros([2, 3])
tensor_flat_offset(t, [1, 2])
:: 5

tensor_get(t, indices)

Reads the single element at indices (one Integer for a vector, or [row, column] for a matrix).

t = tensor_from_nested_list([[1, 2], [3, 4]], "integer")
tensor_get(t, [1, 0])
:: 3

tensor_set(t, indices, value)

Writes value into t's own data at indices, mutating t in place (this is not a copy-on-write operation: the same Tensor value handed in comes back changed).

t = tensor_zeros([2, 2], "integer")
tensor_set(t, [0, 1], 9)
tensor_get(t, [0, 1])
:: 9

Shape / dtype agreement checks used by every binary op

tensor_same_shape(a, b, who)

attempt
    tensor_same_shape(tensor_zeros([2, 3]), tensor_zeros([3, 2]), "tensor_add")
rescue e
    print(e)
:: prints: tensor_add: both tensors must have the same shape (got [2, 3] and [3, 2])

tensor_same_dtype(a, b, who)

attempt
    tensor_same_dtype(tensor_zeros([2], "integer"), tensor_zeros([2], "number"), "tensor_add")
rescue e
    print(e)
:: prints: tensor_add: both tensors must have the same dtype (got 'integer' and 'number')

Element-wise arithmetic

tensor_add(a, b)

Adds two tensors element by element.

a = tensor_from_nested_list([[1, 2]], "integer")
b = tensor_from_nested_list([[3, 4]], "integer")
tensor_to_nested_list(tensor_add(a, b))
:: [[4, 6]]

tensor_subtract(a, b)

Subtracts b from a element by element.

a = tensor_from_nested_list([[5, 6]], "integer")
b = tensor_from_nested_list([[1, 2]], "integer")
tensor_to_nested_list(tensor_subtract(a, b))
:: [[4, 4]]

tensor_multiply_elementwise(a, b)

a = tensor_from_nested_list([[2, 3]], "integer")
b = tensor_from_nested_list([[4, 5]], "integer")
tensor_to_nested_list(tensor_multiply_elementwise(a, b))
:: [[8, 15]]

tensor_divide_elementwise(a, b)

Divides a by b element by element.

a = tensor_from_nested_list([[4.0, 6.0]], "number")
b = tensor_from_nested_list([[2.0, 3.0]], "number")
tensor_to_nested_list(tensor_divide_elementwise(a, b))
:: [[2.0, 2.0]]

tensor_scalar_multiply(t, scalar)

Multiplies every element of t by a single scalar.

t = tensor_from_nested_list([[1, 2], [3, 4]], "integer")
tensor_to_nested_list(tensor_scalar_multiply(t, 2))
:: [[2, 4], [6, 8]]

tensor_matmul(a, b)

a = tensor_from_nested_list([[1, 2], [3, 4]], "integer")
b = tensor_from_nested_list([[5, 6], [7, 8]], "integer")
tensor_to_nested_list(tensor_matmul(a, b))
:: [[19, 22], [43, 50]]

tensor_sum(t)

Adds up every element of t into a single total.

tensor_sum(tensor_from_nested_list([[1, 2], [3, 4]], "integer"))
:: 10

tensor_mean(t)

The average of every element of t.

tensor_mean(tensor_from_nested_list([[1, 2], [3, 4]], "integer"))
:: 2.5

tensor_transpose(t)

t = tensor_from_nested_list([[1, 2, 3], [4, 5, 6]], "integer")
tensor_to_nested_list(tensor_transpose(t))
:: [[1, 4], [2, 5], [3, 6]]

Get notified when vtensor changes

Get notified about

New versions and security advisories.

New and updated packages, once a day.

News on the math model built in Venutian.