# Types

## Native

</>

A type for Native tensor representations.

pub type Native

## NativeResult

</>

A Result alias type for Native tensor data.

pub type NativeResult =
Result(Native, TensorError)

## Tensor

</>

A Tensor is a generic container for n-dimensional data structures.

pub opaque type Tensor(a)

## TensorError

</>

When a tensor operation cannot succeed.

pub type TensorError {
IncompatibleAxes
IncompatibleShape
InvalidData
SpaceErrors(space.SpaceErrors)
ZeroDivision
}

### Constructors

• IncompatibleAxes
• IncompatibleShape
• InvalidData
• SpaceErrors(space.SpaceErrors)
• ZeroDivision

## TensorResult

</>

A Result alias type for tensors.

pub type TensorResult(a) =
Result(Tensor(a), TensorError)

## ToString

</>

A type used to specify how to convert a Tensor into a String via the to_string function.

pub type ToString {
Data
Record
}

• Data
• Record

# Functions

## absolute_value

</>
pub fn absolute_value(x: Tensor(a)) -> Tensor(a)

Returns the element-wise absolute value of the given Tensor.

## Examples

> let x = from_int(3)
> absolute_value(x) |> print
Tensor(
Format(Int32),
Space(),
3,
)
Nil

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [-0.3], into: d1)
> absolute_value(x) |> print
Tensor(
Format(Float32),
Space(X(1)),
[0.3],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_ints(of: [-1, 8, 0], into: d3)
> absolute_value(x) |> print
Tensor(
Format(Int32),
Space(X(1), Y(3), Z(1)),
[[[1],
[8],
[0]]],
)
Nil

</>
pub fn add(a: Tensor(a), b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise addition of the given tensors on success (broadcast as needed), or a TensorError on failure.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [0, 9], into: d1)
> let assert Ok(x) = add(a, from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[ 3, 12],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [0, 4, 5, 0], into: d2)
> let assert Ok(x) = add(a, b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[ 0, 13],
[ 5,  9]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 0], into: d3)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)

## all

</>
pub fn all(from x: Tensor(a), with filter: fn(Axis) -> Bool) -> Tensor(
a,
)

Reduces the given Tensor over select axes to 1 if all values across those axes are nonzero, otherwise 0, with Format retained.

Any Axis for which the given filter function returns True is selected for reduction and will be removed from the reduced tensor’s Space.

If the filter function returns False for every Axis, all Axes will be retained and the operation applied to every value of the Tensor individually.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [-1, 0], into: d1)
> all(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
0,
)
Nil

> all(x, with: fn(_) { False }) |> print
Tensor(
Format(Int32),
Space(X(2)),
[1, 0],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_ints(of: [1, 2], into: d3)
> all(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
1,
)
Nil

> all(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2)),
[[1, 1]],
)
Nil

## any

</>
pub fn any(from x: Tensor(a), with filter: fn(Axis) -> Bool) -> Tensor(
a,
)

Reduces the given Tensor over select axes to 1 if any values across those axes are nonzero, otherwise 0, with Format retained.

Any Axis for which the given filter function returns True is selected for reduction and will be removed from the reduced tensor’s Space.

If the filter function returns False for every Axis, all Axes will be retained and the operation applied to every value of the Tensor individually.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [-1, 0], into: d1)
> any(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
1,
)
Nil

> any(x, with: fn(_) { False }) |> print
Tensor(
Format(Int32),
Space(X(2)),
[1, 0],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_ints(of: [0, 0], into: d3)
> any(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
0,
)
Nil

> any(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2)),
[[0, 0]],
)
Nil

## arg_max

</>
pub fn arg_max(from x: Tensor(a), with find: fn(Axis) -> Bool) -> Tensor(
a,
)

Reduces the given Tensor over a select Axis to the lowest index of the max value across that Axis, with Format retained.

The first Axis for which the given find function returns True is selected for reduction and will be removed from the reduced tensor’s Space.

If the find function returns False for every Axis, the Tensor will be flattened and the operation applied over the remaining Axis.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [-1, 0], into: d1)
> arg_max(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
1,
)
Nil

> arg_max(x, with: fn(_) { False }) |> print
Tensor(
Format(Int32),
Space(),
1,
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4], into: d3)
> arg_max(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(Y(2), Z(2)),
[[0, 0],
[0, 0]],
)
Nil

> arg_max(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2)),
[[1, 0]],
)
Nil

## arg_min

</>
pub fn arg_min(from x: Tensor(a), with find: fn(Axis) -> Bool) -> Tensor(
a,
)

Reduces the given Tensor over a select Axis to the lowest index of the min value across that Axis, with Format retained.

The first Axis for which the given find function returns True is selected for reduction and will be removed from the reduced tensor’s Space.

If the find function returns False for every Axis, the Tensor will be flattened and the operation applied over the remaining Axis.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [-1, 0], into: d1)
> arg_min(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
0,
)
Nil

> arg_min(x, with: fn(_) { False }) |> print
Tensor(
Format(Int32),
Space(),
0,
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4], into: d3)
> arg_min(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(Y(2), Z(2)),
[[0, 0],
[0, 0]],
)
Nil

> arg_min(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2)),
[[0, 1]],
)
Nil

## axes

</>
pub fn axes(x: Tensor(a)) -> List(Axis)

Returns the Axes of a given Tensor.

## Examples

> axes(from_int(3))
[]

> import argamak/axis.{Axis, X}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [1.0, 2.0, 3.0], into: d1)
> axes(x)
[X(3)]

> let assert Ok(d2) = space.d2(Axis("Alpha", 1), Axis("Omega", 3))
> let assert Ok(x) = from_ints(of: [1, 2, 3], into: d2)
> axes(x)
[Axis("Alpha", 1), Axis("Omega", 3)]

</>
pub fn broadcast(from x: Tensor(a), into new_space: Space) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor broadcast into a given Space on success, or a TensorError on failure.

The new Space cannot have fewer Axes than the current Space.

Each current Axis size must be 1 or equal to its counterpart in the new Space (a dimensionless Tensor can be broadcast into any Space). Axis compatibility is considered element-wise, tail-first.

Any Infer in the new Space will result in failure.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(X(3))
> let assert Ok(x) = broadcast(from: from_int(0), into: d1)
> print(x)
Tensor(
Format(Int32),
Space(X(3)),
[0, 0, 0],
)
Nil

> let assert Ok(d1) = space.d1(Infer("X"))
> let x = from_ints(of: [-1], into: d1)
> let assert Ok(d1) = space.d1(Y(5))
> let assert Ok(x) = broadcast(from: x, into: d1)
> print(x)
Tensor(
Format(Int32),
Space(Y(5)),
[-1, -1, -1, -1, -1],
)
Nil

> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [1.0, 2.0, 3.0], into: d1)
> let assert Ok(d2) = space.d2(X(2), Y(3))
> let assert Ok(x) = broadcast(from: x, into: d2)
> print(x)
Tensor(
Format(Float32),
Space(X(2), Y(3)),
[[1.0, 2.0, 3.0],
[1.0, 2.0, 3.0]],
)
Nil

> let assert Ok(d3) = space.d3(X(2), Y(3), Infer("Z"))
Error(IncompatibleShape)

</>
pub fn broadcast_over(from x: Tensor(a), into new_space: Space, with space_map: fn(
Axis,
) -> String) -> Result(Tensor(a), TensorError)

A variant of broadcast that maps the given Tensor’s current Axes to arbitrary counterparts in the new Space.

The map function allows broadcasting into a Space that is incompatible with a standard broadcast operation. Any given new Axis must not be matched with multiple axes from the Tensor‘s current Space, and the current axes’ relative order may be interrupted, but not altered, when axes are translated to their mapped counterparts.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [1.0, 2.0, 3.0], into: d1)
> let assert Ok(d2) = space.d2(X(3), Y(2))
> let assert Ok(y) = broadcast_over(from: x, into: d2, with: fn(_) { "X" })
> print(y)
Tensor(
Format(Float32),
Space(X(3), Y(2)),
[[1.0, 1.0],
[2.0, 2.0],
[3.0, 3.0]],
)
Nil

> let assert Ok(x) = from_ints(of: [1, 2, 3, 4, 5, 6], into: d2)
> let assert Ok(d3) = space.d3(X(3), Y(2), Z(2))
> let assert Ok(y) = broadcast_over(
from: x,
into: d3,
with: fn(a) {
case axis.name(a) {
"Y" -> "Z"
name -> name
}
},
)
> print(y)
Tensor(
Format(Int32),
Space(X(3), Y(2), Z(2))
[[[1, 2],
[1, 2]],
[[3, 4],
[3, 4]],
[[5, 6],
[5, 6]]],
)
Nil

> let assert Ok(y) = broadcast_over(
from: x,
into: d3,
with: axis.name,
)
> print(y)
Tensor(
Format(Int32),
Space(X(3), Y(2), Z(2)),
[[[1, 1],
[2, 2]],
[[3, 3],
[4, 4]],
[[5, 5],
[6, 6]]],
)
Nil

> let assert Ok(d3) = space.d3(X(2), Y(3), Infer("Z"))
> broadcast_over(from: x, into: d3, with: axis.name)
Error(IncompatibleShape)

## ceiling

</>
pub fn ceiling(x: Tensor(a)) -> Tensor(a)

Returns the element-wise ceiling of the given Tensor, with Format retained.

## Examples

> let x = from_int(3)
> ceiling(x) |> print
Tensor(
Format(Int32),
Space(),
3,
)
Nil

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [-0.5], into: d1)
> ceiling(x) |> print
Tensor(
Format(Float32),
Space(X(1)),
[0.0],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_floats(of: [-1.2, 7.8, 0.0], into: d3)
> ceiling(x) |> print
Tensor(
Format(Float32),
Space(X(1), Y(3), Z(1)),
[[[-1.0],
[ 8.0],
[ 0.0]]],
)
Nil

## concat

</>
pub fn concat(xs: List(Tensor(a)), with find: fn(Axis) -> Bool) -> Result(
Tensor(a),
TensorError,
)

Results in a new Tensor formed by concatenating (joining) the given list of tensors along a select Axis on success, or a TensorError on failure.

The first Axis for which the given find function returns True is selected for joining.

If the find function returns False for every Axis, the tensors will be joined along the first Axis.

## Examples

> import argamak/axis.{Infer, X, Y}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(a) = from_ints(of: [0, 1, 2, 3], into: d1)
> let assert Ok(b) = from_ints(of: [4, 5, 6, 7], into: d1)
> let assert Ok(x) = concat([a, b], with: fn(_) { True })
> print(x)
Tensor(
Format(Int32),
Space(X(8)),
[0, 1, 2, 3, 4, 5, 6, 7],
)
Nil

> let assert Ok(d2) = space.d2(X(2), Infer("Y"))
> let assert Ok(a) = reshape(put: a, into: d2)
> let assert Ok(b) = from_ints(of: [4, 5], into: d2)
> let assert Ok(x) = concat([a, b], with: fn(a) { axis.name(a) == "Y" })
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(3)),
[[0, 1, 4],
[2, 3, 5]],
)
Nil

> concat([a, b], with: fn(a) { axis.name(a) == "X" })
Error(IncompatibleShape)

> let assert Ok(b) = reshape(put: b, into: d1)
> concat([a, b], with: fn(a) { axis.name(a) == "X" })
Error(IncompatibleShape)

> let assert Ok(d2) = space.d2(Infer("Z"), Y(1))
> let assert Ok(b) = reshape(put: b, into: d2)
> concat([a, b], with: fn(a) { axis.name(a) == "Y" })
Error(IncompatibleShape)

## debug

</>
pub fn debug(x: Tensor(a)) -> Tensor(a)

Prints the data and metadata from a given Tensor and returns the Tensor.

## Examples

> import argamak/axis.{X, Y, Z}
> import argamak/space
> let assert Ok(d2) = space.d2(X(2), Y(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4], into: d2)
> debug(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[1, 2],
[3, 4]],
)
x

> let assert Ok(d3) = space.d3(X(2), Y(1), Z(4))
> let xs = [1, 2, 3, 4, 5, 6, 7, 8]
> let assert Ok(x) = from_ints(of: xs, into: d3)
> debug(x)
Tensor(
Format(Int32),
Space(X(2), Y(1), Z(4)),
[[[1, 2, 3, 4]],
[[5, 6, 7, 8]]],
)
x

## divide

</>
pub fn divide(from a: Tensor(a), by b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise division of one Tensor by another on success (broadcast as needed), or a TensorError on failure.

As with Gleam’s operators, division by zero returns zero.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [1, 9], into: d1)
> let assert Ok(x) = divide(from: a, by: from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[0, 3],
)
Nil

