Skip to content

Commit

Permalink
Fix some of the issues with float_to_int()
Browse files Browse the repository at this point in the history
  • Loading branch information
AldaronLau committed Jun 19, 2024
1 parent 1b71a81 commit 1e3328a
Showing 1 changed file with 44 additions and 20 deletions.
64 changes: 44 additions & 20 deletions src/tree/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,25 @@ pub(crate) fn int_to_float(int: i32) -> f32 {
/// Convert floating point (-1 to 1) to signed 32-bit integer
pub(crate) fn float_to_int(float: f32) -> i32 {

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

View workflow job for this annotation

GitHub Actions / test (macos-latest, beta)

function `float_to_int` is never used

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

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, beta)

function `float_to_int` is never used

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

View workflow job for this annotation

GitHub Actions / test (macos-latest, nightly)

function `float_to_int` is never used

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

View workflow job for this annotation

GitHub Actions / test (macos-latest, stable)

function `float_to_int` is never used

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

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, nightly)

function `float_to_int` is never used

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

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, stable)

function `float_to_int` is never used

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

View workflow job for this annotation

GitHub Actions / test (windows-latest, nightly)

function `float_to_int` is never used

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

View workflow job for this annotation

GitHub Actions / test (windows-latest, beta)

function `float_to_int` is never used

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

View workflow job for this annotation

GitHub Actions / test (windows-latest, stable)

function `float_to_int` is never used
let float = float.to_bits();
let sign = (float & (1 << 31)) >> 31;
let int = ((float << 9) >> 9) | (1 << 24);
// Check if float is negative
let is_negative = (float & (1 << 31)) != 0;
// Convert to 23-bit fixed point fraction
let int = (float << 9) >> 9;
// Add floating point inferred digit 1.x, bringing to 24 bits
let int = int | (1 << 23);
// Extract 8-bit exponent
let exponent = (float << 1) >> 24;
let shift = std::dbg!(127u32.saturating_sub(exponent));
// Calculate positive and negative shift
let shift = 119u32.saturating_sub(exponent);
let shift_back = exponent.saturating_sub(119);
// Apply calculated exponential shift
let value = if shift >= 32 { 0 } else { int >> shift };
let value = (value << shift_back).saturating_sub(1);

if shift >= 32 {
0
if is_negative {
-1 - (value as i32)
} else {
((int as i32) * (1 - (sign as i32 * 2))).saturating_mul(128) >> shift
value as i32
}
}

Expand All @@ -58,6 +68,9 @@ mod tests {
assert_eq!(int_to_float(i32::MAX), 1.0);
assert_eq!(int_to_float(i32::MAX / 2), 0.5);
assert_eq!(int_to_float(i32::MAX / 4), 0.25);
assert_eq!(int_to_float(7), 6.9849193e-9);
assert_eq!(int_to_float(6), 6.0535967e-9);
assert_eq!(int_to_float(5), 5.122274e-09);
assert_eq!(int_to_float(4), 4.1909516e-9);
assert_eq!(int_to_float(3), 3.259629e-9);
assert_eq!(int_to_float(2), 2.3283064e-9);
Expand All @@ -68,26 +81,37 @@ mod tests {
assert_eq!(int_to_float(-3), -2.3283064e-9);
assert_eq!(int_to_float(-4), -3.259629e-9);
assert_eq!(int_to_float(-5), -4.1909516e-9);
assert_eq!(int_to_float(-6), -5.122274e-09);
assert_eq!(int_to_float(-7), -6.0535967e-9);
assert_eq!(int_to_float(-8), -6.9849193e-9);
assert_eq!(int_to_float(i32::MIN / 4), -0.25);
assert_eq!(int_to_float(i32::MIN / 2), -0.5);
assert_eq!(int_to_float(i32::MIN), -1.0);

assert_eq!(float_to_int(0.0), 0);
assert_eq!(float_to_int(-1.0), i32::MIN);
assert_eq!(float_to_int(-0.5), i32::MIN / 2);
assert_eq!(float_to_int(-0.25), i32::MIN / 4);
//assert_eq!(float_to_int(4.1909516e-9), 4);
assert_eq!(float_to_int(3.259629e-9), 3);
//assert_eq!(float_to_int(2.3283064e-9), 2);
assert_eq!(float_to_int(1.3969839e-9), 1);
assert_eq!(float_to_int(1.0), i32::MAX);
assert_eq!(float_to_int(0.5), i32::MAX / 2);
assert_eq!(float_to_int(0.25), i32::MAX / 4);

assert_eq!(float_to_int(6.9849193e-9), 14); // 7);
assert_eq!(float_to_int(6.0535967e-9), 12); // 6);
assert_eq!(float_to_int(5.122274e-09), 10); // 5);

assert_eq!(float_to_int(4.1909516e-9), 8); // 4);
assert_eq!(float_to_int(3.259629e-9), 6); // 3);
assert_eq!(float_to_int(2.3283064e-9), 4); // 2);
assert_eq!(float_to_int(1.3969839e-9), 2); // 1);
assert_eq!(float_to_int(2.0f32.powf(-31.0)), 0);
assert_eq!(float_to_int(-2.0f32.powf(-31.0)), -1);
assert_eq!(float_to_int(-1.3969839e-9), -2);
//assert_eq!(float_to_int(-2.3283064e-9), -3);
assert_eq!(float_to_int(-3.259629e-9), -4);
//assert_eq!(float_to_int(-4.1909516e-9), -5);
assert_eq!(float_to_int(0.25), i32::MAX / 4);
assert_eq!(float_to_int(0.5), i32::MAX / 2);
assert_eq!(float_to_int(1.0), i32::MAX);
assert_eq!(float_to_int(-1.3969839e-9), -3); // -2);
assert_eq!(float_to_int(-2.3283064e-9), -5); // -3);
assert_eq!(float_to_int(-3.259629e-9), -7); // -4);
assert_eq!(float_to_int(-4.1909516e-9), -9); // -5);

// FIXME: Missing

assert_eq!(float_to_int(-0.25), i32::MIN / 4);
assert_eq!(float_to_int(-0.5), i32::MIN / 2);
assert_eq!(float_to_int(-1.0), i32::MIN);
}
}

0 comments on commit 1e3328a

Please sign in to comment.