Skip to main content
Enigma defines a fixed set of scalar types that map directly to Metal Shading Language types. Use them as kernel parameter type annotations and as arguments to casting functions.

Scalar types

Enigma typeMetal typeBitsPython/NumPy
enigma.f32float32np.float32
enigma.f16half16np.float16
enigma.bf16bfloat16ml_dtypes.bfloat16
enigma.i32int32np.int32
enigma.u32uint32np.uint32
enigma.i64long64np.int64
enigma.u64ulong64np.uint64
enigma.i16short16np.int16
enigma.u16ushort16np.uint16
enigma.i8char8np.int8
enigma.u8uchar8np.uint8
enigma.b1bool1

Using types as kernel parameters

Type annotations on kernel parameters declare the buffer element type:
@enigma.kernel
def mixed(A: enigma.f16, B: enigma.i32, C: enigma.f32):
    tid = enigma.thread_position_in_grid
    val = enigma.metal_cast(A[tid], enigma.f32)
    idx = B[tid]
    C[idx] = val

Type casting

enigma.metal_cast(value, target_type)

Standard type conversion, equivalent to C-style casting in Metal:
x_f32 = enigma.metal_cast(x_f16, enigma.f32)   # half → float
x_i32 = enigma.metal_cast(x_f32, enigma.i32)   # float → int (truncate)

enigma.as_type(value, target_type)

Bitwise reinterpret (no value conversion, same bit pattern):
bits = enigma.as_type(x_f32, enigma.u32)        # float bits as uint32

Integer literals

Integer literals in kernel bodies are automatically promoted to u32:
idx = tid * 4 + 1   # 4 and 1 become u32 IRValues
Float literals become f32:
val = A[tid] * 2.0  # 2.0 is f32

Scalar parameters

enigma.Scalar(dtype) declares a per-dispatch constant. It is lowered as a 1-element device buffer and auto-loaded at kernel entry:
@enigma.kernel
def add_scalar(A: enigma.f32, bias: enigma.Scalar(enigma.f32), C: enigma.f32):
    tid = enigma.thread_position_in_grid
    C[tid] = A[tid] + bias
Pass the scalar value as a 1-element numpy array at dispatch time:
rt.execute(compiled, inputs=[a, np.array([0.5], dtype=np.float32)], ...)

Vector types

Enigma supports vector construction for geometric operations. Vector types are created from scalars:
v2 = enigma.make_float2(x, y)
v3 = enigma.make_float3(x, y, z)
v4 = enigma.make_float4(x, y, z, w)
Access components via .x, .y, .z, .w, or by lane index:
px = v3.x
lane1 = enigma.vec_extract(v3, 1)  # equivalent to .y
See Operations for geometric and vector math functions.