Created
September 1, 2018 05:42
-
-
Save ip/cf39979441efc9f1481bde105b5220a2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| public class PositiveOverflowException : Exception {} | |
| public class NegativeOverflowException : Exception {} | |
| // TODO: | |
| // - increment | |
| // - left shift | |
| public static class BitwiseArithmetics { | |
| private const int bitsNum = sizeof(int) * 8; | |
| public static int Sum(int a, int b) { | |
| int result = 0; | |
| bool carry = false; | |
| for (int i = 0; i != bitsNum; i++) { | |
| bool a_i = _GetBit(a, i); | |
| bool b_i = _GetBit(b, i); | |
| BitSumResult sum = _SumBits(a_i, b_i, carry); | |
| carry = sum.overflow; | |
| result = _SetBit(result, i, sum.result); | |
| bool isLastBit = i == bitsNum - 1; | |
| if (isLastBit) { | |
| _HandleOverflow(a_i, b_i, sum.result); | |
| } | |
| } | |
| return result; | |
| } | |
| private struct BitSumResult { | |
| public bool result, overflow; | |
| } | |
| private static BitSumResult _SumBits(bool a, bool b, bool carry) { | |
| bool overflow, result; | |
| if (carry) { | |
| if (a && b) { overflow = true; result = true; } | |
| if (a || b) { overflow = true; result = false; } | |
| else { overflow = false; result = true; } | |
| } else { | |
| if (a && b) { overflow = true; result = false; } | |
| if (a || b) { overflow = false; result = true; } | |
| else { overflow = false; result = false; } | |
| } | |
| return new BitSumResult { overflow = overflow, result = result }; | |
| } | |
| private static bool _GetBit(int num, int index) { | |
| int mask = 1 << index; | |
| return (num & mask) != 0; | |
| } | |
| private static int _SetBit(int num, int index, bool value) { | |
| int positionMask = 1 << index; | |
| int clearMask = ~positionMask; | |
| int valueMask = value ? positionMask : 0; | |
| return (num & clearMask) | valueMask; | |
| } | |
| private static void _HandleOverflow(bool aSign, bool bSign, bool resultSign) { | |
| bool sourceSignsMatch = !(aSign ^ bSign); | |
| bool signChanged = aSign ^ resultSign; | |
| bool isOverflow = sourceSignsMatch && signChanged; | |
| if (isOverflow) { | |
| if (resultSign) { | |
| throw new PositiveOverflowException(); | |
| } else { | |
| throw new NegativeOverflowException(); | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using NUnit.Framework; | |
| [TestFixture] | |
| public class BitwiseArithmeticsTest { | |
| [Test] | |
| public void SumsTwoPositives() { | |
| _TestPair(52985, 1293953); | |
| } | |
| [Test] | |
| public void SumsPositiveAndNegative() { | |
| _TestPair(92813, -2133); | |
| } | |
| [Test] | |
| public void SumsMinusOneAndOne() { | |
| _TestPair(-1, 1); | |
| } | |
| [Test] | |
| public void SumsTwoNegatives() { | |
| _TestPair(-81324897, -98234); | |
| } | |
| [Test] | |
| public void SumsPositiveAndZero() { | |
| _TestPair(1234, 0); | |
| } | |
| [Test] | |
| public void HandlesPositiveOverflow() { | |
| Assert.Throws<PositiveOverflowException>(() => { | |
| BitwiseArithmetics.Sum(Int32.MaxValue, 1); | |
| }); | |
| } | |
| [Test] | |
| public void HandlesNegativeOverflow() { | |
| Assert.Throws<NegativeOverflowException>(() => { | |
| BitwiseArithmetics.Sum(Int32.MinValue, -1); | |
| }); | |
| } | |
| private void _TestPair(int a, int b) { | |
| int expected = a + b; | |
| int actual = BitwiseArithmetics.Sum(a, b); | |
| Assert.AreEqual(expected, actual); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment