authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-30 21:09:58-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-30 21:09:58-04:00
log844e05f619d62c1c2a332c1effa3ab6c211b3062
treec20bb93357926a7d35164f5b0a92995daa70bae2
parentc6295fe9abf5508d522ab4000b577a6f30a98a88

improve bit shift API in std.math

* `shl` moved to `shlExact` * added `shl` and `shr` which are truncating like `<<` and `>>`. closes #403

1 files changed, 50 insertions(+), 2 deletions(-)

std/math/index.zig+50-2
......@@ -219,11 +219,59 @@ pub fn negate(x: var) -> %@typeOf(x) {
219219}
220220
221221error Overflow;
222pub fn shl(comptime T: type, a: T, shift_amt: Log2Int(T)) -> %T {
222pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) -> %T {
223223 var answer: T = undefined;
224224 if (@shlWithOverflow(T, a, shift_amt, &answer)) error.Overflow else answer
225225}
226226
227/// Shifts left. Overflowed bits are truncated.
228/// A negative shift amount results in a right shift.
229pub fn shl(comptime T: type, a: T, shift_amt: var) -> T {
230 const abs_shift_amt = absCast(shift_amt);
231 const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else Log2Int(T)(abs_shift_amt);
232
233 if (@typeOf(shift_amt).is_signed) {
234 if (shift_amt >= 0) {
235 return a << casted_shift_amt;
236 } else {
237 return a >> casted_shift_amt;
238 }
239 }
240
241 return a << casted_shift_amt;
242}
243
244test "math.shl" {
245 assert(shl(u8, 0b11111111, usize(3)) == 0b11111000);
246 assert(shl(u8, 0b11111111, usize(8)) == 0);
247 assert(shl(u8, 0b11111111, usize(9)) == 0);
248 assert(shl(u8, 0b11111111, isize(-2)) == 0b00111111);
249}
250
251/// Shifts right. Overflowed bits are truncated.
252/// A negative shift amount results in a lefft shift.
253pub fn shr(comptime T: type, a: T, shift_amt: var) -> T {
254 const abs_shift_amt = absCast(shift_amt);
255 const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else Log2Int(T)(abs_shift_amt);
256
257 if (@typeOf(shift_amt).is_signed) {
258 if (shift_amt >= 0) {
259 return a >> casted_shift_amt;
260 } else {
261 return a << casted_shift_amt;
262 }
263 }
264
265 return a >> casted_shift_amt;
266}
267
268test "math.shr" {
269 assert(shr(u8, 0b11111111, usize(3)) == 0b00011111);
270 assert(shr(u8, 0b11111111, usize(8)) == 0);
271 assert(shr(u8, 0b11111111, usize(9)) == 0);
272 assert(shr(u8, 0b11111111, isize(-2)) == 0b11111100);
273}
274
227275pub fn Log2Int(comptime T: type) -> type {
228276 @IntType(false, log2(T.bit_count))
229277}
......@@ -237,7 +285,7 @@ fn testOverflow() {
237285 assert(%%mul(i32, 3, 4) == 12);
238286 assert(%%add(i32, 3, 4) == 7);
239287 assert(%%sub(i32, 3, 4) == -1);
240 assert(%%shl(i32, 0b11, 4) == 0b110000);
288 assert(%%shlExact(i32, 0b11, 4) == 0b110000);
241289}
242290
243291