# Module shapeshifting

# Procs

proc transpose(t: Tensor): Tensor {.

noInit, noSideEffect, inline.}-
Transpose a Tensor.

For N-d Tensor with shape (0, 1, 2 ... n-1) the resulting tensor will have shape (n-1, ... 2, 1, 0)

Data is not copied or modified, only metadata is modified.

Source Edit proc asContiguous[T](t: Tensor[T]; layout: OrderType = rowMajor; force: bool = false): Tensor[ T] {.

noInit.}-
Transform a tensor with general striding to a Tensor with contiguous layout.

By default tensor will be rowMajor.

The layout is kept if the tensor is already contiguous (C Major or F major) The "force" parameter can force re-ordering to a specific layout.

Result is always a fully packed tensor even if the input is a contiguous slice.

Source Edit proc reshape(t: Tensor; new_shape: varargs[int]): Tensor {.

noInit.}-
Reshape a tensor
- Input:
- a tensor
- a new shape. Number of elements must be the same

- Returns:
- a tensor with the same data but reshaped.

proc reshape(t: Tensor; new_shape: MetadataArray): Tensor {.

noInit.}-
Reshape a tensor
- Input:
- a tensor
- a new shape. Number of elements must be the same

- Returns:
- a tensor with the same data but reshaped.

proc broadcast[T](t: Tensor[T]; shape: varargs[int]): Tensor[T] {.

noInit, noSideEffect.}-
Explicitly broadcast a tensor to the specified shape.

Dimension(s) of size 1 can be expanded to arbitrary size by replicating values along that dimension.

- Warning ⚠:
- A broadcasted tensor should not be modified and only used for computation.

proc broadcast[T](t: Tensor[T]; shape: MetadataArray): Tensor[T] {.

noInit, noSideEffect.}-
Explicitly broadcast a tensor to the specified shape.

Dimension(s) of size 1 can be expanded to arbitrary size by replicating values along that dimension.

- Warning ⚠:
- A broadcasted tensor should not be modified and only used for computation.

proc broadcast[T: SomeNumber](val: T; shape: varargs[int]): Tensor[T] {.

noInit, noSideEffect.}-
Broadcast a number
- Input:
- a number to be broadcasted
- a tensor shape that will be broadcasted to

- Returns:
- a tensor with the broadcasted shape where all elements has the broadcasted value

The broadcasting is made using tensor data of size 1 and 0 strides, i.e. the operation is memory efficient.

- Warning ⚠:
- A broadcasted tensor should not be modified and only used for computation. Modifying any value from this broadcasted tensor will change all its values.

proc broadcast[T: SomeNumber](val: T; shape: MetadataArray): Tensor[T] {.

noInit, noSideEffect.}-
Broadcast a number
- Input:
- a number to be broadcasted
- a tensor shape that will be broadcasted to

- Returns:
- a tensor with the broadcasted shape where all elements has the broadcasted value

The broadcasting is made using tensor data of size 1 and 0 strides, i.e. the operation is memory efficient.

- Warning ⚠:
- A broadcasted tensor should not be modified and only used for computation. Modifying any value from this broadcasted tensor will change all its values.

proc broadcast2[T](a, b: Tensor[T]): tuple[a, b: Tensor[T]] {.

noSideEffect, noInit.}-
Broadcast 2 tensors so they have compatible shapes for element-wise computations.

Tensors in the tuple can be accessed with output.a and output.b

The returned broadcasted Tensors share the underlying data with the input.

Dimension(s) of size 1 can be expanded to arbitrary size by replicating values along that dimension.

- Warning ⚠:
- This is a no-copy operation, data is shared with the input. This proc does not guarantee that a
`let`value is immutable. A broadcasted tensor should not be modified and only used for computation.

proc permute(t: Tensor; dims: varargs[int]): Tensor {.

noInit, noSideEffect.}-
Permute dimensions of a tensors
- Input:
- a tensor
- the new dimension order

- Returns:
- a tensor with re-order dimension

- Usage:
a.permute(0,2,1) # dim 0 stays at 0, dim 1 becomes dim 2 and dim 2 becomes dim 1

proc concat[T](t_list: varargs[Tensor[T]]; axis: int): Tensor[T] {.

noInit.}-
Concatenate tensors
- Input:
- Tensors
- An axis (dimension)

- Returns:
- a tensor

proc squeeze(t: AnyTensor): AnyTensor {.

noInit, noSideEffect.}-
Squeeze tensors. For example a Tensor of shape [4,1,3] will become [4,3]
- Input:
- a tensor

- Returns:
- a tensor with singleton dimensions collapsed

proc squeeze(t: Tensor; axis: int): Tensor {.

noInit, noSideEffect.}-
Collapse the given axis, if the dimension is not 1, it does nothing.
- Input:
- a tensor
- an axis (dimension)

- Returns:
- a tensor with that axis collapsed, if it was a singleton dimension

proc unsqueeze(t: Tensor; axis: int): Tensor {.

noInit, noSideEffect.}-
Insert a new axis just before the given axis, increasing the tensor dimension (rank) by 1
- Input:
- a tensor
- an axis (dimension)

- Returns:
- a tensor with that new axis

proc stack[T](tensors: varargs[Tensor[T]]; axis: int = 0): Tensor[T] {.

noInit.}-
Join a sequence of tensors along a new axis into a new tensor.
- Input:
- a tensor
- an axis (dimension)

- Returns:
- a new stacked tensor along the new axis