| ... | ... | @@ -219,11 +219,59 @@ pub fn negate(x: var) -> %@typeOf(x) { |
| 219 | 219 | } |
| 220 | 220 | |
| 221 | 221 | error Overflow; |
| 222 | | pub fn shl(comptime T: type, a: T, shift_amt: Log2Int(T)) -> %T { |
| 222 | pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) -> %T { |
| 223 | 223 | var answer: T = undefined; |
| 224 | 224 | if (@shlWithOverflow(T, a, shift_amt, &answer)) error.Overflow else answer |
| 225 | 225 | } |
| 226 | 226 | |
| 227 | /// Shifts left. Overflowed bits are truncated. |
| 228 | /// A negative shift amount results in a right shift. |
| 229 | pub 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 | |
| 244 | test "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. |
| 253 | pub 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 | |
| 268 | test "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 | |
| 227 | 275 | pub fn Log2Int(comptime T: type) -> type { |
| 228 | 276 | @IntType(false, log2(T.bit_count)) |
| 229 | 277 | } |
| ... | ... | @@ -237,7 +285,7 @@ fn testOverflow() { |
| 237 | 285 | assert(%%mul(i32, 3, 4) == 12); |
| 238 | 286 | assert(%%add(i32, 3, 4) == 7); |
| 239 | 287 | assert(%%sub(i32, 3, 4) == -1); |
| 240 | | assert(%%shl(i32, 0b11, 4) == 0b110000); |
| 288 | assert(%%shlExact(i32, 0b11, 4) == 0b110000); |
| 241 | 289 | } |
| 242 | 290 | |
| 243 | 291 | |