I made a function in Rust to add two floating point numbers (f32s) together using only their bit representation and integer operations. I have tested it for a quite a few different cases but I'm not sure how I can efficiently test it for all floating point numbers without it taking ages.

fn add_f32(mut a: f32, mut b: f32) -> f32 {
if b > a {
// If b has a larger exponent than a, swap a and b so that a has the larger exponent
core::mem::swap(&mut a, &mut b);
}

let a_normal = a.is_normal();
let b_normal = b.is_normal();

let a_bits = a.to_bits();
let b_bits = b.to_bits();
let mut a_exp = (a_bits << 1) >> (23 + 1);
let mut b_exp = (b_bits << 1) >> (23 + 1);

let mut a_mant = a_bits & 0x007fffff;
let mut b_mant = b_bits & 0x007fffff;

if a_exp == 0 {
a_exp += 1;
}
if b_exp == 0 {
b_exp += 1;
}

let exp_diff = a_exp - b_exp;

let sticky_bit = b_mant.trailing_zeros() + 1 < exp_diff;

if a_normal {
a_mant |= 1 << 23;
}
if b_normal {
b_mant |= 1 << 23;
}

// Append extra bits to the mantissas to ensure correct rounding
a_mant <<= 2;
b_mant <<= 2;

// If the shift causes an overflow, the b_mant is too small so is set to 0
b_mant = b_mant.checked_shr(exp_diff).unwrap_or(0);

if sticky_bit {
b_mant |= 1;
}

let mut mant = a_mant + b_mant;

let overflow = (mant >> 26) != 0;
if !overflow {
if mant & 0b11 == 0b11 {
mant += 0b100;
if (mant >> 26) != 0 {
mant >>= 1;
a_exp += 1;
}
} else if mant & 0b110 == 0b110 {
mant += 0b100;
if (mant >> 26) != 0 {
mant >>= 1;
a_exp += 1;
}
}
} else {
match mant & 0b111 {
0b111 | 0b110 | 0b101 => {
mant += 0b1000;
},
0b100 => {
if mant & 0b1000 == 0b1000 {
mant += 0b1000;
}
},
_ => {},
}

mant >>= 1;
a_exp += 1;
}

mant >>= 2;

if mant >> 23 == 0 {
a_exp = 0;
} else {
mant <<= 9;
mant >>= 9;
}

f32::from_bits(mant | (a_exp << 23))
}
$$$$

• Did you finally checked this (nice) code ?
– JCLL
Commented Jan 8 at 18:13
• @JCLL Yes, I tested it a while ago and completely forgot to update the post! It works so long as a and b are finite (also can't be NaN), both have positive sign, and as long as a + b` is not infinite. Obviously the code can be easily modified to account for these cases. Commented Jan 9 at 21:23