> let a = reformat(a, apply: format.float32())
> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_floats(of: [0.0, 4.0, 5.0, 9.0], into: d2)
> let assert Ok(x) = divide(from: a, by: b)
> print(x)
Tensor(
Format(Float32),
Space(X(2), Y(2)),
[[ 0.0, 2.25],
[ 0.2,  1.0]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_floats(of: [4.0, 5.0, 0.0], into: d3)
> divide(from: b, by: c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> divide(from: b, by: c)

## equal

</>
pub fn equal(is a: Tensor(a), to b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise comparison of the given tensors on success (broadcast as needed), or a TensorError on failure.

Equality is represented by 1, inequality by 0, with Format retained.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [5, 4], into: d1)
> let assert Ok(x) = equal(is: a, to: from_int(4))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[0, 1],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [4, 4, 5, 5], into: d2)
> let assert Ok(x) = equal(is: a, to: b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[0, 1],
[1, 0]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 6], into: d3)
> equal(is: b, to: c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> equal(is: b, to: c)

## exp

</>
pub fn exp(x: Tensor(a)) -> Tensor(a)

Returns the element-wise natural exponential (Euler’s number raised to the power of x) of the given Tensor, with Format retained.

## Examples

> let x = from_int(3)
> exp(x) |> print
Tensor(
Format(Int32),
Space(),
20,
)
Nil

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [-0.5], into: d1)
> exp(x) |> print
Tensor(
Format(Float32),
Space(X(1)),
[0.223],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_floats(of: [-1.2, 7.8, 0.0], into: d3)
> exp(x) |> print
Tensor(
Format(Float32),
Space(X(1), Y(3), Z(1)),
[[[   0.301],
[2440.603],
[     1.0]]],
)
Nil

## floor

</>
pub fn floor(x: Tensor(a)) -> Tensor(a)

Returns the element-wise floor of the given Tensor, with Format retained.

## Examples

> let x = from_int(3)
> floor(x) |> print
Tensor(
Format(Int32),
Space(),
3,
)
Nil

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [-0.5], into: d1)
> floor(x) |> print
Tensor(
Format(Float32),
Space(X(1)),
[-1.0],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_floats(of: [-1.2, 7.8, 0.0], into: d3)
> floor(x) |> print
Tensor(
Format(Float32),
Space(X(1), Y(3), Z(1)),
[[[-2.0],
[ 7.0],
[ 0.0]]],
)
Nil

## format

</>
pub fn format(x: Tensor(a)) -> Format(a)

Returns the Format of a given Tensor.

## Examples

import argamak/format
> format(from_float(0.0))
format.float32()

> import argamak/axis.{Infer}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [1, 2, 3], into: d1)
> format(x)
format.int32()

## from_bool

</>
pub fn from_bool(x: Bool) -> Tensor(Int32)

Creates a Tensor(Int32) from a Bool.

True is represented by 1, False by 0.

## Examples

> from_bool(True) |> print_data
1
Nil

> from_bool(False) |> print_data
0
Nil

## from_bools

</>
pub fn from_bools(of xs: List(Bool), into space: Space) -> Result(
Tensor(Int32),
TensorError,
)

Results in a Tensor(Int32) created from a list of booleans and placed into a given Space on success, or a TensorError on failure.

True is represented by 1, False by 0.

The Space may have a single Infer Axis, the size of which will be determined based on the given list. This is useful when working with lists of unknown length.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_bools(of: [True], into: d1)
> print(x)
Tensor(
Format(Int32),
Space(X(1)),
[1],
)
Nil

> let assert Ok(d2) = space.d2(X(2), Y(2))
> let assert Ok(x) = from_bools(of: [True, False, True, True], into: d2)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[1, 0],
[1, 1]],
)
Nil

> let assert Ok(d3) = space.d3(Infer("X"), Y(2), Z(2))
> let xs = [True, False, True, False, False, True, False, True]
> let assert Ok(x) = from_bools(of: xs, into: d3)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2), Z(2)),
[[[1, 0],
[1, 0]],
[[0, 1],
[0, 1]]],
)
Nil

## from_float

</>
pub fn from_float(x: Float) -> Tensor(Float32)

Creates a Tensor from a Float.

## Examples

> from_float(1.0) |> print_data
1.0
Nil

## from_floats

</>
pub fn from_floats(of xs: List(Float), into space: Space) -> Result(
Tensor(Float32),
TensorError,
)

Results in a Tensor created from a list of floats and placed into a given Space on success, or a TensorError on failure.

The Space may have a single Infer Axis, the size of which will be determined based on the given list. This is useful when working with lists of unknown length.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [1.0], into: d1)
> print(x)
Tensor(
Format(Float32),
Space(X(1)),
[1.0],
)
Nil

> let assert Ok(d2) = space.d2(X(2), Y(2))
> let assert Ok(x) = from_floats(of: [1.0, 2.0, 3.0, 4.0], into: d2)
> print(x)
Tensor(
Format(Float32),
Space(X(2), Y(2)),
[[1.0, 2.0],
[3.0, 4.0]],
)
Nil

> let assert Ok(d3) = space.d3(Infer("X"), Y(2), Z(2))
> let xs = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
> let assert Ok(x) = from_floats(of: xs, into: d3)
> print(x)
Tensor(
Format(Float32),
Space(X(2), Y(2), Z(2)),
[[[1.0, 2.0],
[3.0, 4.0]],
[[5.0, 6.0],
[7.0, 8.0]]],
)
Nil

## from_int

</>
pub fn from_int(x: Int) -> Tensor(Int32)

Creates a Tensor from an Int.

## Examples

> from_int(1) |> print_data
1
Nil

## from_ints

</>
pub fn from_ints(of xs: List(Int), into space: Space) -> Result(
Tensor(Int32),
TensorError,
)

Results in a Tensor created from a list of integers and placed into a given Space on success, or a TensorError on failure.

The Space may have a single Infer Axis, the size of which will be determined based on the given list. This is useful when working with lists of unknown length.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [1], into: d1)
> print(x)
Tensor(
Format(Int32),
Space(X(1)),
[1],
)
Nil

> let assert Ok(d2) = space.d2(X(2), Y(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4], into: d2)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[1, 2],
[3, 4]],
)
Nil

> let assert Ok(d3) = space.d3(Infer("X"), Y(2), Z(2))
> let xs = [1, 2, 3, 4, 5, 6, 7, 8]
> let assert Ok(x) = from_ints(of: xs, into: d3)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2), Z(2)),
[[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]]],
)
Nil

## from_native

</>
pub fn from_native(of x: Native, into space: Space, with format: Format(
a,
)) -> Result(Tensor(a), TensorError)

Results in a Tensor created from a Native representation on success, or a TensorError on failure.

## Examples

> import argamak/axis.{Infer, X, Y}
> import argamak/format
> import argamak/space
> import gleam/dynamic.{Dynamic}
> @external(erlang, "Elixir.Nx", "tensor")
> fn erlang_tensor(data: Dynamic) -> Native
> let native = erlang_tensor(dynamic.from([[1, 2], [3, 4]]))
> let assert Ok(d2) = space.d2(X(2), Infer("Y"))
> let assert Ok(x) = from_native(of: native, into: d2, with: format.int32)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[1, 2],
[3, 4]],
)
Nil

## greater

