Skip to content

Commit 2a89d0e

Browse files
committed
Macro-ify udivmod
1 parent 3923ece commit 2a89d0e

File tree

1 file changed

+131
-124
lines changed

1 file changed

+131
-124
lines changed

src/int/udiv.rs

Lines changed: 131 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -114,152 +114,159 @@ pub extern "C" fn __umoddi3(a: u64, b: u64) -> u64 {
114114
rem
115115
}
116116

117-
/// Returns `n / d` and sets `*rem = n % d`
118-
#[cfg_attr(not(test), no_mangle)]
119-
pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
120-
// NOTE X is unknown, K != 0
121-
if n.high() == 0 {
122-
if d.high() == 0 {
123-
// 0 X
124-
// ---
125-
// 0 X
117+
macro_rules! udivmod_inner {
118+
($n:expr, $d:expr, $rem:expr, $ty:ty, $tys:ty, $tyh:ty) => {{
119+
let (n, d, rem) = ($n, $d, $rem);
120+
// NOTE X is unknown, K != 0
121+
if n.high() == 0 {
122+
if d.high() == 0 {
123+
// 0 X
124+
// ---
125+
// 0 X
126+
127+
if let Some(rem) = rem {
128+
*rem = <$ty>::from(urem!(n.low(), d.low()));
129+
}
130+
return <$ty>::from(udiv!(n.low(), d.low()));
131+
} else {
132+
// 0 X
133+
// ---
134+
// K X
135+
if let Some(rem) = rem {
136+
*rem = n;
137+
}
138+
return 0;
139+
};
140+
}
126141

127-
if let Some(rem) = rem {
128-
*rem = u64::from(urem!(n.low(), d.low()));
142+
let mut sr;
143+
let mut q;
144+
let mut r;
145+
146+
if d.low() == 0 {
147+
if d.high() == 0 {
148+
// K X
149+
// ---
150+
// 0 0
151+
// NOTE This should be unreachable in safe Rust because the program will panic before
152+
// this intrinsic is called
153+
unsafe {
154+
intrinsics::abort()
155+
}
129156
}
130-
return u64::from(udiv!(n.low(), d.low()));
131-
} else {
132-
// 0 X
133-
// ---
134-
// K X
135-
if let Some(rem) = rem {
136-
*rem = n;
137-
}
138-
return 0;
139-
};
140-
}
141-
142-
let mut sr;
143-
let mut q;
144-
let mut r;
145157

146-
if d.low() == 0 {
147-
if d.high() == 0 {
148-
// K X
149-
// ---
150-
// 0 0
151-
// NOTE This should be unreachable in safe Rust because the program will panic before
152-
// this intrinsic is called
153-
unsafe {
154-
intrinsics::abort()
158+
if n.low() == 0 {
159+
// K 0
160+
// ---
161+
// K 0
162+
if let Some(rem) = rem {
163+
*rem = <$ty>::from_parts(0, urem!(n.high(), d.high()));
164+
}
165+
return <$ty>::from(udiv!(n.high(), d.high()));
155166
}
156-
}
157167

158-
if n.low() == 0 {
159-
// K 0
168+
// K K
160169
// ---
161170
// K 0
162-
if let Some(rem) = rem {
163-
*rem = u64::from_parts(0, urem!(n.high(), d.high()));
171+
172+
if d.high().is_power_of_two() {
173+
if let Some(rem) = rem {
174+
*rem = <$ty>::from_parts(n.low(), n.high() & (d.high() - 1));
175+
}
176+
return <$ty>::from(n.high() >> d.high().trailing_zeros());
164177
}
165-
return u64::from(udiv!(n.high(), d.high()));
166-
}
167178

168-
// K K
169-
// ---
170-
// K 0
179+
sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
171180

172-
if d.high().is_power_of_two() {
173-
if let Some(rem) = rem {
174-
*rem = u64::from_parts(n.low(), n.high() & (d.high() - 1));
181+
// D > N
182+
if sr > <$tyh>::bits() - 2 {
183+
if let Some(rem) = rem {
184+
*rem = n;
185+
}
186+
return 0;
175187
}
176-
return u64::from(n.high() >> d.high().trailing_zeros());
177-
}
178188

179-
sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
189+
sr += 1;
180190

181-
// D > N
182-
if sr > u32::bits() - 2 {
183-
if let Some(rem) = rem {
184-
*rem = n;
191+
// 1 <= sr <= <$tyh>::bits() - 1
192+
q = n << (<$ty>::bits() - sr);
193+
r = n >> sr;
194+
} else if d.high() == 0 {
195+
// K X
196+
// ---
197+
// 0 K
198+
if d.low().is_power_of_two() {
199+
if let Some(rem) = rem {
200+
*rem = <$ty>::from(n.low() & (d.low() - 1));
201+
}
202+
203+
if d.low() == 1 {
204+
return n;
205+
} else {
206+
let sr = d.low().trailing_zeros();
207+
return n >> sr;
208+
};
185209
}
186-
return 0;
187-
}
188210

189-
sr += 1;
190-
191-
// 1 <= sr <= u32::bits() - 1
192-
q = n << (u64::bits() - sr);
193-
r = n >> sr;
194-
} else if d.high() == 0 {
195-
// K X
196-
// ---
197-
// 0 K
198-
if d.low().is_power_of_two() {
199-
if let Some(rem) = rem {
200-
*rem = u64::from(n.low() & (d.low() - 1));
201-
}
211+
sr = 1 + <$tyh>::bits() + d.low().leading_zeros() - n.high().leading_zeros();
202212

203-
if d.low() == 1 {
204-
return n;
205-
} else {
206-
let sr = d.low().trailing_zeros();
207-
return n >> sr;
208-
};
209-
}
210-
211-
sr = 1 + u32::bits() + d.low().leading_zeros() - n.high().leading_zeros();
212-
213-
// 2 <= sr <= u64::bits() - 1
214-
q = n << (u64::bits() - sr);
215-
r = n >> sr;
216-
} else {
217-
// K X
218-
// ---
219-
// K K
220-
sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
221-
222-
// D > N
223-
if sr > u32::bits() - 1 {
224-
if let Some(rem) = rem {
225-
*rem = n;
213+
// 2 <= sr <= u64::bits() - 1
214+
q = n << (<$ty>::bits() - sr);
215+
r = n >> sr;
216+
} else {
217+
// K X
218+
// ---
219+
// K K
220+
sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
221+
222+
// D > N
223+
if sr > <$tyh>::bits() - 1 {
224+
if let Some(rem) = rem {
225+
*rem = n;
226+
}
227+
return 0;
226228
}
227-
return 0;
228-
}
229229

230-
sr += 1;
230+
sr += 1;
231231

232-
// 1 <= sr <= u32::bits()
233-
q = n << (u64::bits() - sr);
234-
r = n >> sr;
235-
}
236-
237-
// Not a special case
238-
// q and r are initialized with
239-
// q = n << (u64::bits() - sr)
240-
// r = n >> sr
241-
// 1 <= sr <= u64::bits() - 1
242-
let mut carry = 0;
232+
// 1 <= sr <= <$tyh>::bits()
233+
q = n << (<$ty>::bits() - sr);
234+
r = n >> sr;
235+
}
243236

244-
for _ in 0..sr {
245-
// r:q = ((r:q) << 1) | carry
246-
r = (r << 1) | (q >> (u64::bits() - 1));
247-
q = (q << 1) | carry as u64;
237+
// Not a special case
238+
// q and r are initialized with
239+
// q = n << (u64::bits() - sr)
240+
// r = n >> sr
241+
// 1 <= sr <= u64::bits() - 1
242+
let mut carry = 0;
243+
244+
for _ in 0..sr {
245+
// r:q = ((r:q) << 1) | carry
246+
r = (r << 1) | (q >> (<$ty>::bits() - 1));
247+
q = (q << 1) | carry as $ty;
248+
249+
// carry = 0
250+
// if r >= d {
251+
// r -= d;
252+
// carry = 1;
253+
// }
254+
let s = (d.wrapping_sub(r).wrapping_sub(1)) as $tys >> (<$ty>::bits() - 1);
255+
carry = (s & 1) as $tyh;
256+
r -= d & s as $ty;
257+
}
248258

249-
// carry = 0
250-
// if r >= d {
251-
// r -= d;
252-
// carry = 1;
253-
// }
254-
let s = (d.wrapping_sub(r).wrapping_sub(1)) as i64 >> (u64::bits() - 1);
255-
carry = (s & 1) as u32;
256-
r -= d & s as u64;
257-
}
259+
if let Some(rem) = rem {
260+
*rem = r;
261+
}
262+
(q << 1) | carry as $ty
263+
}}
264+
}
258265

259-
if let Some(rem) = rem {
260-
*rem = r;
261-
}
262-
(q << 1) | carry as u64
266+
/// Returns `n / d` and sets `*rem = n % d`
267+
#[cfg_attr(not(test), no_mangle)]
268+
pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
269+
udivmod_inner!(n, d, rem, u64, i64, u32)
263270
}
264271

265272
#[cfg(test)]

0 commit comments

Comments
 (0)