Skip to content

Commit

Permalink
Clamp before downcasting in float to i8 conversions
Browse files Browse the repository at this point in the history
    Previously we were downcasting floats to the target type (e.g. int8_t), and then
    clamping to [-100, 100] range. This means that e.g. 129 would be cast to -127 and
    then converted to -100, in stead of becoming 100

    The fix does clamping first, and then casts the resulting number
    (which is guaranteed to be in range [-100, 100], due to clamping)
    from source type to target int8_t. Given the clamping, this will never overflow.
  • Loading branch information
Ngalstyan4 committed May 25, 2024
1 parent c453582 commit 11cfb94
Showing 1 changed file with 4 additions and 3 deletions.
7 changes: 4 additions & 3 deletions include/usearch/index_plugins.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -960,12 +960,13 @@ class i8_converted_t {
inline explicit operator std::int32_t() const noexcept { return int8_; }
inline explicit operator std::int64_t() const noexcept { return int8_; }

/* clamp uses std::less comparator which does not have comparisons for f16_t, so promoting v to float below */
inline i8_converted_t(f16_t v)
: int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
: int8_(static_cast<std::int8_t>(usearch::clamp<f32_t>(v * divisor_k, min_k, max_k))) {}
inline i8_converted_t(f32_t v)
: int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
: int8_(static_cast<std::int8_t>(usearch::clamp<f32_t>(v * divisor_k, min_k, max_k))) {}
inline i8_converted_t(f64_t v)
: int8_(usearch::clamp<std::int8_t>(static_cast<std::int8_t>(v * divisor_k), min_k, max_k)) {}
: int8_(static_cast<std::int8_t>(usearch::clamp<f64_t>(v * divisor_k, min_k, max_k))) {}
};

f16_bits_t::f16_bits_t(i8_converted_t v) noexcept : uint16_(f32_to_f16(v)) {}
Expand Down

0 comments on commit 11cfb94

Please sign in to comment.