</>
pub fn greater(is a: Tensor(a), than b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise comparison of the given tensors on success (broadcast as needed), or a TensorError on failure.

Values in the first Tensor that are greater than those in the second are represented by 1, otherwise 0, with Format retained.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [5, 4], into: d1)
> let assert Ok(x) = greater(is: a, than: from_int(4))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[1, 0],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [4, 4, 5, 5], into: d2)
> let assert Ok(x) = greater(is: a, than: b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[1, 0],
[0, 0]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 6], into: d3)
> greater(is: b, than: c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> greater(is: b, than: c)

## greater_or_equal

</>
pub fn greater_or_equal(is a: Tensor(a), to b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise comparison of the given tensors on success (broadcast as needed), or a TensorError on failure.

Values in the first Tensor that are greater than or equal to those in the second are represented by 1, otherwise 0, with Format retained.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [5, 4], into: d1)
> let assert Ok(x) = greater_or_equal(is: a, to: from_int(4))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[1, 1],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [4, 4, 5, 5], into: d2)
> let assert Ok(x) = greater_or_equal(is: a, to: b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[1, 1],
[1, 0]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 6], into: d3)
> greater_or_equal(is: b, to: c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> greater_or_equal(is: b, to: c)

## in_situ_all

</>
pub fn in_situ_all(from x: Tensor(a), with filter: fn(Axis) ->
Bool) -> Tensor(a)

A variant of all that preserves all Axes from the given Tensor.

Any Axis for which the given filter function returns True will retain a size of 1 after the operation.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_ints(of: [0, 2], into: d3)
> in_situ_all(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2), Z(1)),
[[[0],
[1]]],
)
Nil

## in_situ_any

</>
pub fn in_situ_any(from x: Tensor(a), with filter: fn(Axis) ->
Bool) -> Tensor(a)

A variant of any that preserves all Axes from the given Tensor.

Any Axis for which the given filter function returns True will retain a size of 1 after the operation.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_ints(of: [0, 2], into: d3)
> in_situ_any(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2), Z(1)),
[[[0],
[1]]],
)
Nil

## in_situ_arg_max

</>
pub fn in_situ_arg_max(from x: Tensor(a), with find: fn(Axis) ->
Bool) -> Tensor(a)

A variant of arg_max that preserves all Axes from the given Tensor.

An Axis for which the given find function returns True will retain a size of 1 after the operation.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4], into: d3)
> in_situ_arg_max(x, with: fn(a) { axis.name(a) == "Y" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(1), Z(2)),
[[[1, 0]]],
)
Nil

> in_situ_arg_max(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2), Z(1)),
[[[1],
[0]]],
)
Nil

## in_situ_arg_min

</>
pub fn in_situ_arg_min(from x: Tensor(a), with find: fn(Axis) ->
Bool) -> Tensor(a)

A variant of arg_min that preserves all Axes from the given Tensor.

An Axis for which the given find function returns True will retain a size of 1 after the operation.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4], into: d3)
> in_situ_arg_min(x, with: fn(a) { axis.name(a) == "Y" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(1), Z(2)),
[[[0, 1]]],
)
Nil

> in_situ_arg_min(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2), Z(1)),
[[[0],
[1]]],
)
Nil

## in_situ_max_over

</>
pub fn in_situ_max_over(from x: Tensor(a), with filter: fn(Axis) ->
Bool) -> Tensor(a)

A variant of max_over that preserves all Axes from the given Tensor.

Any Axis for which the given filter function returns True will retain a size of 1 after the operation.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [1, 4, 3, 2], into: d3)
> in_situ_max_over(x, with: fn(a) { axis.name(a) == "Y" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(1), Z(2)),
[[[3, 4]]],
)
Nil

> in_situ_max_over(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2), Z(1)),
[[[4],
[3]]],
)
Nil

## in_situ_mean

</>
pub fn in_situ_mean(from x: Tensor(a), with filter: fn(Axis) ->
Bool) -> Tensor(a)

A variant of mean that preserves all Axes from the given Tensor.

Any Axis for which the given filter function returns True will retain a size of 1 after the operation.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_floats(of: [1.0, 4.0, 3.0, 2.0], into: d3)
> in_situ_mean(x, with: fn(_) { True }) |> print
Tensor(
Format(Float32),
Space(X(1), Y(1), Z(1)),
[[[2.5]]],
)
Nil

> in_situ_mean(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Float32),
Space(X(1), Y(2), Z(1)),
[[[2.5],
[2.5]]],
)
Nil

## in_situ_min_over

</>
pub fn in_situ_min_over(from x: Tensor(a), with filter: fn(Axis) ->
Bool) -> Tensor(a)

A variant of min_over that preserves all Axes from the given Tensor.

Any Axis for which the given filter function returns True will retain a size of 1 after the operation.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [1, 4, 3, 2], into: d3)
> in_situ_min_over(x, with: fn(a) { axis.name(a) == "Y" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(1), Z(2)),
[[[1, 2]]],
)
Nil

> in_situ_min_over(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2), Z(1)),
[[[1],
[2]]],
)
Nil

## in_situ_product

</>
pub fn in_situ_product(from x: Tensor(a), with filter: fn(Axis) ->
Bool) -> Tensor(a)

A variant of product that preserves all Axes from the given Tensor.

Any Axis for which the given filter function returns True will retain a size of 1 after the operation.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [1, 4, 3, 2], into: d3)
> in_situ_product(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(1), Z(1)),
[[[24]]],
)
Nil

> in_situ_product(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2), Z(1)),
[[[4],
[6]]],
)
Nil

## in_situ_sum

</>
pub fn in_situ_sum(from x: Tensor(a), with filter: fn(Axis) ->
Bool) -> Tensor(a)

A variant of sum that preserves all Axes from the given Tensor.

Any Axis for which the given filter function returns True will retain a size of 1 after the operation.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [2, 4, 3, 0], into: d3)
> in_situ_sum(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(1), Z(1)),
[[[9]]],
)
Nil

> in_situ_sum(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2), Z(1)),
[[[6],
[3]]],
)
Nil

## less

