use crate::cmp::Ordering;
use crate::fmt;
use crate::hash;
-use crate::intrinsics;
+use crate::intrinsics::{self, is_aligned_and_not_null, is_nonoverlapping};
use crate::mem::{self, MaybeUninit};
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
#[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
+ debug_assert!(is_aligned_and_not_null(x), "attempt to swap unaligned or null pointer");
+ debug_assert!(is_aligned_and_not_null(y), "attempt to swap unaligned or null pointer");
+ debug_assert!(is_nonoverlapping(x, y, count), "attempt to swap overlapping memory");
+
let x = x as *mut u8;
let y = y as *mut u8;
let len = mem::size_of::<T>() * count;
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn read<T>(src: *const T) -> T {
+ // `copy_nonoverlapping` takes care of debug_assert.
let mut tmp = MaybeUninit::<T>::uninit();
copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
tmp.assume_init()
#[inline]
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
pub unsafe fn read_unaligned<T>(src: *const T) -> T {
+ // `copy_nonoverlapping` takes care of debug_assert.
let mut tmp = MaybeUninit::<T>::uninit();
copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::<T>());
tmp.assume_init()
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn write<T>(dst: *mut T, src: T) {
+ // FIXME: the debug assertion here causes codegen test failures on some architectures.
+ // See <https://github.com/rust-lang/rust/pull/69208#issuecomment-591326757>.
+ // debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
intrinsics::move_val_init(&mut *dst, src)
}
#[inline]
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
+ // `copy_nonoverlapping` takes care of debug_assert.
copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::<T>());
mem::forget(src);
}
#[inline]
#[stable(feature = "volatile", since = "1.9.0")]
pub unsafe fn read_volatile<T>(src: *const T) -> T {
+ debug_assert!(is_aligned_and_not_null(src), "attempt to read from unaligned or null pointer");
intrinsics::volatile_load(src)
}
#[inline]
#[stable(feature = "volatile", since = "1.9.0")]
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
+ debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
intrinsics::volatile_store(dst, src);
}
// uses e.g., subtraction `mod n`. It is entirely fine to do them `mod
// usize::max_value()` instead, because we take the result `mod n` at the end
// anyway.
- inverse = inverse.wrapping_mul(2usize.wrapping_sub(x.wrapping_mul(inverse)))
- & (going_mod - 1);
- if going_mod > m {
+ inverse = inverse.wrapping_mul(2usize.wrapping_sub(x.wrapping_mul(inverse)));
+ if going_mod >= m {
return inverse & (m - 1);
}
going_mod = going_mod.wrapping_mul(going_mod);
let gcdpow = intrinsics::cttz_nonzero(stride).min(intrinsics::cttz_nonzero(a));
let gcd = 1usize << gcdpow;
- if p as usize & (gcd - 1) == 0 {
+ if p as usize & (gcd.wrapping_sub(1)) == 0 {
// This branch solves for the following linear congruence equation:
//
- // $$ p + so ≡ 0 mod a $$
+ // ` p + so = 0 mod a `
//
- // $p$ here is the pointer value, $s$ – stride of `T`, $o$ offset in `T`s, and $a$ – the
+ // `p` here is the pointer value, `s` - stride of `T`, `o` offset in `T`s, and `a` - the
// requested alignment.
//
- // g = gcd(a, s)
- // o = (a - (p mod a))/g * ((s/g)⁻¹ mod a)
+ // With `g = gcd(a, s)`, and the above asserting that `p` is also divisible by `g`, we can
+ // denote `a' = a/g`, `s' = s/g`, `p' = p/g`, then this becomes equivalent to:
+ //
+ // ` p' + s'o = 0 mod a' `
+ // ` o = (a' - (p' mod a')) * (s'^-1 mod a') `
//
- // The first term is “the relative alignment of p to a”, the second term is “how does
- // incrementing p by s bytes change the relative alignment of p”. Division by `g` is
- // necessary to make this equation well formed if $a$ and $s$ are not co-prime.
+ // The first term is "the relative alignment of `p` to `a`" (divided by the `g`), the second
+ // term is "how does incrementing `p` by `s` bytes change the relative alignment of `p`" (again
+ // divided by `g`).
+ // Division by `g` is necessary to make the inverse well formed if `a` and `s` are not
+ // co-prime.
//
- // Furthermore, the result produced by this solution is not “minimal”, so it is necessary
- // to take the result $o mod lcm(s, a)$. We can replace $lcm(s, a)$ with just a $a / g$.
- let j = a.wrapping_sub(pmoda) >> gcdpow;
- let k = smoda >> gcdpow;
- return intrinsics::unchecked_rem(j.wrapping_mul(mod_inv(k, a)), a >> gcdpow);
+ // Furthermore, the result produced by this solution is not "minimal", so it is necessary
+ // to take the result `o mod lcm(s, a)`. We can replace `lcm(s, a)` with just a `a'`.
+ let a2 = a >> gcdpow;
+ let a2minus1 = a2.wrapping_sub(1);
+ let s2 = smoda >> gcdpow;
+ let minusp2 = a2.wrapping_sub(pmoda >> gcdpow);
+ return (minusp2.wrapping_mul(mod_inv(s2, a2))) & a2minus1;
}
// Cannot be aligned at all.