Skip to main content

nanvm_lib/vm/bigint/
bitxor.rs

1use core::ops::BitXor;
2
3use crate::vm::{BigInt, IVm};
4
5impl<A: IVm> BitXor for BigInt<A> {
6    type Output = Self;
7    fn bitxor(self, rhs: Self) -> Self::Output {
8        self.bitwise_op(rhs, |a, b| a ^ b, |a_neg, b_neg| a_neg != b_neg)
9    }
10}
11
12#[cfg(test)]
13mod tests {
14    use crate::vm::bigint::test_util::{int, neg, pos};
15
16    #[test]
17    fn both_positive() {
18        assert_eq!(int(0b1100) ^ int(0b1010), int(0b0110));
19    }
20
21    #[test]
22    fn both_negative() {
23        // -1 ^ -1 == 0 (all-ones XOR all-ones cancels out).
24        assert_eq!(int(-1) ^ int(-1), int(0));
25        // -2 ^ -3 == 3: 0b...110 ^ 0b...101 == 0b...011.
26        assert_eq!(int(-2) ^ int(-3), int(3));
27    }
28
29    #[test]
30    fn mixed_signs() {
31        // 5 ^ -1 == -6 (XOR with all-ones flips every bit, i.e. bitwise NOT).
32        assert_eq!(int(5) ^ int(-1), int(-6));
33        assert_eq!(int(-1) ^ int(5), int(-6));
34    }
35
36    #[test]
37    fn with_zero() {
38        assert_eq!(int(0) ^ int(0), int(0));
39        assert_eq!(int(12_345) ^ int(0), int(12_345));
40        assert_eq!(int(-12_345) ^ int(0), int(-12_345));
41    }
42
43    #[test]
44    fn multi_word_carry_on_decode() {
45        // x = -(0xFFFFFFFF00000001), whose two's-complement word is
46        // 0x00000000FFFFFFFF; y = 0x00000000FFFFFFFF (positive, so its
47        // pattern is its own value). XORing equal words gives an all-zero
48        // pattern, so decoding the negative result must carry a brand-new
49        // second word into existence, giving -(2^64).
50        let x = neg([0xFFFF_FFFF_0000_0001u64]);
51        let y = pos([0x0000_0000_FFFF_FFFFu64]);
52        let expected = neg([0u64, 1u64]);
53        assert_eq!(x ^ y, expected);
54    }
55}