CUDA emission for custom operations #
Each output element is computed independently. Inputs are immutable and only the current thread's
output is written. Temporaries sequence arithmetic; branches and folds become structured CUDA
control flow. Native compilation must use --fmad=false and --ftz=false, without fast math.
Scoped target blocks are allocated into named statements before rendering. Target.eval_lower
certifies the scoped lowering; the named evaluator models mutable storage and control flow.
Checked literal words retain the supplied bits; native-value round trips reuse FloatLib. The
named allocation is certified in Cuda.Correctness. CUDA syntax interpretation, NVIDIA's
compilation and device execution require separate evidence; the lowering theorems alone do not
establish correctness of rendered text.
See NVIDIA's NVRTC manual and CUDA Math API for round-to-nearest arithmetic intrinsics: https://docs.nvidia.com/cuda/nvrtc/index.html https://docs.nvidia.com/cuda/cuda-math-api/index.html
Native Lean scalar formats; configured binary values use their complete-word emitter.
Instances For
The native Lean scalar corresponding to a CUDA format.
Instances For
Literal interchange words carry their width, rather than relying on a renderer-side cast.
- binary32 (bits : UInt32) : Literal Format.binary32
- binary64 (bits : UInt64) : Literal Format.binary64
Instances For
Retain the literal word in the common unsigned ABI without changing its bits.
Instances For
Interpret a word in Lean's native float model, which canonicalizes NaN payloads.
Instances For
Obtain the exact interchange word of a native value.
Instances For
Render a checked word as a CUDA bit reinterpretation, never a decimal float approximation.
Instances For
Remove an exact prefix and suffix, rejecting mismatched emitted syntax.
Instances For
Decode the emitted bit-reinterpretation syntax, rejecting invalid or oversized words.
This recognizes literal text, not arbitrary CUDA expressions. The word is checked before any narrowing conversion, so an out-of-range decimal integer cannot silently wrap. Only canonical decimal spelling is accepted; leading zeros would give the integer an octal meaning in CUDA.
Instances For
Literal text preserves a native value in Lean's float model, including signed zeros.
As with value_ofValue, this concerns the model's NaN value, not native NaN payload preservation.
Unsigned CUDA expressions over already-evaluated operands.
Raw division and remainder have no defined result at a zero denominator. The lowering inserts a lazy conditional instead of relying on Lean's total unsigned operations to model that case.
- literal {ν : Type} (value : UInt64) : Unsigned ν
- var {ν : Type} (name : ν) : Unsigned ν
- binary {ν : Type} (op : IndexOp) (x y : Unsigned ν) : Unsigned ν
- ifZero {ν : Type} (test yes no : Unsigned ν) : Unsigned ν
Instances For
Lower an index operation on named values, guarding native division and remainder.
Instances For
Atomic operands with a typed address space for local variables.
- scalar {α : Type} {ν : Ty → Type} (value : α) : Atom α ν Ty.scalar
- index {α : Type} {ν : Ty → Type} (value : UInt64) : Atom α ν Ty.index
- predicate {α : Type} {ν : Ty → Type} (value : Bool) : Atom α ν Ty.predicate
- var {α : Type} {ν : Ty → Type} {t : Ty} (name : ν t) : Atom α ν t
Instances For
Assigning names preserves atomic values when the named locals represent the source scope.
Typed CUDA primitives, including the explicit guards required by unsigned arithmetic.
Scalar operations use the supplied arithmetic contract. A read remains checked by the reader; its CUDA implementation needs a bounds-check statement, not just a right-hand-side expression.
- copy {α : Type} {ν : Ty → Type} {t : Ty} (atom : Atom α ν t) : Primitive α ν t
- load {α : Type} {ν : Ty → Type} (operand : ℕ) (index : Atom α ν Ty.index) : Primitive α ν Ty.scalar
- binary {α : Type} {ν : Ty → Type} (op : ScalarOp) (x y : Atom α ν Ty.scalar) : Primitive α ν Ty.scalar
- neg {α : Type} {ν : Ty → Type} (x : Atom α ν Ty.scalar) : Primitive α ν Ty.scalar
- unsigned {α : Type} {ν : Ty → Type} (value : Unsigned (Atom α ν Ty.index)) : Primitive α ν Ty.index
- compare {α : Type} {ν : Ty → Type} (op : Compare) (x y : Atom α ν Ty.scalar) : Primitive α ν Ty.predicate
- indexCompare {α : Type} {ν : Ty → Type} (op : Compare) (x y : Atom α ν Ty.index) : Primitive α ν Ty.predicate
Instances For
Interpret a primitive; none means undefined unsigned arithmetic, not a failed input read.
Instances For
Lowering introduces no undefined operation and preserves both values and input errors.
The arithmetic contract is unchanged: this does not identify an arbitrary contract with NVIDIA's intrinsics, or prove that rendering and native compilation implement the interpreted primitive.
Render a local name without admitting arbitrary identifier text.
Instances For
Decode generated local names at their declared type, without accepting arbitrary identifiers.
The output index is available only at index type. Temporary numbers use canonical decimal spelling; names with leading zeros, trailing source text or missing allocation numbers are rejected.
Instances For
A typed valuation of named locals; values outside the current scope are unconstrained.
Instances For
Allocating the next temporary leaves every earlier local unchanged.
Execute the assignment in its local valuation. Failed reads never supply a stored value.
Instances For
A lowered primitive writes exactly its source result and retains the source read errors.
Assigning a fresh local preserves every previously represented source variable.
Named statements used by both the CUDA renderer and the mutable-local evaluator.
Branch results are copied into their destination only after the selected arm finishes. Loop bodies read the current counter and accumulator, then copy their result back into the accumulator.
- skip {α : Type} : Statement α
- assign {α : Type} {t : Ty} (assignment : Assignment α t) : Statement α
- seq {α : Type} (first second : Statement α) : Statement α
- branch {α : Type} {t : Ty} (name : Name t) (condition : Atom α Name Ty.predicate) (yes : Statement α) (yesResult : Name t) (no : Statement α) (noResult : Name t) : Statement α
- loop {α : Type} (acc : Name Ty.scalar) (counter : Name Ty.index) (count : Atom α Name Ty.index) (initial : Atom α Name Ty.scalar) (body : Statement α) (next : Name Ty.scalar) : Statement α
Instances For
A defined body gives exactly the remaining source iterations, including their errors.
Evaluate the same named assignments and control flow that the renderer consumes.
none denotes undefined raw unsigned arithmetic; checked input failures remain Except.error.
The loop's fuel is its unsigned bound, so it cannot truncate an increasing counter from zero.
Instances For
A named loop agrees with the unsigned guarded loop when its body has defined semantics.
The step may fail with a checked error. The hypothesis excludes only undefined raw arithmetic, not failed input reads; each successful step copies its result into the mutable accumulator.
Instances For
Instances For
Emit one independent output calculation with exact bit-pattern scalar literals.
The expression's sole free variable is its row-major output index. Each input has its own pointer and length argument. A four-word error record reports an observed invalid read; callers must check it after execution before exposing the output. No caller-provided text enters the source.