tracel-ai/burn · error

compare_elem: unsupported dtype {:?}

Error message

compare_elem: unsupported dtype {:?}

What it means

compare_elem performs tensor-vs-scalar comparisons (greater_elem, greater_equal_elem, lower_elem, lower_equal_elem, equal_elem, not_equal_elem). The scalar is converted into the tensor's element type — F16/BF16 scalars go through from_f64 with an f32 comparison — and any non-float tensor dtype hits the panic arm. out_dtype controls the output boolean representation.

Source

Thrown at crates/burn-flex/src/ops/comparison.rs:336

{
    let dtype = lhs.dtype();

    match dtype {
        DType::F32 => compare_elem_f32(lhs, rhs as f32, out_dtype, f32_cmp, simd_hint),
        DType::F64 => compare_elem_typed(lhs, rhs, out_dtype, f64_cmp),
        DType::F16 => {
            let scalar = f16::from_f64(rhs);
            compare_elem_typed(lhs, scalar, out_dtype, |a: f16, b: f16| {
                f32_cmp(a.to_f32(), b.to_f32())
            })
        }
        DType::BF16 => {
            let scalar = bf16::from_f64(rhs);
            compare_elem_typed(lhs, scalar, out_dtype, |a: bf16, b: bf16| {
                f32_cmp(a.to_f32(), b.to_f32())
            })
        }
        _ => panic!("compare_elem: unsupported dtype {:?}", dtype),
    }
}

/// Specialized scalar comparison for f32 with SIMD fast path.
#[cfg(feature = "simd")]
fn compare_elem_f32<Cmp>(
    lhs: FlexTensor,
    rhs: f32,
    out_dtype: BoolDType,
    cmp: Cmp,
    simd_hint: Option<CompareOp>,
) -> FlexTensor
where
    Cmp: Fn(f32, f32) -> bool,
{
    // SIMD fast path: tensor is contiguous
    if let Some((start, end)) = lhs.layout().contiguous_offsets()
        && let Some(simd_op) = simd_hint

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Cast the tensor to a float dtype first: x.cast(DType::F32).greater_elem(0.5).
  2. Use an integer-aware comparison helper if one exists in the ops module for int tensors.
  3. Compute the threshold as an integer scalar and use int scalar comparison ops when the tensor is integral.

Example fix

// before
let mask = greater_elem(preds_i64, 0); // panics
// after
let mask = preds_i64.cast(DType::F32).greater_elem(0.0);
Defensive patterns

Strategy: validation

Validate before calling

if !matches!(tensor.dtype(), DType::F32 | DType::F64 | DType::F16 | DType::BF16) {
    tensor = tensor.cast(DType::F32);
}
let mask = tensor.greater_elem(threshold);

Type guard

fn is_float_dtype(d: DType) -> bool {
    matches!(d, DType::F32 | DType::F64 | DType::F16 | DType::BF16)
}

Try / catch

let mask = std::panic::catch_unwind(|| greater_elem(tensor.clone(), t))
    .unwrap_or_else(|_| greater_elem(tensor.cast(DType::F32), t as f32));

Prevention

When it happens

Trigger: Calling any *_elem comparison on an integer, unsigned or bool tensor (only float branches are matched); passing a scalar that cannot be represented in f16/bf16 is fine (it rounds), but a non-float tensor dtype always panics.

Common situations: Thresholding integer predictions/labels against a scalar; comparing bool tensors against 0/1; porting NumPy/PyTorch scalar-comparison code that supports all dtypes.

Related errors


AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05). Data as JSON: /api/errors/b692e19de2ff5c17. Report an issue: GitHub.