Why does @fastmath have problems with promoting integers?

Why do I get the following error?

julia> (-1) * UInt(1)
0xffffffffffffffff

julia> @fastmath (-1) * UInt(1)
ERROR: InexactError: convert(UInt64, -1)

Tested with Julia 1.11.4.

@fastmath changes operations:

julia> @macroexpand @fastmath((-1) * UInt(1))
:(Base.FastMath.mul_fast(-1, UInt(1)))

which falls back to promotion and the original operation if it’s not among the floating point types flouting IEEE-754 for speed:

        $op_fast(x::Number, y::Number, zs::Number...) = # op_fast === mul_fast
            $op_fast(promote(x,y,zs...)...)
        # fall-back implementation that applies after promotion
        $op_fast(x::T,ys::T...) where {T<:Number} = $op(x,ys...) # op === *

Unfortunately, the promotion doesn’t work for *(::Int, ::Uint):

julia> promote((-1), UInt(1))
ERROR: InexactError: convert(UInt64, -1)

I have no idea if this is intentional or why they’d take the extra step of promotion when the original operation would take care of it (and properly), I’d argue it’s a bug. The non-numeric method preceding the above numeric methods actually wouldn’t have this problem:

        # fall-back implementation for non-numeric types
        $op_fast(xs...) = $op(xs...)

Practically speaking, there’s no point in using @fastmath for anything that doesn’t involve floating point types, and involving negative signs with an unsigned number is an unusually tricky use of overflow.

True. However, one might have a function that accepts both integer and floating point types, and one adds @fastmath to have it for the floating point case.

Anyway, thanks!

Indeed, so proper fallbacks are still the right thing to do IMO. Forgot to mention, but the promotion for *(::Int, ::UInt) works by % overflow prior to promotion to get around the typical InexactError for converting negative signed integers to unsigned ones.

Here is a link to a relevant GitHub issue: JuliaLang/julia#15489. The consensus seems to be not to throw an error in such a case. I guess the @fastmath version was forgotten.

EDIT: I’ve created an issue on GitHub: integer multiplication errors with `@fastmath` · Issue #58188 · JuliaLang/julia · GitHub

2 Likes