</>
pub fn less(is a: Tensor(a), than b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise comparison of the given tensors on success (broadcast as needed), or a TensorError on failure.

Values in the first Tensor that are less than those in the second are represented by 1, otherwise 0, with Format retained.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [5, 4], into: d1)
> let assert Ok(x) = less(is: a, than: from_int(5))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[0, 1],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [4, 4, 5, 5], into: d2)
> let assert Ok(x) = less(is: a, than: b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[0, 0],
[0, 1]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 6], into: d3)
> less(is: b, than: c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> less(is: b, than: c)

## less_or_equal

</>
pub fn less_or_equal(is a: Tensor(a), to b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise comparison of the given tensors on success (broadcast as needed), or a TensorError on failure.

Values in the first Tensor that are less than or equal to those in the second are represented by 1, otherwise 0, with Format retained.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [5, 4], into: d1)
> let assert Ok(x) = less_or_equal(is: a, to: from_int(5))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[1, 1],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [4, 4, 5, 5], into: d2)
> let assert Ok(x) = less_or_equal(is: a, to: b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[0, 1],
[1, 1]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 6], into: d3)
> less_or_equal(is: b, to: c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> less_or_equal(is: b, to: c)

## ln

</>
pub fn ln(x: Tensor(a)) -> Result(Tensor(a), TensorError)

Results in the element-wise natural logarithm of the given Tensor on success, or a TensorError on failure, with Format retained.

## Examples

> let assert Ok(x) = ln(from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(),
1,
)
Nil

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [1.5], into: d1)
> let assert Ok(x) = ln(x)
> print(x)
Tensor(
Format(Float32),
Space(X(1)),
[0.405],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_floats(of: [1.2, 7.8, 0.0], into: d3)
> let assert Ok(x) = ln(x)
> print(x)
Tensor(
Format(Float32),
Space(X(1), Y(3), Z(1)),
[[[    0.182],
[    2.054],
[-Infinity]]],
)
Nil

> ln(from_float(-0.1))
Error(InvalidData)

## logical_and

</>
pub fn logical_and(a: Tensor(a), b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise comparison of the given tensors on success (broadcast as needed), or a TensorError on failure.

Values that are nonzero in both the first and second tensors are represented by 1, otherwise 0, with Format retained.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [9, 0], into: d1)
> let assert Ok(x) = logical_and(a, from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[1, 0],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [0, 4, 5, 0], into: d2)
> let assert Ok(x) = logical_and(a, b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[0, 0],
[1, 0]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 0], into: d3)
> logical_and(b, c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> logical_and(b, c)

## logical_not

</>
pub fn logical_not(x: Tensor(a)) -> Tensor(a)

Returns the element-wise logical opposite of the given Tensor.

Values that are nonzero are represented by 0, otherwise 1, with Format retained.

## Examples

> let x = from_int(3)
> logical_not(x) |> print
Tensor(
Format(Int32),
Space(),
0,
)
Nil

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [-0.3], into: d1)
> logical_not(x) |> print
Tensor(
Format(Float32),
Space(X(1)),
[0.0],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_ints(of: [-1, 8, 0], into: d3)
> logical_not(x) |> print
Tensor(
Format(Int32),
Space(X(1), Y(3), Z(1)),
[[[0],
[0],
[1]]],
)
Nil

## logical_or

</>
pub fn logical_or(a: Tensor(a), b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise comparison of the given tensors on success (broadcast as needed), or a TensorError on failure.

Values that are nonzero in either the first or second Tensor, or both, are represented by 1, otherwise 0, with Format retained.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [9, 0], into: d1)
> let assert Ok(x) = logical_or(a, from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[1, 1],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [0, 4, 5, 0], into: d2)
> let assert Ok(x) = logical_or(a, b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[1, 1],
[1, 0]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 0], into: d3)
> logical_or(b, c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> logical_or(b, c)

## logical_xor

</>
pub fn logical_xor(a: Tensor(a), b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise comparison of the given tensors on success (broadcast as needed), or a TensorError on failure.

Values that are nonzero in either the first or second Tensor, but not both, are represented by 1, otherwise 0, with Format retained.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [9, 0], into: d1)
> let assert Ok(x) = logical_xor(a, from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[0, 1],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [0, 4, 5, 0], into: d2)
> let assert Ok(x) = logical_xor(a, b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[1, 1],
[0, 0]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 0], into: d3)
> logical_xor(b, c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> logical_xor(b, c)

## max

</>
pub fn max(a: Tensor(a), b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise maximum of the given tensors on success (broadcast as needed), or a TensorError on failure.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [1, 9], into: d1)
> let assert Ok(x) = max(a, from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[3, 9],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [0, 4, 5, -9], into: d2)
> let assert Ok(x) = max(a, b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[1, 9],
[5, 9]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 0], into: d3)
> max(b, c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> max(b, c)

## max_over

</>
pub fn max_over(from x: Tensor(a), with filter: fn(Axis) -> Bool) -> Tensor(
a,
)

Reduces the given Tensor over select axes to the max value across those axes.

Any Axis for which the given filter function returns True is selected for reduction and will be removed from the reduced tensor’s Space.

If the filter function returns False for every Axis, all Axes will be retained and the operation applied to every value of the Tensor individually.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [-1, 2], into: d1)
> max_over(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
2,
)
Nil

> max_over(x, with: fn(_) { False }) |> print
Tensor(
Format(Int32),
Space(X(2)),
[-1,  2],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [1, 4, 3, 2], into: d3)
> max_over(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
4,
)
Nil

> max_over(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2)),
[[4, 3]],
)
Nil

## mean

</>
pub fn mean(from x: Tensor(a), with filter: fn(Axis) -> Bool) -> Tensor(
a,
)

Reduces the given Tensor over select axes to the mean of the values across those axes.

Any Axis for which the given filter function returns True is selected for reduction and will be removed from the reduced tensor’s Space.

If the filter function returns False for every Axis, all Axes will be retained and the operation applied to every value of the Tensor individually.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [-1, 2], into: d1)
> mean(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
0,
)
Nil

> mean(x, with: fn(_) { False }) |> print
Tensor(
Format(Int32),
Space(X(2)),
[-1,  2],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_floats(of: [1.0, 4.0, 3.0, 2.0], into: d3)
> mean(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
2.5,
)
Nil

> mean(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2)),
[[2.5, 2.5]],
)
Nil

## min

</>
pub fn min(a: Tensor(a), b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise minimum of the given tensors on success (broadcast as needed), or a TensorError on failure.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [1, 9], into: d1)
> let assert Ok(x) = min(a, from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[1, 3],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [0, 4, 5, -9], into: d2)
> let assert Ok(x) = min(a, b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[ 0,  4],
[ 1, -9]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 0], into: d3)
> min(b, c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> min(b, c)

## min_over

</>
pub fn min_over(from x: Tensor(a), with filter: fn(Axis) -> Bool) -> Tensor(
a,
)

Reduces the given Tensor over select axes to the min value across those axes.

Any Axis for which the given filter function returns True is selected for reduction and will be removed from the reduced tensor’s Space.

If the filter function returns False for every Axis, all Axes will be retained and the operation applied to every value of the Tensor individually.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [-1, 2], into: d1)
> min_over(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
-1,
)
Nil

> min_over(x, with: fn(_) { False }) |> print
Tensor(
Format(Int32),
Space(X(2)),
[-1,  2],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [1, 4, 3, 2], into: d3)
> min_over(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
1,
)
Nil

> min_over(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2)),
[[1, 2]],
)
Nil

## modulo

