# Encoding

> UForm for Mojo

Every encode verb takes its inputs as tapes, elements end to end with one more offset than items, then the `Outputs` to keep, the arena, and an optional `EncodeConfig` naming the scalar outputs land as and a report slot:

```mojo
var stats = EncodeStats()
var config = EncodeConfig(outputs_scalar=ScalarKind.BF16, stats=Pointer(to=stats))
var images = model.image_encode(files, Outputs.EMBEDDINGS | Outputs.TOKEN_VECTORS, arena, config)
var pixels = model.image_encode_pixels(rgb, heights, widths, Outputs.EMBEDDINGS, arena)
var clips = model.video_encode(videos, Outputs.EMBEDDINGS, arena)
var sounds = model.audio_encode_samples(samples, 16000, Outputs.EMBEDDINGS, arena)
var probabilities = model.text_choose(states, choices, arena)  # one F32 per legal byte
```

`from uform import Outputs, EncodeStats, Encoded, …`

## Outputs

The surfaces an encode verb keeps from its one forward, named after the fields they fill. Binding-only; it decides which output pointers a verb passes.

```mojo
struct Outputs
```

- `EMBEDDINGS` = `Outputs(UInt32(1))`: One pooled embedding per item, past the attention pool and the projection head.
- `STATES` = `Outputs(UInt32(2))`: One final-norm state per token left after truncation.
- `TOKEN_VECTORS` = `Outputs(UInt32(4))`: One unit vector of the token head per token left after truncation; a model without a token head fails the call with [`UNSUPPORTED`](https://www.unum.cloud/docs/uform/mojo/errors.md#UNSUPPORTED).
- `code` `UInt32`: The surfaces kept, one flag each.

Conforms to: `Copyable`, `Deinitable`, `Equatable`, `ImplicitlyCopyable`, `Movable`, `RegisterPassable`, `TrivialRegisterPassable`

## __or__

Both sets of surfaces.

```mojo
def __or__(self, other: Self) -> Self
```

## contains

Whether every surface `other` names is kept.

```mojo
def contains(self, other: Self) -> Bool
```

## EncodeStats

What an encode call reports beside its outputs: `uform_text_encode_stats_t`, and the image, video and audio reports that share its two fields.

```mojo
struct EncodeStats
```

- `truncated` `c_size_t`: Items cut at the model's context.
- `tokens` `c_size_t`: Tokens the call encoded after truncation: bytes, patches, tubes or frames.

Conforms to: `Copyable`, `Defaultable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`

## __init__

Zeroes both fields, which is what a failed call leaves.

```mojo
def __init__(out self)
```

## Encoded

What an encode verb wrote into the arena it borrows: the surfaces its [`Outputs`](#Outputs) named. Binding-only.

```mojo
struct Encoded[origin: MutOrigin]
```

- `origin` (comptime): The arena the surfaces live in, which this result borrows.

- `arena` `Pointer[Arena, origin]`: The arena holding the surfaces.
- `generation` `Int`: The arena's call these surfaces came from, so a read after a later call is refused.
- `kept` `Outputs`: The surfaces the call kept.
- `written` `EncodedArguments`: The views the engine wrote, inside the arena.
- `count` `Int`: Items the call encoded.

Conforms to: `Deinitable`, `Movable`

## embeddings

One pooled embedding of the model's dimensions per item, without normalization; absent unless kept.

```mojo
def embeddings(self) -> Optional[Rows[origin]]
```

## states

One final-norm state per token left after truncation, item by item; absent unless kept.

```mojo
def states(self) -> Optional[RowsTape[origin]]
```

## token_vectors

One unit vector of the model's token width per token left after truncation, item by item; absent unless kept.

```mojo
def token_vectors(self) -> Optional[RowsTape[origin]]
```

## EncodeConfig

The knobs every encode verb shares, the verbs over texts, images, clips and recordings alike.

```mojo
struct EncodeConfig[stats_origin: MutOrigin = MutUntrackedOrigin]
```

- `stats_origin` (comptime): The lent report slot's origin, inferred where one is lent.

- `outputs_scalar` `ScalarKind`: The scalar type every output lands as.
- `progress` `Progress`: Reports the items encoded, and stops the call where it says to.
- `stats` `Optional[Pointer[EncodeStats, stats_origin]]`: Receives the truncation report, overwritten by the call; absent skips it.

Conforms to: `Copyable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`

## __init__

Names only the knobs that differ from the defaults.

```mojo
def __init__(
    out self,
    *,
    outputs_scalar: ScalarKind = ScalarKind.F32,
    progress: Progress = Progress(),
    stats: Optional[Pointer[EncodeStats, stats_origin]] = Optional()
)
```

## ScalarKind

The scalar types a model computes in and its outputs land as, `uform_scalar_t` named by width.

```mojo
struct ScalarKind
```

Named [`ScalarKind`](#ScalarKind) because Mojo's own `Scalar` is the element type it describes. The `xN`
suffixes spell how many logical dimensions share one byte. [`Library.scalar_name`](https://www.unum.cloud/docs/uform/mojo/design.md#scalar_name) spells each one
as the engine does.

- `UNKNOWN` = `ScalarKind(Int32(0))`: No scalar named, an unset field refused rather than written at the wrong width.
- `F64` = `ScalarKind(Int32(1))`: IEEE-754 binary64.
- `F32` = `ScalarKind(Int32(2))`: IEEE-754 binary32.
- `BF16` = `ScalarKind(Int32(3))`: Truncated f32 with an 8-bit exponent and a 7-bit mantissa.
- `F16` = `ScalarKind(Int32(4))`: IEEE-754 binary16.
- `E5M2` = `ScalarKind(Int32(5))`: FP8 with a 5-bit exponent, with infinities and NaNs.
- `E4M3` = `ScalarKind(Int32(6))`: FP8 with a 4-bit exponent, no infinities.
- `E3M2` = `ScalarKind(Int32(7))`: FP6 with a 3-bit exponent, byte-aligned with two padding bits.
- `E2M3` = `ScalarKind(Int32(8))`: FP6 with a 2-bit exponent, byte-aligned with two padding bits.
- `I8` = `ScalarKind(Int32(10))`: 8-bit signed integer.
- `I4X2` = `ScalarKind(Int32(11))`: Two signed nibbles per byte, even dimensions in the low nibble.
- `I32` = `ScalarKind(Int32(12))`: 32-bit signed integer.
- `U8` = `ScalarKind(Int32(20))`: 8-bit unsigned integer, the element of UTF-8 text and of encoded files.
- `U4X2` = `ScalarKind(Int32(21))`: Two unsigned nibbles per byte, even dimensions in the low nibble.
- `U1X8` = `ScalarKind(Int32(22))`: Eight single-bit dimensions per byte, the sign of each embedding dimension.
- `code` `c_int`: The raw `uform_scalar_t` value the ABI exchanges.

Conforms to: `Copyable`, `Deinitable`, `Equatable`, `ImplicitlyCopyable`, `Movable`, `RegisterPassable`, `TrivialRegisterPassable`

## of

The kind a Mojo scalar type stores one-to-one; the packed and FP6 kinds have none. Binding-only.

```mojo
def of[dtype: DType]() -> Self
```

## bits_per_scalar

How many bits one logical dimension occupies, which sub-byte kinds share; zero for [`UNKNOWN`](#UNKNOWN).

```mojo
def bits_per_scalar(self) -> Int
```

## stores

Whether values of this kind read as whole `dtype` elements: equal widths, or bytes for packed kinds. Binding-only.

```mojo
def stores[dtype: DType](self) -> Bool
```

## BytesView

A borrowed run of bytes and its length, never null-terminated: every path, buffer and name.

```mojo
struct BytesView[origin: ImmOrigin = ImmUntrackedOrigin]
```

- `origin` (comptime): The borrowed storage, which the view keeps alive for as long as it is used.

- `data` `Pointer[UInt8, origin]`: The first byte.
- `length` `Int`: How many bytes the run covers, since nothing terminates it.

Conforms to: `Copyable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`

## of

Borrows a string's bytes, with no terminator manufactured.

```mojo
def of[text_origin: ImmOrigin, //](text: StringSpan[text_origin]) -> BytesView[text_origin]
```

```mojo
def of[bytes_origin: ImmOrigin, //](bytes: Span[UInt8, bytes_origin]) -> BytesView[bytes_origin]
```

Borrows a run of raw bytes, such as a checkpoint held in memory.

## *

The C layout, erased only inside a verb so the borrow lives through the call.

```mojo
def arguments(self) -> BytesViewArguments
```

## TapeView

A borrowed ragged batch laid out as Apache Arrow lays one out: elements end to end, and one more offset than entries around them.

```mojo
struct TapeView[origin: ImmOrigin = ImmUntrackedOrigin]
```

Entry `i` spans elements `offsets[i]` up to `offsets[i + 1]`. The elements may live in host or
device memory; the offsets always live in host memory, since they drive host-side dispatch.

- `origin` (comptime): The borrowed elements and offsets, which the view keeps alive for as long as it is used.

- `data` `Pointer[NoneType, origin]`: The first element, which every offset counts from.
- `offsets` `Pointer[UInt, origin]`: The entries' boundaries, one more of them than entries.
- `count` `Int`: Entries in the tape, which the verb takes as its `count`.
- `scalar` `ScalarKind`: The scalar type the elements hold: [`U8`](#U8) for text and encoded files, [`F32`](#F32) for decoded samples.

Conforms to: `Copyable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`, `Sized`

## __len__

The entries in the tape.

```mojo
def __len__(self) -> Int
```

## of

Reads host elements and their offsets as a tape, refusing offsets that end past the elements.

```mojo
def of[dtype: DType, data_origin: ImmOrigin, offsets_origin: ImmOrigin, //](
    data: Span[Scalar[dtype], data_origin],
    offsets: Span[UInt, offsets_origin],
    scalar: ScalarKind = ScalarKind.of[dtype]()
) -> TapeView[origin_of(data_origin, offsets_origin)]
```

```mojo
def of[dtype: DType, data_origin: ImmOrigin, offsets_origin: ImmOrigin, //](
    data: Pointer[Scalar[dtype], data_origin],
    offsets: Span[UInt, offsets_origin],
    scalar: ScalarKind = ScalarKind.of[dtype]()
) -> TapeView[origin_of(data_origin, offsets_origin)]
```

Reads elements behind a host or device pointer, such as `buffer.unsafe_ptr()` of a MAX `DeviceBuffer`, with their offsets in host memory.

Raises: [`Error`](https://www.unum.cloud/docs/uform/mojo/errors.md#Error) with [`SHAPE_MISMATCH`](https://www.unum.cloud/docs/uform/mojo/errors.md#SHAPE_MISMATCH) when no offset is given or the last one exceeds `len(data)`.

## Rows

Rows a call wrote into the arena it borrows, one per item, packed, `uform_rows_view_t` read in place.

```mojo
struct Rows[origin: MutOrigin]
```

- `origin` (comptime): The arena the rows live in, which this result borrows.

- `arena` `Pointer[Arena, origin]`: The arena holding the rows.
- `generation` `Int`: The arena's call these rows came from, so a read after a later call is refused.
- `view` `RowsViewArguments`: The first row, the stride, the width and the kind, as the engine wrote them.
- `count` `Int`: Rows written.

Conforms to: `Copyable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`, `Sized`

## __len__

The rows written.

```mojo
def __len__(self) -> Int
```

## columns

Values per row, the model's embedding dimensions or token width.

```mojo
def columns(self) -> Int
```

## stride

Bytes between the starts of consecutive rows.

```mojo
def stride(self) -> Int
```

## scalar

The scalar type the rows hold.

```mojo
def scalar(self) -> ScalarKind
```

## row

One row's values, or its packed bytes for a sub-byte kind, borrowed from the arena.

```mojo
def row[dtype: DType](ref self, row: Int) -> Span[Scalar[dtype], origin_of(self)]
```

Raises: [`Error`](https://www.unum.cloud/docs/uform/mojo/errors.md#Error) with [`DEVICE`](https://www.unum.cloud/docs/uform/mojo/errors.md#DEVICE) over device memory, [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/uform/mojo/errors.md#INVALID_ARGUMENT) once a later call rewound the arena, or when the rows hold a kind `dtype` does not store.

## values

Every row's values end to end, refused for padded rows.

```mojo
def values[dtype: DType](ref self) -> Span[Scalar[dtype], origin_of(self)]
```

Raises: [`Error`](https://www.unum.cloud/docs/uform/mojo/errors.md#Error) with [`DEVICE`](https://www.unum.cloud/docs/uform/mojo/errors.md#DEVICE) over device memory, [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/uform/mojo/errors.md#INVALID_ARGUMENT) once a later call rewound the arena or for another kind, and with [`UNSUPPORTED_LAYOUT`](https://www.unum.cloud/docs/uform/mojo/errors.md#UNSUPPORTED_LAYOUT) when the rows are padded.

## RowsTape

A ragged run of rows a call wrote into the arena it borrows, as many per item as the item had tokens left after truncation, `uform_rows_tape_view_t` read in place.

```mojo
struct RowsTape[origin: MutOrigin]
```

- `origin` (comptime): The arena the rows live in, which this result borrows.

- `arena` `Pointer[Arena, origin]`: The arena holding the rows.
- `generation` `Int`: The arena's call these rows came from, so a read after a later call is refused.
- `view` `RowsTapeViewArguments`: The rows and their offsets, as the engine wrote them.
- `count` `Int`: Items the call wrote rows for.

Conforms to: `Copyable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`, `Sized`

## __len__

The items the call wrote rows for.

```mojo
def __len__(self) -> Int
```

## offsets

The items' boundaries in rows, one more of them than items.

```mojo
def offsets(ref self) -> Span[UInt, origin_of(self)]
```

Raises: [`Error`](https://www.unum.cloud/docs/uform/mojo/errors.md#Error) with [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/uform/mojo/errors.md#INVALID_ARGUMENT) once a later call rewound the arena, or [`DEVICE`](https://www.unum.cloud/docs/uform/mojo/errors.md#DEVICE) over device memory.

## rows

Every item's rows end to end, as one run.

```mojo
def rows(self) -> Rows[origin]
```

Raises: [`Error`](https://www.unum.cloud/docs/uform/mojo/errors.md#Error) with [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/uform/mojo/errors.md#INVALID_ARGUMENT) once a later call rewound the arena, or [`DEVICE`](https://www.unum.cloud/docs/uform/mojo/errors.md#DEVICE) over device memory.

## item

One item's rows.

```mojo
def item(self, item: Int) -> Rows[origin]
```

Raises: [`Error`](https://www.unum.cloud/docs/uform/mojo/errors.md#Error) with [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/uform/mojo/errors.md#INVALID_ARGUMENT) once a later call rewound the arena, or [`DEVICE`](https://www.unum.cloud/docs/uform/mojo/errors.md#DEVICE) over device memory.

## Tape

A ragged run of values a call wrote into the arena it borrows, `uform_tape_view_t` read in place.

```mojo
struct Tape[origin: MutOrigin]
```

- `origin` (comptime): The arena the values live in, which this result borrows.

- `arena` `Pointer[Arena, origin]`: The arena holding the values.
- `generation` `Int`: The arena's call these values came from, so a read after a later call is refused.
- `view` `TapeViewArguments`: The values and their offsets, as the engine wrote them.
- `count` `Int`: Items the call wrote values for.

Conforms to: `Copyable`, `Deinitable`, `ImplicitlyCopyable`, `Movable`, `Sized`

## __len__

The items the call wrote values for.

```mojo
def __len__(self) -> Int
```

## scalar

The scalar type the values hold.

```mojo
def scalar(self) -> ScalarKind
```

## offsets

The items' boundaries in values, one more of them than items.

```mojo
def offsets(ref self) -> Span[UInt, origin_of(self)]
```

Raises: [`Error`](https://www.unum.cloud/docs/uform/mojo/errors.md#Error) with [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/uform/mojo/errors.md#INVALID_ARGUMENT) once a later call rewound the arena, or [`DEVICE`](https://www.unum.cloud/docs/uform/mojo/errors.md#DEVICE) over device memory.

## item

One item's values.

```mojo
def item[dtype: DType](ref self, item: Int) -> Span[Scalar[dtype], origin_of(self)]
```

Raises: [`Error`](https://www.unum.cloud/docs/uform/mojo/errors.md#Error) with [`DEVICE`](https://www.unum.cloud/docs/uform/mojo/errors.md#DEVICE) over device memory, [`INVALID_ARGUMENT`](https://www.unum.cloud/docs/uform/mojo/errors.md#INVALID_ARGUMENT) once a later call rewound the arena, or when the values hold a kind `dtype` does not store.

