Skip to content

Improve performance of i256 to f64 #8013

@alamb

Description

@alamb

This ticket tracks potentially improving performance of i256 --> f64 conversion via manually twiddling bits from @scovich

Bit twiddling that I think would work:

  1. Define i256::leading_zeros() that follows the semantics of all the other leading_zeros for integral types
    impl i256 {
        pub fn leading_zeros(&self) -> u32 {
            match self.high {
                0 => 128 + self.low.leading_zeros(),
                _ => self.high.leading_zeros(),
            }
        }
    }
  2. Define a notion of "redundant leading sign bits" in terms of leading zeros:
    fn redundant_leading_sign_bits_i256(n: i256) -> u32 {
        let mask = n >> 255; // all ones or all zeros
        (n ^ mask).leading_zeros() - 1; // we only need one sign bit
    }
  3. Shift out all redundant leading sign bits when converting to f64:
    fn i256_to_f64(n: i256) -> f64 {
        let k = redundant_leading_sign_bits_i256(n);
        let n = n << k; // left-justify (no redundant sign bits)
        let n = (n.high >> 64) as i64; // throw away the lower 192 bits
        (n as f64) * f64::powi(2.0, 192-k) // convert to f64 and scale it
    }

The above should work for both positive and negative values

Originally posted by @scovich in #7986 (comment)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions