1#![unstable(
2 feature = "core_intrinsics_fallbacks",
3 reason = "The fallbacks will never be stable, as they exist only to be called \
4 by the fallback MIR, but they're exported so they can be tested on \
5 platforms where the fallback MIR isn't actually used",
6 issue = "none"
7)]
8#![allow(missing_docs)]
9
10#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
11pub const trait CarryingMulAdd: Copy + 'static {
12 type Unsigned: Copy + 'static;
13 fn carrying_mul_add(
14 self,
15 multiplicand: Self,
16 addend: Self,
17 carry: Self,
18 ) -> (Self::Unsigned, Self);
19}
20
21macro_rules! impl_carrying_mul_add_by_widening {
22 ($($t:ident $u:ident $w:ident,)+) => {$(
23 #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
24 const impl CarryingMulAdd for $t {
25 type Unsigned = $u;
26 #[inline]
27 fn carrying_mul_add(self, a: Self, b: Self, c: Self) -> ($u, $t) {
28 let wide = (self as $w) * (a as $w) + (b as $w) + (c as $w);
29 (wide as _, (wide >> Self::BITS) as _)
30 }
31 }
32 )+};
33}
34#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarryingMulAdd for u8 {
type Unsigned = u8;
#[inline]
fn carrying_mul_add(self, a: Self, b: Self, c: Self) -> (u8, u8) {
let wide = (self as u16) * (a as u16) + (b as u16) + (c as u16);
(wide as _, (wide >> Self::BITS) as _)
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarryingMulAdd for u16 {
type Unsigned = u16;
#[inline]
fn carrying_mul_add(self, a: Self, b: Self, c: Self) -> (u16, u16) {
let wide = (self as u32) * (a as u32) + (b as u32) + (c as u32);
(wide as _, (wide >> Self::BITS) as _)
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarryingMulAdd for u32 {
type Unsigned = u32;
#[inline]
fn carrying_mul_add(self, a: Self, b: Self, c: Self) -> (u32, u32) {
let wide = (self as u64) * (a as u64) + (b as u64) + (c as u64);
(wide as _, (wide >> Self::BITS) as _)
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarryingMulAdd for u64 {
type Unsigned = u64;
#[inline]
fn carrying_mul_add(self, a: Self, b: Self, c: Self) -> (u64, u64) {
let wide = (self as u128) * (a as u128) + (b as u128) + (c as u128);
(wide as _, (wide >> Self::BITS) as _)
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarryingMulAdd for usize {
type Unsigned = usize;
#[inline]
fn carrying_mul_add(self, a: Self, b: Self, c: Self) -> (usize, usize) {
let wide =
(self as UDoubleSize) * (a as UDoubleSize) + (b as UDoubleSize) +
(c as UDoubleSize);
(wide as _, (wide >> Self::BITS) as _)
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarryingMulAdd for i8 {
type Unsigned = u8;
#[inline]
fn carrying_mul_add(self, a: Self, b: Self, c: Self) -> (u8, i8) {
let wide = (self as i16) * (a as i16) + (b as i16) + (c as i16);
(wide as _, (wide >> Self::BITS) as _)
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarryingMulAdd for i16 {
type Unsigned = u16;
#[inline]
fn carrying_mul_add(self, a: Self, b: Self, c: Self) -> (u16, i16) {
let wide = (self as i32) * (a as i32) + (b as i32) + (c as i32);
(wide as _, (wide >> Self::BITS) as _)
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarryingMulAdd for i32 {
type Unsigned = u32;
#[inline]
fn carrying_mul_add(self, a: Self, b: Self, c: Self) -> (u32, i32) {
let wide = (self as i64) * (a as i64) + (b as i64) + (c as i64);
(wide as _, (wide >> Self::BITS) as _)
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarryingMulAdd for i64 {
type Unsigned = u64;
#[inline]
fn carrying_mul_add(self, a: Self, b: Self, c: Self) -> (u64, i64) {
let wide = (self as i128) * (a as i128) + (b as i128) + (c as i128);
(wide as _, (wide >> Self::BITS) as _)
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarryingMulAdd for isize {
type Unsigned = usize;
#[inline]
fn carrying_mul_add(self, a: Self, b: Self, c: Self) -> (usize, isize) {
let wide =
(self as UDoubleSize) * (a as UDoubleSize) + (b as UDoubleSize) +
(c as UDoubleSize);
(wide as _, (wide >> Self::BITS) as _)
}
}impl_carrying_mul_add_by_widening! {
35 u8 u8 u16,
36 u16 u16 u32,
37 u32 u32 u64,
38 u64 u64 u128,
39 usize usize UDoubleSize,
40 i8 u8 i16,
41 i16 u16 i32,
42 i32 u32 i64,
43 i64 u64 i128,
44 isize usize UDoubleSize,
45}
46
47#[cfg(target_pointer_width = "16")]
48type UDoubleSize = u32;
49#[cfg(target_pointer_width = "32")]
50type UDoubleSize = u64;
51#[cfg(target_pointer_width = "64")]
52type UDoubleSize = u128;
53
54#[inline]
55const fn wide_mul_u128(a: u128, b: u128) -> (u128, u128) {
56 #[inline]
57 const fn to_low_high(x: u128) -> [u128; 2] {
58 const MASK: u128 = u64::MAX as _;
59 [x & MASK, x >> 64]
60 }
61 #[inline]
62 const fn from_low_high(x: [u128; 2]) -> u128 {
63 x[0] | (x[1] << 64)
64 }
65 #[inline]
66 const fn scalar_mul(low_high: [u128; 2], k: u128) -> [u128; 3] {
67 let [x, c] = to_low_high(k * low_high[0]);
68 let [y, z] = to_low_high(k * low_high[1] + c);
69 [x, y, z]
70 }
71 let a = to_low_high(a);
72 let b = to_low_high(b);
73 let low = scalar_mul(a, b[0]);
74 let high = scalar_mul(a, b[1]);
75 let r0 = low[0];
76 let [r1, c] = to_low_high(low[1] + high[0]);
77 let [r2, c] = to_low_high(low[2] + high[1] + c);
78 let r3 = high[2] + c;
79 (from_low_high([r0, r1]), from_low_high([r2, r3]))
80}
81
82#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
83const impl CarryingMulAdd for u128 {
84 type Unsigned = u128;
85 #[inline]
86 fn carrying_mul_add(self, b: u128, c: u128, d: u128) -> (u128, u128) {
87 let (low, mut high) = wide_mul_u128(self, b);
88 let (low, carry) = u128::overflowing_add(low, c);
89 high += carry as u128;
90 let (low, carry) = u128::overflowing_add(low, d);
91 high += carry as u128;
92 (low, high)
93 }
94}
95
96#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
97const impl CarryingMulAdd for i128 {
98 type Unsigned = u128;
99 #[inline]
100 fn carrying_mul_add(self, b: i128, c: i128, d: i128) -> (u128, i128) {
101 let (low, high) = wide_mul_u128(self as u128, b as u128);
102 let mut high = high as i128;
103 high = high.wrapping_add(i128::wrapping_mul(self >> 127, b));
104 high = high.wrapping_add(i128::wrapping_mul(self, b >> 127));
105 let (low, carry) = u128::overflowing_add(low, c as u128);
106 high = high.wrapping_add((carry as i128) + (c >> 127));
107 let (low, carry) = u128::overflowing_add(low, d as u128);
108 high = high.wrapping_add((carry as i128) + (d >> 127));
109 (low, high)
110 }
111}
112
113#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
114pub const trait DisjointBitOr: Copy + 'static {
115 unsafe fn disjoint_bitor(self, other: Self) -> Self;
123}
124macro_rules! zero {
125 (bool) => {
126 false
127 };
128 ($t:ident) => {
129 0
130 };
131}
132macro_rules! impl_disjoint_bitor {
133 ($($t:ident,)+) => {$(
134 #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
135 const impl DisjointBitOr for $t {
136 #[cfg_attr(miri, track_caller)]
137 #[inline]
138 unsafe fn disjoint_bitor(self, other: Self) -> Self {
139 unsafe { super::assume((self & other) == zero!($t)) };
144 self | other
145 }
146 }
147 )+};
148}
149#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for bool {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == false) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for u8 {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for u16 {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for u32 {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for u64 {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for u128 {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for usize {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for i8 {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for i16 {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for i32 {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for i64 {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for i128 {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl DisjointBitOr for isize {
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
unsafe { super::assume((self & other) == 0) };
self | other
}
}impl_disjoint_bitor! {
150 bool,
151 u8, u16, u32, u64, u128, usize,
152 i8, i16, i32, i64, i128, isize,
153}
154
155#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
156pub const trait FunnelShift: Copy + 'static {
157 unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self;
165
166 unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self;
174}
175
176macro_rules! impl_funnel_shifts {
177 ($($type:ident),*) => {$(
178 #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
179 const impl FunnelShift for $type {
180 #[cfg_attr(miri, track_caller)]
181 #[inline]
182 unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self {
183 unsafe { super::assume(shift < $type::BITS) };
186 if shift == 0 {
187 self
188 } else {
189 unsafe {
197 super::disjoint_bitor(
198 super::unchecked_shl(self, shift),
199 super::unchecked_shr(right, $type::BITS - shift),
200 )
201 }
202 }
203 }
204
205 #[cfg_attr(miri, track_caller)]
206 #[inline]
207 unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self {
208 unsafe { super::assume(shift < $type::BITS) };
211 if shift == 0 {
212 right
213 } else {
214 unsafe {
222 super::disjoint_bitor(
223 super::unchecked_shl(self, $type::BITS - shift),
224 super::unchecked_shr(right, shift),
225 )
226 }
227 }
228 }
229 }
230 )*};
231}
232
233#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl FunnelShift for u8 {
#[inline]
unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < u8::BITS) };
if shift == 0 {
self
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self, shift),
super::unchecked_shr(right, u8::BITS - shift))
}
}
}
#[inline]
unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < u8::BITS) };
if shift == 0 {
right
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self,
u8::BITS - shift), super::unchecked_shr(right, shift))
}
}
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl FunnelShift for u16 {
#[inline]
unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < u16::BITS) };
if shift == 0 {
self
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self, shift),
super::unchecked_shr(right, u16::BITS - shift))
}
}
}
#[inline]
unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < u16::BITS) };
if shift == 0 {
right
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self,
u16::BITS - shift), super::unchecked_shr(right, shift))
}
}
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl FunnelShift for u32 {
#[inline]
unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < u32::BITS) };
if shift == 0 {
self
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self, shift),
super::unchecked_shr(right, u32::BITS - shift))
}
}
}
#[inline]
unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < u32::BITS) };
if shift == 0 {
right
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self,
u32::BITS - shift), super::unchecked_shr(right, shift))
}
}
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl FunnelShift for u64 {
#[inline]
unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < u64::BITS) };
if shift == 0 {
self
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self, shift),
super::unchecked_shr(right, u64::BITS - shift))
}
}
}
#[inline]
unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < u64::BITS) };
if shift == 0 {
right
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self,
u64::BITS - shift), super::unchecked_shr(right, shift))
}
}
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl FunnelShift for u128 {
#[inline]
unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < u128::BITS) };
if shift == 0 {
self
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self, shift),
super::unchecked_shr(right, u128::BITS - shift))
}
}
}
#[inline]
unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < u128::BITS) };
if shift == 0 {
right
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self,
u128::BITS - shift), super::unchecked_shr(right, shift))
}
}
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl FunnelShift for usize {
#[inline]
unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < usize::BITS) };
if shift == 0 {
self
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self, shift),
super::unchecked_shr(right, usize::BITS - shift))
}
}
}
#[inline]
unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self {
unsafe { super::assume(shift < usize::BITS) };
if shift == 0 {
right
} else {
unsafe {
super::disjoint_bitor(super::unchecked_shl(self,
usize::BITS - shift), super::unchecked_shr(right, shift))
}
}
}
}impl_funnel_shifts! {
234 u8, u16, u32, u64, u128, usize
235}
236
237#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
238pub const trait CarrylessMul: Copy + 'static {
239 fn carryless_mul(self, rhs: Self) -> Self;
242}
243
244macro_rules! impl_carryless_mul{
245 ($($type:ident),*) => {$(
246 #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
247 const impl CarrylessMul for $type {
248 #[inline]
249 fn carryless_mul(self, rhs: Self) -> Self {
250 let mut result = 0;
251 let mut i = 0;
252
253 while i < $type::BITS {
254 if (rhs >> i) & 1 != 0 {
256 result ^= self << i;
258 }
259 i += 1;
260 }
261
262 result
263 }
264 }
265 )*};
266}
267
268#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarrylessMul for u8 {
#[inline]
fn carryless_mul(self, rhs: Self) -> Self {
let mut result = 0;
let mut i = 0;
while i < u8::BITS {
if (rhs >> i) & 1 != 0 { result ^= self << i; }
i += 1;
}
result
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarrylessMul for u16 {
#[inline]
fn carryless_mul(self, rhs: Self) -> Self {
let mut result = 0;
let mut i = 0;
while i < u16::BITS {
if (rhs >> i) & 1 != 0 { result ^= self << i; }
i += 1;
}
result
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarrylessMul for u32 {
#[inline]
fn carryless_mul(self, rhs: Self) -> Self {
let mut result = 0;
let mut i = 0;
while i < u32::BITS {
if (rhs >> i) & 1 != 0 { result ^= self << i; }
i += 1;
}
result
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarrylessMul for u64 {
#[inline]
fn carryless_mul(self, rhs: Self) -> Self {
let mut result = 0;
let mut i = 0;
while i < u64::BITS {
if (rhs >> i) & 1 != 0 { result ^= self << i; }
i += 1;
}
result
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarrylessMul for u128 {
#[inline]
fn carryless_mul(self, rhs: Self) -> Self {
let mut result = 0;
let mut i = 0;
while i < u128::BITS {
if (rhs >> i) & 1 != 0 { result ^= self << i; }
i += 1;
}
result
}
}
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
const impl CarrylessMul for usize {
#[inline]
fn carryless_mul(self, rhs: Self) -> Self {
let mut result = 0;
let mut i = 0;
while i < usize::BITS {
if (rhs >> i) & 1 != 0 { result ^= self << i; }
i += 1;
}
result
}
}impl_carryless_mul! {
269 u8, u16, u32, u64, u128, usize
270}