Crate fast_float_to_integer

Source
Expand description

Convert floating point values to integer types faster than the standard as operator.

The standard way of converting floating point values to integers is with the as operator. This conversion has various guarantees as listed in the reference. One of them is that it saturates: Input values out of range of the output type convert to the minimal/maximal value of the output type.

assert_eq!(300f32 as u8, 255);
assert_eq!(-5f32 as u8, 0);

This contrasts C/C++, where this kind of cast is undefined behavior. Saturation comes with a downside. It is slower than the C/C++ version. On many hardware targets a float to integer conversion can be done in one instruction. For example CVTTSS2SI on x86_84+SSE. Rust has to do more work than this, because the instruction does not provide saturation.

Sometimes you want faster conversions and don’t need saturation. This is what this crate provides. The behavior of the conversion functions in this crate depends on whether the input value is in range of the output type. If in range, then the conversion functions work like the standard as operator conversion. If not in range (including NaN), then you get an unspecified value.

You never get undefined behavior but you can get unspecified behavior. In the unspecified case, you get an arbitrary value. The function returns and you get a valid value of the output type, but there is no guarantee what that value is.

This crate picks an implementation automatically at compile time based on the target and features. If there is no specialized implementation, then this crate picks the standard as operator conversion. This crate has optimized implementations on the following targets:

  • target_arch = "x86_64", target_feature = "sse": all conversions except 128 bit integers
  • target_arch = "x86", target_feature = "sse": all conversions except 64 bit and 128 bit integers

§Assembly comparison

The repository contains generated assembly for every conversion and target. Here are some typical examples on x86_64+SSE.

standard:

f32_to_i64:
    cvttss2si rax, xmm0
    ucomiss xmm0, dword ptr [rip + .L_0]
    movabs rcx, 9223372036854775807
    cmovbe rcx, rax
    xor eax, eax
    ucomiss xmm0, xmm0
    cmovnp rax, rcx
    ret

fast:

f32_to_i64:
    cvttss2si rax, xmm0
    ret

standard:

f32_to_u64:
    cvttss2si rax, xmm0
    mov rcx, rax
    sar rcx, 63
    movaps xmm1, xmm0
    subss xmm1, dword ptr [rip + .L_0]
    cvttss2si rdx, xmm1
    and rdx, rcx
    or rdx, rax
    xor ecx, ecx
    xorps xmm1, xmm1
    ucomiss xmm0, xmm1
    cmovae rcx, rdx
    ucomiss xmm0, dword ptr [rip + .L_1]
    mov rax, -1
    cmovbe rax, rcx
    ret

fast:

f32_to_u64:
    cvttss2si rcx, xmm0
    addss xmm0, dword ptr [rip + .L_0]
    cvttss2si rdx, xmm0
    mov rax, rcx
    sar rax, 63
    and rax, rdx
    or rax, rcx
    ret

Functions§

f32_to_i8
Convert the input floating point value to the output integer type.
f32_to_i16
Convert the input floating point value to the output integer type.
f32_to_i32
Convert the input floating point value to the output integer type.
f32_to_i64
Convert the input floating point value to the output integer type.
f32_to_i128
Convert the input floating point value to the output integer type.
f32_to_u8
Convert the input floating point value to the output integer type.
f32_to_u16
Convert the input floating point value to the output integer type.
f32_to_u32
Convert the input floating point value to the output integer type.
f32_to_u64
Convert the input floating point value to the output integer type.
f32_to_u128
Convert the input floating point value to the output integer type.
f64_to_i8
Convert the input floating point value to the output integer type.
f64_to_i16
Convert the input floating point value to the output integer type.
f64_to_i32
Convert the input floating point value to the output integer type.
f64_to_i64
Convert the input floating point value to the output integer type.
f64_to_i128
Convert the input floating point value to the output integer type.
f64_to_u8
Convert the input floating point value to the output integer type.
f64_to_u16
Convert the input floating point value to the output integer type.
f64_to_u32
Convert the input floating point value to the output integer type.
f64_to_u64
Convert the input floating point value to the output integer type.
f64_to_u128
Convert the input floating point value to the output integer type.