</>
pub fn modulo(from a: Tensor(a), divided_by b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise modulus when dividing one Tensor by another on success (broadcast as needed), or a TensorError on failure.

As with Gleam’s operators, division by zero returns zero.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [13, -13], into: d1)
> let assert Ok(x) = modulo(from: a, divided_by: from_int(0))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[0, 0],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [3, 3, -3, -3], into: d2)
> let assert Ok(x) = modulo(from: a, divided_by: b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[ 1, 2],
[ -2, -1]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 0], into: d3)
> modulo(from: b, divided_by: c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> modulo(from: b, divided_by: c)

## multiply

</>
pub fn multiply(a: Tensor(a), b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise multiplication of the given tensors on success (broadcast as needed), or a TensorError on failure.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [1, 9], into: d1)
> let assert Ok(x) = multiply(a, from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[ 3, 27],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [0, 4, 5, 9], into: d2)
> let assert Ok(x) = multiply(a, b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[ 0, 36],
[ 5, 81]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 0], into: d3)
> multiply(b, c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> multiply(b, c)

## negate

</>
pub fn negate(x: Tensor(a)) -> Tensor(a)

Returns the element-wise negation of the given Tensor.

## Examples

> let x = from_int(3)
> negate(x) |> print
Tensor(
Format(Int32),
Space(),
-3,
)
Nil

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [-0.3], into: d1)
> negate(x) |> print
Tensor(
Format(Float32),
Space(X(1)),
[0.3],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_ints(of: [-1, 8, 0], into: d3)
> negate(x) |> print
Tensor(
Format(Int32),
Space(X(1), Y(3), Z(1)),
[[[ 1],
[-8],
[ 0]]],
)
Nil

## not_equal

</>
pub fn not_equal(is a: Tensor(a), to b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise comparison of the given tensors on success (broadcast as needed), or a TensorError on failure.

Inequality is represented by 1, equality by 0, with Format retained.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [5, 4], into: d1)
> let assert Ok(x) = not_equal(is: a, to: from_int(4))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[1, 0],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [4, 4, 5, 5], into: d2)
> let assert Ok(x) = not_equal(is: a, to: b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[1, 0],
[0, 1]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 6], into: d3)
> not_equal(is: b, to: c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> not_equal(is: b, to: c)

## power

</>
pub fn power(raise a: Tensor(a), to_the b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise raising of one Tensor to the power of another on success (broadcast as needed), or a TensorError on failure.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [1, 9], into: d1)
> let assert Ok(x) = power(raise: a, to_the: from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[  1, 729],
)
Nil

> let a = reformat(a, apply: format.float32())
> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_floats(of: [0.0, 0.4, 0.5, 0.9], into: d2)
> let assert Ok(x) = power(raise: a, to_the: b)
> print(x)
Tensor(
Format(Float32),
Space(X(2), Y(2)),
[[  1.0, 2.408],
[  1.0, 7.225]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_floats(of: [4.0, 5.0, 0.0], into: d3)
> power(raise: b, to_the: c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> power(raise: b, to_the: c)

## print

</>
pub fn print(x: Tensor(a)) -> Nil

Prints the data and metadata from a given Tensor.

## Examples

> import argamak/axis.{X, Y, Z}
> import argamak/space
> let assert Ok(d2) = space.d2(X(2), Y(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4], into: d2)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[1, 2],
[3, 4]],
)
Nil

> let assert Ok(d3) = space.d3(X(2), Y(1), Z(4))
> let xs = [1, 2, 3, 4, 5, 6, 7, 8]
> let assert Ok(x) = from_ints(of: xs, into: d3)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(1), Z(4)),
[[[1, 2, 3, 4]],
[[5, 6, 7, 8]]],
)
Nil
</>
pub fn print_data(x: Tensor(a)) -> Nil

Prints the data from a given Tensor.

## Examples

> import argamak/axis.{X, Y, Z}
> import argamak/space
> let assert Ok(d2) = space.d2(X(2), Y(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4], into: d2)
> print_data(x)
[[1, 2],
[3, 4]]
Nil

> let assert Ok(d3) = space.d3(X(2), Y(1), Z(4))
> let xs = [1, 2, 3, 4, 5, 6, 7, 8]
> let assert Ok(x) = from_ints(of: xs, into: d3)
> print_data(x)
[[[1, 2, 3, 4]],
[[5, 6, 7, 8]]]
Nil

## product

</>
pub fn product(from x: Tensor(a), with filter: fn(Axis) -> Bool) -> Tensor(
a,
)

Reduces the given Tensor over select axes to the product of the values across those axes.

Any Axis for which the given filter function returns True is selected for reduction and will be removed from the reduced tensor’s Space.

If the filter function returns False for every Axis, all Axes will be retained and the operation applied to every value of the Tensor individually.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [-1, 2], into: d1)
> product(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
-2,
)
Nil

> product(x, with: fn(_) { False }) |> print
Tensor(
Format(Int32),
Space(X(2)),
[-1,  2],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [1, 4, 3, 2], into: d3)
> product(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
24,
)
Nil

> product(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2)),
[[4, 6]],
)
Nil

## rank

</>
pub fn rank(x: Tensor(a)) -> Int

Returns the rank of a given Tensor as an Int representing the number of Axes.

## Examples

> rank(from_float(0.0))
0

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [1, 2, 3], into: d1)
> rank(x)
1

> let assert Ok(d3) = space.d3(X(2), Y(2), Z(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4, 5, 6, 7, 8], into: d3)
> rank(x)
3

## reformat

</>
pub fn reformat(x: Tensor(a), apply format: Format(b)) -> Tensor(
b,
)

Changes the Format of a Tensor.

Reformatting from Float-like formats to Int-like formats truncates the data. For consistency, consider using round, floor, or ceiling beforehand.

Lowering precision may lead to an overflow or underflow, the outcome of which depends on platform and compiler.

## Examples

> import argamak/format
> reformat(from_int(0), apply: format.float32()) |> print
Tensor(
Format(Float32),
Space(),
0.0,
)
Nil

> import argamak/axis.{Infer}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [1.0, 2.0, 3.0], into: d1)
> reformat(x, apply: format.int32()) |> print
Tensor(
Format(Int32),
Space(X(3)),
[1, 2, 3],
)
Nil

## remainder

</>
pub fn remainder(from a: Tensor(a), divided_by b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise remainder when dividing one Tensor by another on success (broadcast as needed), or a TensorError on failure.

As with Gleam’s operators, division by zero returns zero.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [13, -13], into: d1)
> let assert Ok(x) = remainder(from: a, divided_by: from_int(0))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[0, 0],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [3, 3, -3, -3], into: d2)
> let assert Ok(x) = remainder(from: a, divided_by: b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[ 1, -1],
[ 1, -1]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 0], into: d3)
> remainder(from: b, divided_by: c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> remainder(from: b, divided_by: c)

## reshape

</>
pub fn reshape(put x: Tensor(a), into new_space: Space) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor placed into a given Space on success, or a TensorError on failure.

The new Space may have a single Infer Axis, the size of which will be determined based on the given Tensor.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = reshape(put: from_float(1.0), into: d1)
> print(x)
Tensor(
Format(Float32),
Space(X(1)),
[1.0],
)
Nil

> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [1.0, 2.0, 3.0, 4.0], into: d1)
> let assert Ok(d2) = space.d2(X(2), Y(2))
> let assert Ok(x) = reshape(put: x, into: d2)
> print(x)
Tensor(
Format(Float32),
Space(X(2), Y(2)),
[[1.0, 2.0],
[3.0, 4.0]],
)
Nil

