-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Closed
Labels
C-feature-requestCategory: A feature request, i.e: not implemented / a PR.Category: A feature request, i.e: not implemented / a PR.
Description
fn overflowing_difference_signed(a: unsigned, b: unsigned) -> (signed, bool);
This is useful in the case of
async fn seek(&mut self, seek: SeekFrom) -> Result<u64> {
match seek {
SeekFrom::Current(pos) => self.seek_relative(pos).await,
SeekFrom::End(pos) => ...
SeekFrom::Start(pos: u64) => {
if !self.stream_position_fast() {
return self.seek_inner(seek).await;
}
let stream_pos: u64 = self.stream_position().await?;
/* want to make sure pos - stream_pos can fit in an i64 without overflow */
/* stream_pos = u64::MAX, pos = 0, seek_relative = -1: wrong */
self.seek_relative(pos.wrapping_sub(stream_pos) as i64).await
}
}
}
This is better than casting u64s to u128s and doing try_into
i64 as u128s cannot be upgraded to u256s
GCC and Clang have this feature via
__builtin_sub_overflow(a, b, &output)
which generates the following code: https://godbolt.org/z/E64GnaEz6
This can be implemented in rust with sub_check2
: https://godbolt.org/z/dxrP4d9vT
which has zero branches for optimal performance
sub_large: 1.029584449 ns / rep
sub_check: 1.436846155 ns / rep
sub_check2: 1.02297698 ns / rep
CPU: AMD R7 5800X
New code:
let (pos: i64, overflow: bool) = pos.overflowing_difference_signed(stream_pos);
if overflow {
self.seek_inner(seek).await
} else {
self.seek_relative(pos)
}
Zoybean
Metadata
Metadata
Assignees
Labels
C-feature-requestCategory: A feature request, i.e: not implemented / a PR.Category: A feature request, i.e: not implemented / a PR.