Agent skill
dtype-native-migration
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/dtype-native-migration
SKILL.md
Skill: dtype-native-migration
Overview
| Field | Value |
|---|---|
| Date | 2025-12-31 |
| Category | architecture |
| Objective | Migrate custom dtype struct implementations to Mojo's native built-in types |
| Outcome | ✅ Success - ~5000 lines removed, all tests pass |
When to Use
Invoke this skill when:
- You need to replace custom dtype structs (BF16, FP8, BF8, FP4) with Mojo native types
- You encounter E8M0 (exponent-only) or other exotic dtype conversions
- You're updating code that uses MXFP4/NVFP4 blocked formats
- Mojo has added native support for a dtype you previously implemented manually
Verified Workflow
Step 1: Create Type Aliases File
Create shared/core/types/dtype_aliases.mojo:
"""Type aliases for Mojo built-in dtypes."""
# Use comptime (not alias) to avoid deprecation warnings
comptime BF16 = DType.bfloat16
comptime FP8 = DType.float8_e4m3fn
comptime BF8 = DType.float8_e5m2
comptime FP4 = DType.float4_e2m1fn
comptime E8M0 = DType.float8_e8m0fnu
Step 2: Handle E8M0 Conversion (CRITICAL)
Native conversion does NOT work for E8M0 because it's exponent-only (no mantissa).
Use manual exponent extraction:
fn _e8m0_from_float32(scale: Float32) -> Scalar[E8M0]:
"""Convert Float32 to E8M0 (power-of-2 only)."""
if scale <= 0.0 or isnan(scale):
return bitcast[E8M0, 1](SIMD[DType.uint8, 1](0))
if isinf(scale):
return bitcast[E8M0, 1](SIMD[DType.uint8, 1](255))
# Extract exponent from Float32 bits
var bits = bitcast[DType.uint32, 1](SIMD[DType.float32, 1](scale))
var float_exp = ((bits[0] >> 23) & 0xFF).cast[DType.uint8]()
# Round to nearest power of 2 based on mantissa
var mantissa = bits[0] & 0x7FFFFF
if mantissa >= 0x400000: # >= 0.5
if float_exp < 255:
float_exp += 1
return bitcast[E8M0, 1](SIMD[DType.uint8, 1](float_exp))
fn _e8m0_to_float32(e8m0_val: Scalar[E8M0]) -> Float32:
"""Convert E8M0 to Float32 (power-of-2 result)."""
var exp = bitcast[DType.uint8, 1](e8m0_val)[0]
if exp == 0:
return Float32(0.0)
if exp == 255:
return Float32(1.0) / Float32(0.0) # Infinity
# Construct Float32: sign=0, exponent=exp, mantissa=0
var float_bits = exp.cast[DType.uint32]() << 23
return bitcast[DType.float32, 1](SIMD[DType.uint32, 1](float_bits))[0]
Step 3: Update Dependent Code
Replace struct field types:
# Before
var scale: E8M0Scale # Custom struct
# After
var scale: Scalar[E8M0] # Native type
Replace method calls:
# Before
block.scale.exponent # Struct field access
E8M0Scale(byte_value) # Constructor
# After
bitcast[DType.uint8, 1](block.scale)[0] # Get raw bits
bitcast[E8M0, 1](SIMD[DType.uint8, 1](byte_value)) # From raw bits
Step 4: Update Test Tolerances
E8M0's power-of-2 constraint means scale can be up to 2x off from optimal:
# Before (assumes optimal scale)
assert_true(error < expected * 0.5, "Error too large")
# After (accounts for E8M0 quantization)
assert_true(error < expected * 1.0, "Error too large")
Step 5: Update CI and Delete Old Files
- Remove deleted test files from CI workflow patterns
- Delete old struct implementation files
- Delete obsolete test files
Failed Attempts
1. Native E8M0 Conversion
What was tried:
return Scalar[E8M0](scale) # Native conversion
Why it failed: E8M0 has no mantissa - only 8 exponent bits. Native Scalar[E8M0]() conversion doesn't
know how to handle the mantissa portion of Float32.
Solution: Manual exponent extraction with proper rounding.
2. Native E8M0 to Float32 Conversion
What was tried:
return Float32(e8m0_val) # Native conversion
Why it failed: Similar issue - the reverse conversion doesn't properly reconstruct Float32 from exponent-only format.
Solution: Manual Float32 reconstruction using bitcast.
3. Original Test Tolerances
What was tried: 50% relative error tolerance for round-trip tests.
Why it failed: E8M0's power-of-2 scale can be up to 2x off, causing >50% error for values at low end of block range.
Solution: Increased tolerance to 100% for tests with E8M0 scaling.
Results & Parameters
Type Mapping
| Custom Type | Mojo Built-in | Alias |
|---|---|---|
BF16 struct |
DType.bfloat16 |
BF16 |
FP8 struct |
DType.float8_e4m3fn |
FP8 |
BF8 struct |
DType.float8_e5m2 |
BF8 |
FP4_E2M1 struct |
DType.float4_e2m1fn |
FP4 |
E8M0Scale struct |
DType.float8_e8m0fnu |
E8M0 |
Code Impact
- Files deleted: 4 dtype files + 10 test files
- Lines removed: ~5000
- Lines added: ~750 (mostly helper functions for E8M0)
Key Patterns
Use comptime not alias:
comptime BF16 = DType.bfloat16 # Correct
alias BF16 = DType.bfloat16 # Deprecated
Import bitcast for dtype conversions:
from memory import bitcast
Bitcast pattern for raw byte access:
# Read raw bits from native dtype
var raw_byte = bitcast[DType.uint8, 1](scalar_val)[0]
# Create native dtype from raw bits
var scalar_val = bitcast[FP8, 1](SIMD[DType.uint8, 1](raw_byte))
Platform Notes
DType.bfloat16is NOT supported on Apple Silicon- E8M0 (
DType.float8_e8m0fnu) requires manual conversion helpers - FP8/BF8/FP4 native conversions work correctly
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?