> let assert Ok(d2) = space.d2(X(2), Infer("Y"))
> let xs = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
> let assert Ok(x) = from_floats(of: xs, into: d2)
> let assert Ok(d3) = space.d3(Infer("X"), Y(2), Z(2))
> let assert Ok(x) = reshape(put: x, into: d3)
> print(x)
Tensor(
Format(Float32),
Space(X(2), Y(2), Z(2)),
[[[1.0, 2.0],
[3.0, 4.0]],
[[5.0, 6.0],
[7.0, 8.0]]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Y(1), Z(1))
> let assert Ok(x) = from_floats(of: [1.0], into: d3)
> let assert Ok(x) = reshape(put: x, into: space.new())
> print_data(x)
1.0
Nil

> reshape(put: x, into: d2)
Error(IncompatibleShape)

## round

</>
pub fn round(x: Tensor(a)) -> Tensor(a)

Returns the element-wise rounding of the given Tensor, with Format retained.

## Examples

> let x = from_int(3)
> round(x) |> print
Tensor(
Format(Int32),
Space(),
3,
)
Nil

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [-0.5], into: d1)
> round(x) |> print
Tensor(
Format(Float32),
Space(X(1)),
[-1.0],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_floats(of: [-1.2, 7.8, 0.0], into: d3)
> round(x) |> print
Tensor(
Format(Float32),
Space(X(1), Y(3), Z(1)),
[[[-1.0],
[ 8.0],
[ 0.0]]],
)
Nil

## shape

</>
pub fn shape(x: Tensor(a)) -> List(Int)

Returns the shape of a given Tensor.

## Examples

> shape(from_float(0.0))
[]

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [1, 2, 3], into: d1)
> shape(x)
[3]

> let assert Ok(d3) = space.d3(X(2), Y(2), Z(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4, 5, 6, 7, 8], into: d3)
> shape(x)
[2, 2, 2]

## sign

</>
pub fn sign(x: Tensor(a)) -> Tensor(a)

Returns an element-wise indication of the sign of the given Tensor.

Positive numbers are represented by 1, negative numbers by -1, and zero by 0, with Format retained.

## Examples

> let x = from_int(3)
> sign(x) |> print
Tensor(
Format(Int32),
Space(),
1,
)
Nil

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [-0.3], into: d1)
> sign(x) |> print
Tensor(
Format(Float32),
Space(X(1)),
[-1.0],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_ints(of: [-1, 8, 0], into: d3)
> sign(x) |> print
Tensor(
Format(Int32),
Space(X(1), Y(3), Z(1)),
[[[-1],
[ 1],
[ 0]]],
)
Nil

## size

</>
pub fn size(x: Tensor(a)) -> Int

Returns the number of values in a given Tensor.

## Examples

> size(from_float(0.0))
1

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [1, 2, 3], into: d1)
> size(x)
3

> let assert Ok(d3) = space.d3(X(2), Y(2), Z(2))
> let assert Ok(x) = from_ints(of: [0, 1, 2, 3, 4, 5, 6, 7], into: d3)
> size(x)
8

## space

</>
pub fn space(x: Tensor(a)) -> Space

Returns the Space a given Tensor is currently in.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> space(from_float(0.0)) |> space.axes
[]

> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [1, 2, 3], into: d1)
> space(x) |> space.axes
[X(3)]

> let assert Ok(d3) = space.d3(X(2), Y(2), Z(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4, 5, 6, 7, 8], into: d3)
> space(x) |> space.axes
[X(2), Y(2), Z(2)]

## square_root

</>
pub fn square_root(x: Tensor(a)) -> Result(Tensor(a), TensorError)

Results in the element-wise square root of the given Tensor on success, or a TensorError on failure, with Format retained.

## Examples

> let assert Ok(x) = square_root(from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(),
1,
)
Nil

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_floats(of: [1.5], into: d1)
> let assert Ok(x) = square_root(x)
> print(x)
Tensor(
Format(Float32),
Space(X(1)),
[1.225],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_floats(of: [1.2, 7.8, 0.0], into: d3)
> let assert Ok(x) = square_root(x)
> print(x)
Tensor(
Format(Float32),
Space(X(1), Y(3), Z(1)),
[[[1.095],
[2.793],
[  0.0]]],
)
Nil

> square_root(from_float(-0.1))
Error(InvalidData)

## squeeze

</>
pub fn squeeze(from x: Tensor(a), with filter: fn(Axis) -> Bool) -> Tensor(
a,
)

Removes from the given Tensor axes of size 1 for which filter returns True.

## Examples

> let x = from_int(3)
> squeeze(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
3,
)
Nil

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [3], into: d1)
> squeeze(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
3,
)
Nil

> squeeze(x, with: fn(_) { False }) |> print
Tensor(
Format(Int32),
Space(X(1)),
[3],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(x) = from_ints(of: [1, 2], into: d3)
> squeeze(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(Y(2)),
[1, 2],
)
Nil

> squeeze(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2)),
[[1, 2]],
)
Nil

## subtract

</>
pub fn subtract(from a: Tensor(a), value b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

Results in a Tensor that is the element-wise subtraction of one Tensor from another on success (broadcast as needed), or a TensorError on failure.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [0, 9], into: d1)
> let assert Ok(x) = subtract(from: a, value: from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[-3,  6],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [0, 4, 5, 0], into: d2)
> let assert Ok(x) = subtract(from: a, value: b)
> print(x)
Tensor(
Format(Int32),
Space(X(2), Y(2)),
[[ 0,  5],
[-5,  9]],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(1))
> let assert Ok(c) = from_ints(of: [4, 5, 0], into: d3)
> subtract(from: b, value: c)
Error(SpaceErrors([
SpaceError(CannotMerge, [Y(3), X(2)]),
SpaceError(CannotMerge, [Z(1), Y(2)]),
]))

> let assert Ok(d3) = space.d3(Z(1), Infer("X"), Y(1))
> let assert Ok(c) = reshape(put: c, into: d3)
> subtract(from: b, value: c)

## sum

</>
pub fn sum(from x: Tensor(a), with filter: fn(Axis) -> Bool) -> Tensor(
a,
)

Reduces the given Tensor over select axes to the sum of the values across those axes.

Any Axis for which the given filter function returns True is selected for reduction and will be removed from the reduced tensor’s Space.

If the filter function returns False for every Axis, all Axes will be retained and the operation applied to every value of the Tensor individually.

## Examples

> import argamak/axis.{Infer, X, Y, Z}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [-1, 2], into: d1)
> sum(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
1,
)
Nil

