Physical Tensor Storage #
Storage α selects the physical buffer used by tensors with scalar type
α. Arbitrary scalar types retain ordinary Array α storage. Float uses
Lean's unboxed FloatArray runtime representation, while UInt8 uses
ByteArray.
The toArray laws are the proof boundary: the kernel reasons about an ordinary
array observation, while compiled code calls the specialized buffer operations
directly. Selected pointwise, slice, and transpose operations also have
proof-visible Lean definitions with native compiled replacements. The Lean
theorems describe those definitions; agreement of the external C bodies is a
native runtime boundary documented in docs/TRUST_BOUNDARIES.md.
Run the tail-recursive engine used by nativeFinFoldl.
hBound and the callback's index proof are erased. The executable loop
therefore carries only an unboxed bound, counter, and accumulator.
Instances For
Fold over Fin length with a platform-native loop counter.
The caller supplies a native bound together with an erased proof that it represents the semantic length.
Instances For
nativeFinFoldl computes exactly Fin.foldl.
Generated kernels can execute with an unboxed counter while proofs continue to reason about the standard finite enumeration.
A native callback computes the semantic finite fold when it agrees with the semantic callback at every represented index.
Physical tensor storage for one scalar type.
The buffer operations are used by generated native kernels. toArray is their
proof-facing observation and may allocate when explicitly evaluated; optimized
code therefore stays on Buffer, get, uget, push, and appendSlice.
- Buffer : Type u
Physical row-major scalar buffer.
Allocate an empty buffer with room for the requested number of scalars.
Append one scalar.
Append a contiguous half-open source interval to an output buffer.
Traverse the physical buffer in row-major order.
Number of scalar entries in the buffer.
Copy one physical entry from a source buffer into an output buffer.
Unlike
push output (uget source index ...), this primitive does not expose the scalar at the caller boundary. Generic arrays can therefore transfer an existing boxed object directly, while scalar arrays read and write their unboxed representation.- gather (source : Buffer α) (length : ℕ) (bound : USize) : bound.toNat = length → (sourceIndices : (index : USize) → index.toNat < length → USize) → (∀ (index : USize) (hIndex : index.toNat < length), (sourceIndices index hIndex).toNat < size source) → Buffer α
Build a buffer by gathering physical entries from one source buffer.
The storage implementation owns the complete loop so backend selection happens once per tensor rather than once per copied scalar.
- gather_eq_nativeFinFoldl (source : Buffer α) (length : ℕ) (bound : USize) (hBound : bound.toNat = length) (sourceIndices : (index : USize) → index.toNat < length → USize) (hSourceIndices : ∀ (index : USize) (hIndex : index.toNat < length), (sourceIndices index hIndex).toNat < size source) : gather source length bound hBound sourceIndices hSourceIndices = Tensor.Internal.Elab.Impl.nativeFinFoldl length bound hBound (fun (output : Buffer α) (index : USize) (hIndex : index.toNat < length) => copyAt source (sourceIndices index hIndex) ⋯ output) (emptyWithCapacity length)
Physical gathering is the storage-specific native finite loop.
Read one scalar using a natural-number index.
Read one scalar using a platform-native index.
Observe the physical buffer as an ordinary logical array.
Construct physical storage from an ordinary array.
Buffer observation preserves size.
- toArray_get (buffer : Buffer α) (index : ℕ) (hBuffer : index < size buffer) (hArray : index < (toArray buffer).size) : (toArray buffer)[index] = get buffer index hBuffer
Buffer observation preserves natural-number reads.
- toArray_uget (buffer : Buffer α) (index : USize) (hBuffer : index.toNat < size buffer) (hArray : index.toNat < (toArray buffer).size) : (toArray buffer).uget index hArray = uget buffer index hBuffer
Buffer observation preserves platform-native reads.
- toArray_emptyWithCapacity (capacity : ℕ) : toArray (emptyWithCapacity capacity) = Array.emptyWithCapacity capacity
An empty physical buffer observes as an empty ordinary array.
- toArray_push (buffer : Buffer α) (value : α) : toArray (push buffer value) = (toArray buffer).push value
Appending one scalar commutes with buffer observation.
- toArray_copyAt (source : Buffer α) (index : USize) (hBuffer : index.toNat < size source) (output : Buffer α) (hArray : index.toNat < (toArray source).size) : toArray (copyAt source index hBuffer output) = (toArray output).push ((toArray source).uget index hArray)
Copying one physical entry commutes with buffer observation.
- toArray_appendSlice (source : Buffer α) (start stop : ℕ) (output : Buffer α) : toArray (appendSlice source start stop output) = toArray output ++ (toArray source).extract start stop
Appending a source interval commutes with buffer observation.
- toArray_foldl {β : Type u} (step : β → α → β) (initial : β) (buffer : Buffer α) : foldl step initial buffer = Array.foldl step initial (toArray buffer)
Row-major traversal agrees with folding the ordinary array observation.
Converting from an ordinary array is inverse to observation.
- toArray_injective : Function.Injective toArray
The ordinary array observation uniquely determines physical storage.
Instances
Copy-on-write replacement of one physical scalar.
Every Storage receives the ordinary-array fallback below, so defining a
custom scalar storage does not require implementing this capability. Packed
backends can override it to retain their native representation.
Replace one in-bounds physical entry.
- toArray_set (buffer : Buffer α) (index : ℕ) (hBuffer : index < size buffer) (value : α) : toArray (set buffer index hBuffer value) = (toArray buffer).set index value ⋯
Physical replacement agrees with ordinary-array replacement.
Instances
Universal update support for any storage.
This fallback round-trips through the logical array observation. Specialized packed storage overrides it below with native copy-on-write replacement.
Copying a physical entry is the same buffer update as pushing its observed scalar value.
Generated movement kernels use this theorem to reason about copyAt without
exposing the scalar at the executable callback boundary.
Pushing finite-indexed values in order constructs Array.ofFn.
Observing finite pushes from any reserved capacity gives the corresponding ordinary function array.
Finite construction observes as the corresponding ordinary array.
An Array.ofFn observation determines the physical buffer size.
Empty physical storage contains no scalar entries.
Ordinary-array slice traversal is extraction followed by append.
Copy one ordinary-array entry without exposing its scalar at the caller boundary.
Specializing a scalar-valued callback can unbox and immediately rebox values
such as Float32. Keeping the transfer inside this polymorphic primitive lets
Lean's runtime retain and move the existing lean_object* instead.
Instances For
Gather ordinary-array entries without exposing their scalar values.
Instances For
Ordinary polymorphic arrays are the universal tensor-storage fallback.
Proof-visible model of the native empty ByteArray allocator.
Compiled code calls Lean's built-in scalar-array runtime primitive.
Instances For
Fast native transfer between byte buffers.
Instances For
Proof-visible model of one native byte-buffer transfer.
Instances For
Runtime adapter from the proof-visible byte-buffer bound to ByteArray.get.
Instances For
Proof-visible model of native natural-number ByteArray lookup.
Instances For
Fast native replacement in a packed byte buffer.
Instances For
Proof-visible model of native byte-buffer replacement.
Instances For
Runtime adapter from the proof-visible byte-buffer bound to ByteArray.uget.
Instances For
Proof-visible model of native USize ByteArray lookup.
Instances For
Gather native byte-buffer entries in one storage-specific loop.
Instances For
Fast native implementation of contiguous byte-buffer copying.
Clamp before calling ByteArray.copySlice: its native allocator may reserve the requested length
before clipping the source interval. The model follows Array.extract, including huge naturals.
Instances For
Proof-visible model of contiguous native ByteArray traversal.
The logical body exposes ordinary array extraction. Native code delegates the
whole interval to Lean's built-in ByteArray.copySlice runtime primitive.
Instances For
Fast native traversal of an unboxed byte buffer.
Instances For
Proof-visible model of native ByteArray traversal.
The logical body exposes the ordinary array fold. Native code traverses the unboxed byte buffer directly.
Instances For
Proof-visible model of the native empty FloatArray allocator.
Compiled code calls Lean's built-in scalar-array runtime primitive.
Instances For
Proof-visible model of native FloatArray.push.
Instances For
Proof-visible model of native FloatArray.size.
Instances For
Fast native transfer between floating-point buffers.
Instances For
Proof-visible model of one native floating-point-buffer transfer.
Instances For
Runtime adapter from the proof-visible float-buffer bound to FloatArray.get.
Instances For
Proof-visible model of native natural-number FloatArray lookup.
Instances For
Runtime adapter from the proof-visible float-buffer bound to FloatArray.uget.
Instances For
Proof-visible model of native USize FloatArray lookup.
Instances For
Gather native floating-point-buffer entries in one storage-specific loop.
Instances For
Proof-visible model of contiguous native FloatArray traversal.
The logical body exposes ordinary array extraction.
Instances For
Native implementation of contiguous packed floating-point copying.
The body calls the reference rather than restating it, so the rfl below cannot drift; compiled
code replaces the whole thing with torchlean_float_array_append_slice.
Instances For
Compile packed floating-point slice appends to one native bulk-copy call.
Lean evaluation and proofs continue to unfold floatBufferAppendSlice; only
generated code uses the external implementation.
Fast native traversal of an unboxed floating-point buffer.
Instances For
Proof-visible model of native FloatArray traversal.
The logical body exposes the ordinary array fold. Native code traverses the unboxed floating-point buffer directly.
Instances For
Fast native replacement in an unboxed floating-point buffer.
Instances For
Proof-visible model of native floating-point-buffer replacement.
Instances For
UInt8 tensors use Lean's packed native byte-array representation.
Float tensors use Lean's unboxed native scalar-array representation.
Byte tensors replace entries directly in their packed native buffer.
Float tensors replace entries directly in their unboxed native buffer.