Module Tolk.Decomp_dtype
Emulated data types.
A target that lacks a data type computes with another one.
- A 64-bit integer (
Dtype.t.Int64,Dtype.t.Uint64) is two 32-bit words, low first, ofDtype.t.Int32orDtype.t.Uint32. Its storage holds twice as many words, and its operations are built from 32-bit ones. - A narrow float (
Dtype.t.Float16,Dtype.t.Bfloat16and the 8-bit floats) is stored in its own format, as the unsigned integer of its width, and computed with as aDtype.t.Float32: a load converts it up, a store converts it down (f2f). A cast to it rounds its source to it, once; a source more precise than aDtype.t.Float32reaches one rounded to odd. An operation on it computes inDtype.t.Float32, and its result is rounded to the narrow float only where a store converts it down: a later operation, or a cast of it to another type, reads the unrounded value. A copy or a selection keeps the stored bits.
The conversions are IEEE's: one rounding, to nearest with ties to even, gradual underflow, and infinities and NaNs kept where the format has them.
A type is emulated when the target does not support it (Renderer.supported_dtypes) or the setting Setting.emulated_dtypes names it.
Float conversion
f2f ~sat v fr to_ converts between a narrow float and Dtype.t.Float32, v being the bits of a float of type fr, as the unsigned integer of its width:
- widening to
Dtype.t.Float32, it is the valuevencodes, subnormals included; - narrowing from
Dtype.t.Float32, it is the bits, as the unsigned integer ofto_'s width, of the valuevencodes rounded toto_'s precision, to nearest with ties to even, into a subnormal belowto_'s least normal. A value that rounds pastto_'s greatest finite value, and an infinity, is an infinity, which a format without one holds as its NaN; but a finite value of an 8-bit float, ifsat, is at most its greatest finite value.
A NaN stays a NaN, and a quiet one stays quiet; an fnuz format has one NaN, and no negative zero. sat defaults to true.
Raises Invalid_argument unless one of fr and to_ is Dtype.t.Float32 and the other a narrower float.
narrow x dt is x cast to dt, but for a Dtype.t.Float32 from a Dtype.t.Float64 or an integer of 32 or 64 bits whose bounds (Ops.vmin, Ops.vmax) do not lie within 2{^24}, more precise than a float32: then it is x rounded to odd, towards zero with the last bit set if bits were dropped, so that a narrow float rounded to nearest from it is x rounded to nearest once.
It needs only that the target's conversion to Dtype.t.Float32 lands on one of the two float32 values around x, as C11 6.3.1.4p2 and 6.3.1.5p1 promise; not that it rounds to nearest.
Passes
val computes : Renderer.t -> Dtype.t listcomputes r is the data types of Dtype.all, in order, that r's target computes: those it supports (Renderer.supported_dtypes), and those pm_dtype_decomps emulates where it lacks them, the 8-bit floats, Dtype.t.Bfloat16, Dtype.t.Float16, Dtype.t.Int64 and Dtype.t.Uint64.
val emulates : Renderer.t -> Dtype.t -> boolemulates r dt is true iff code generation for r's target emulates dt: r does not support it (Renderer.supported_dtypes) or the setting Setting.emulated_dtypes names it, an unsigned 64-bit integer as the signed one that emulates it. The setting is read at emulates r.
type ctxThe type for the context of pm_dtype_decomps: the types a kernel uses that may need emulation, and the target's renderer.
val ctx : Renderer.t -> ctxctx r is the context for emulating on r's target, with no type found yet.
val pm_dtype_decomps : (ctx, Ops.t) Ops.Pattern_matcher.tpm_dtype_decomps notes the narrow floats and 64-bit integers a kernel uses, and at the kernel's Op.t.Sink rewrites it to emulate those that the target lacks, in the promotion order of their types (Dtype.compare). Unsigned 64-bit integers are emulated with signed ones.
Raises Invalid_argument if a 64-bit integer variable must be emulated, or if Setting.emulated_dtypes names no data type.