# Floating point addition algorithm

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;

// Add the implicit leading 1 bit to the mantissas
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))
}
$$$$
`

## 1 Answer

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.

I would use something like the quickcheck crate (a port of Haskell's QuickCheck) to test the property of whether your addition function has the same results as ordinary f32 addition. If you don't know what quickcheck is, then this video might help.

Fuzzing your function as described in this video about Fuzz-Driven Development (FDD) might be another option.