> sum(x, with: fn(_) { False }) |> print
Tensor(
Format(Int32),
Space(X(2)),
[-1,  2],
)
Nil

> let assert Ok(d3) = space.d3(X(1), Infer("Y"), Z(2))
> let assert Ok(x) = from_ints(of: [2, 4, 3, 0], into: d3)
> sum(x, with: fn(_) { True }) |> print
Tensor(
Format(Int32),
Space(),
9,
)
Nil

> sum(x, with: fn(a) { axis.name(a) == "Z" }) |> print
Tensor(
Format(Int32),
Space(X(1), Y(2)),
[[6, 3]],
)
Nil

## to_bool

</>
pub fn to_bool(x: Tensor(a)) -> Result(Bool, TensorError)

Results in a Bool converted from a dimensionless Tensor on success, or a TensorError on failure.

Nonzero values become True, otherwise False.

## Examples

> to_bool(from_float(0.0))
Ok(False)

> to_bool(from_int(1))
Ok(True)

import argamak/axis.{Infer}
import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [1], into: d1)
> to_bool(x)
Error(IncompatibleShape)

## to_bools

</>
pub fn to_bools(x: Tensor(a)) -> List(Bool)

Converts a Tensor into a flat list of booleans.

Nonzero values become True, otherwise False.

## Examples

> to_bools(from_float(0.0))
[False]

> import argamak/axis.{X, Y}
> import argamak/space
> let assert Ok(d2) = space.d2(X(3), Y(1))
> let assert Ok(x) = from_ints(of: [1, 0, -3], into: d2)
> to_bools(x)
[True, False, True]

## to_float

</>
pub fn to_float(x: Tensor(a)) -> Result(Float, TensorError)

Results in a Float converted from a dimensionless Tensor on success, or a TensorError on failure.

Values that are infinite will be clipped to min/max finite values based on the current Format.

## Examples

> to_float(from_float(0.0))
Ok(0.0)

> to_float(from_int(0))
Ok(0.0)

import argamak/axis.{Infer}
import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [1], into: d1)
> to_float(x)
Error(IncompatibleShape)

## to_floats

</>
pub fn to_floats(x: Tensor(a)) -> List(Float)

Converts a Tensor into a flat list of floats.

Values that are infinite will be clipped to min/max finite values based on the current Format.

## Examples

> to_floats(from_int(0))
[0.0]

> import argamak/axis.{X, Y}
> import argamak/space
> let assert Ok(d2) = space.d2(X(3), Y(1))
> let assert Ok(x) = from_floats(of: [1.0, 2.0, 3.0], into: d2)
> to_floats(x)
[1.0, 2.0, 3.0]

## to_int

</>
pub fn to_int(x: Tensor(a)) -> Result(Int, TensorError)

Results in an Int converted from a dimensionless Tensor on success, or a TensorError on failure.

Values that are infinite will be clipped to min/max finite values based on the current Format.

## Examples

> to_int(from_float(0.0))
Ok(0)

> to_int(from_int(0))
Ok(0)

import argamak/axis.{Infer}
import argamak/space
> let assert Ok(d1) = space.d1(Infer("X"))
> let assert Ok(x) = from_ints(of: [1], into: d1)
> to_int(x)
Error(IncompatibleShape)

## to_ints

</>
pub fn to_ints(x: Tensor(a)) -> List(Int)

Converts a Tensor into a flat list of integers.

Values that are infinite will be clipped to min/max finite values based on the current Format.

## Examples

> to_ints(from_float(0.0))
[0]

> import argamak/axis.{X, Y}
> import argamak/space
> let assert Ok(d2) = space.d2(X(3), Y(1))
> let assert Ok(x) = from_ints(of: [1, 2, 3], into: d2)
> to_ints(x)
[1, 2, 3]

## to_native

</>
pub fn to_native(x: Tensor(a)) -> Native

Converts a Tensor into its Native representation.

## Examples

> @external(erlang, "Elixir.Nx", "rank")
> fn erlang_rank(tensor: Native) -> Int
> to_native(from_int(3)) |> erlang_rank
0

## to_string

</>
pub fn to_string(from x: Tensor(a), return record_or_data: ToString, wrap_at column: Int) -> String

Returns a string representation of the given Tensor, either the whole Record or just its Data.

Takes a column argument for which the special values -1 and 0 represent default and no wrapping, respectively.

## Examples

> import argamak/axis.{X, Y, Z}
> import argamak/space
> let assert Ok(d2) = space.d2(X(2), Y(2))
> let assert Ok(x) = from_ints(of: [1, 2, 3, 4], into: d2)
> to_string(from: x, return: Data, wrap_at: 0)
"[[1, 2],
[3, 4]]"

> let assert Ok(d3) = space.d3(X(2), Y(1), Z(4))
> let xs = [1, 2, 3, 4, 5, 6, 7, 8]
> let assert Ok(x) = from_ints(of: xs, into: d3)
> do_print(from: x, return: Record, wrap_at: 10)
"Tensor(
Format(Int32),
Space(X(2), Y(1), Z(4)),
[[[1, 2,
3, 4]],
[[5, 6,
7, 8]]],
)"

## try_divide

</>
pub fn try_divide(from a: Tensor(a), by b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

A variant of divide that results in a TensorError if any value of the divisor is zero.

## Examples

> import argamak/axis.{Infer, X, Y}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [1, 9], into: d1)
> let assert Ok(x) = try_divide(from: a, by: from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[0, 3],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [0, 4, 5, 9], into: d2)
> try_divide(from: a, by: b)
Error(ZeroDivision)

## try_modulo

</>
pub fn try_modulo(from a: Tensor(a), divided_by b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

A variant of modulo that results in a TensorError if any value of the divisor is zero.

## Examples

> import argamak/axis.{Infer, X, Y}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [1, 9], into: d1)
> let assert Ok(x) = try_modulo(from: a, divided_by: from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[1, 0],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [0, 4, 5, 9], into: d2)
> try_modulo(from: a, divided_by: b)
Error(ZeroDivision)

## try_remainder

</>
pub fn try_remainder(from a: Tensor(a), divided_by b: Tensor(a)) -> Result(
Tensor(a),
TensorError,
)

A variant of remainder that results in a TensorError if any value of the divisor is zero.

## Examples

> import argamak/axis.{Infer, X, Y}
> import argamak/space
> let assert Ok(d1) = space.d1(Infer("Y"))
> let assert Ok(a) = from_ints(of: [1, 9], into: d1)
> let assert Ok(x) = try_remainder(from: a, divided_by: from_int(3))
> print(x)
Tensor(
Format(Int32),
Space(Y(2)),
[1, 0],
)
Nil

> let assert Ok(d2) = space.d2(Infer("X"), Y(2))
> let assert Ok(b) = from_ints(of: [0, 4, 5, 9], into: d2)
> try_remainder(from: a, divided_by: b)
Error(ZeroDivision)