important bugfix
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
Rust/spacepackets/pipeline/pr-main This commit looks good

This commit is contained in:
Robin Müller 2022-12-21 01:01:05 +01:00
parent f641248ac2
commit 3828a98c76
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC

View File

@ -64,10 +64,16 @@ pub fn fractional_part_from_subsec_ns(
if ns > sec_as_ns {
panic!("passed nanosecond value larger than 1 second");
}
let resolution = fractional_res_to_div(res) as u64;
// Use integer division because this can reduce code size of really small systems.
// First determine the nanoseconds for the smallest segment given the resolution.
// Then divide by that to find out the fractional part. An integer division floors
// which is what we want here.
let fractional_part = ns / (sec_as_ns / fractional_res_to_div(res) as u64);
// Then divide by that to find out the fractional part. For the calculation of the smallest
// fraction, we perform a ceiling division. This is because if we would use the default
// flooring division, we would divide by a smaller value, thereby allowing the calculation to
// invalid fractional parts which are too large. For the division of the nanoseconds by the
// smallest fraction, a flooring division is correct.
// The multiplication with 100000 is necessary to avoid precision loss during integer division.
let fractional_part = ns * 100000 / ((sec_as_ns * 100000 + resolution) / resolution);
Some(FractionalPart(res, fractional_part as u32))
}
@ -914,4 +920,12 @@ mod tests {
let res = stamp.update_from_now();
assert!(res.is_ok());
}
#[test]
fn assert_largest_fractions() {
let fractions = fractional_part_from_subsec_ns(FractionalResolution::SixtyNs, 10u64.pow(9) - 1).unwrap();
// The value can not be larger than representable by 3 bytes
// Assert that the maximum resolution can be reached
assert_eq!(fractions.1, 2_u32.pow(3 * 8) - 2);
}
}