Skip to content

Commit

Permalink
Refactor conversions to float
Browse files Browse the repository at this point in the history
  • Loading branch information
AldaronLau committed Feb 7, 2025
1 parent 15e8fcd commit 7d1536e
Showing 1 changed file with 30 additions and 24 deletions.
54 changes: 30 additions & 24 deletions src/tree/conversions.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,49 @@
/// Convert [`u32`] fraction to [`f32`] (ranged 0 to 1).
pub(crate) fn u32_to_f32(fraction: u32) -> f32 {
// Check if fraction is 0
let nonzero = u32::from(fraction != 0);
// Calculate leading zeros (including inferred 1)
#[inline(always)]
fn reinterpret_signed(int: u32) -> i32 {

Check warning on line 2 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, stable)

function `reinterpret_signed` is never used

Check warning on line 2 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, nightly)

function `reinterpret_signed` is never used

Check warning on line 2 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, beta)

function `reinterpret_signed` is never used

Check warning on line 2 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, beta)

function `reinterpret_signed` is never used

Check warning on line 2 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, nightly)

function `reinterpret_signed` is never used

Check warning on line 2 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, stable)

function `reinterpret_signed` is never used

Check warning on line 2 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, nightly)

function `reinterpret_signed` is never used

Check warning on line 2 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, beta)

function `reinterpret_signed` is never used

Check warning on line 2 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, stable)

function `reinterpret_signed` is never used
i32::from_ne_bytes(int.to_ne_bytes())
}

#[inline(always)]
fn reinterpret_unsigned(int: i32) -> u32 {

Check warning on line 7 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, stable)

function `reinterpret_unsigned` is never used

Check warning on line 7 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, nightly)

function `reinterpret_unsigned` is never used

Check warning on line 7 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, beta)

function `reinterpret_unsigned` is never used

Check warning on line 7 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, beta)

function `reinterpret_unsigned` is never used

Check warning on line 7 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, nightly)

function `reinterpret_unsigned` is never used

Check warning on line 7 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, stable)

function `reinterpret_unsigned` is never used

Check warning on line 7 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, nightly)

function `reinterpret_unsigned` is never used

Check warning on line 7 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, beta)

function `reinterpret_unsigned` is never used

Check warning on line 7 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, stable)

function `reinterpret_unsigned` is never used
u32::from_ne_bytes(int.to_ne_bytes())
}

/// Convert non-zero [`u32`] fraction to [`f32`] (ranged 0 to 1).
#[inline(always)]
fn nonzero_u32_to_f32(fraction: u32) -> f32 {

Check warning on line 13 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, stable)

function `nonzero_u32_to_f32` is never used

Check warning on line 13 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, nightly)

function `nonzero_u32_to_f32` is never used

Check warning on line 13 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, beta)

function `nonzero_u32_to_f32` is never used

Check warning on line 13 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, beta)

function `nonzero_u32_to_f32` is never used

Check warning on line 13 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, nightly)

function `nonzero_u32_to_f32` is never used

Check warning on line 13 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, stable)

function `nonzero_u32_to_f32` is never used

Check warning on line 13 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, nightly)

function `nonzero_u32_to_f32` is never used

Check warning on line 13 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, beta)

function `nonzero_u32_to_f32` is never used

Check warning on line 13 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, stable)

function `nonzero_u32_to_f32` is never used
// Calculate leading zeros (with inferred 1)
let leading_zeros = fraction.leading_zeros() + 1;
// Remove leading zeros and top (inferred 1) bit to subtract from exponent
let fraction = fraction.checked_shl(leading_zeros).unwrap_or(0);
// Remove leading zeros and inferred 1 to subtract from exponent
let fraction = fraction.wrapping_shl(leading_zeros);
// Shift right to truncate to 23-bit fraction
let fraction = fraction >> 9;
// Calculate -127 bias exponent
let exponent = (127 - leading_zeros) << 23;

// Scale up (u32 max is 2³² - 1, and we want 2³²)
f32::from_bits(nonzero * (exponent | fraction))
f32::from_bits(exponent | fraction)
* f32::from_bits(0b111111100000000000000000000001)
}

/// Convert [`u32`] fraction to [`f32`] (ranged 0 to 1).
pub(crate) fn u32_to_f32(fraction: u32) -> f32 {

Check warning on line 29 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, stable)

function `u32_to_f32` is never used

Check warning on line 29 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, nightly)

function `u32_to_f32` is never used

Check warning on line 29 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, beta)

function `u32_to_f32` is never used

Check warning on line 29 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, beta)

function `u32_to_f32` is never used

Check warning on line 29 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, nightly)

function `u32_to_f32` is never used

Check warning on line 29 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, stable)

function `u32_to_f32` is never used

Check warning on line 29 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, nightly)

function `u32_to_f32` is never used

Check warning on line 29 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, beta)

function `u32_to_f32` is never used

Check warning on line 29 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, stable)

function `u32_to_f32` is never used
// Check if fraction is 0 or not
let nonzero = reinterpret_unsigned(-i32::from(fraction != 0));

// Make zero if zero, otherwise no-op
f32::from_bits(nonzero_u32_to_f32(fraction).to_bits() & nonzero)
}

/// Convert [`i32`] fraction to [`f32`] (ranged -1 to 1).
pub(crate) fn i32_to_f32(int: i32) -> f32 {

Check warning on line 38 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, stable)

function `i32_to_f32` is never used

Check warning on line 38 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, nightly)

function `i32_to_f32` is never used

Check warning on line 38 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, beta)

function `i32_to_f32` is never used

Check warning on line 38 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, beta)

function `i32_to_f32` is never used

Check warning on line 38 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, nightly)

function `i32_to_f32` is never used

Check warning on line 38 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (macos-latest, stable)

function `i32_to_f32` is never used

Check warning on line 38 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, nightly)

function `i32_to_f32` is never used

Check warning on line 38 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, beta)

function `i32_to_f32` is never used

Check warning on line 38 in src/tree/conversions.rs

View workflow job for this annotation

GitHub Actions / test (windows-latest, stable)

function `i32_to_f32` is never used
// Split sign and magnitude from signed integer
let (uint, sign) = if int < 0 {
(reinterpret_unsigned(-1 - int), -1.0)
} else {
(reinterpret_unsigned(int), 1.0)
};
let sign = -i8::from(int < 0);
let uint = int.abs_diff(sign.into());
// Scale up unsigned integer to full range (without true zero)
let uint = (uint * 2) + 1;

// Copy sign back into converted float
u32_to_f32(uint).copysign(sign)
nonzero_u32_to_f32(uint).copysign(sign.into())
}

/// Convert floating point (-1 to 1) to signed 32-bit integer
Expand Down Expand Up @@ -61,16 +77,6 @@ pub(crate) fn float_to_int(float: f32) -> i32 {
}
}

#[inline(always)]
fn reinterpret_signed(int: u32) -> i32 {
i32::from_ne_bytes(int.to_ne_bytes())
}

#[inline(always)]
fn reinterpret_unsigned(int: i32) -> u32 {
u32::from_ne_bytes(int.to_ne_bytes())
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 7d1536e

Please sign in to comment.