Skip to content

Computing the inverse powers of 2 in place can be faster than a lookup table #157

Description

@tisonkun

For #148 @leerho discussed with me that computing the inverse powers of 2 is a very simple integer subtract and shift operation that is performed in one or two CPU clocks.  It is extremely fast, can be inlined, and faster than any table lookup.  No need to store a table.  The Java code looks like this:

public static double invPow2(final int exp) {
  if ((exp | (1024 - exp - 1)) < 0) {
    throw new SketchesArgumentException("exp cannot be negative or greater than 1023: " + exp);
  }
  return Double.longBitsToDouble((1023L - exp) << 52);
}

As in Rust, we define the exp as u8, it can be as simple as:

/// Compute 1 / 2^value (inverse power of 2)
#[inline]
fn inv_pow2(value: u8) -> f64 {
    let value = (1023u64 - value as u64) << 52;
    f64::from_bits(value)
}

I think we can try to replace INVERSE_POWERS_OF_2[old_value as usize] with inv_pow2(old_value). But we'd better have a benchmark first to check if the inv_pow2 approach is significantly faster in Rust.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions