コード例 #1
0
        public static byte[] AddUnsignedBigEndian([NotNull] byte[] right,
                                                  [NotNull] byte[] left)
        {
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }

            var enumerable  = new ConcurrentBigEndianByteEnumerable(left, right).GetLsbToMsbEnumerable();
            var resultStack = new Stack <byte>(); // use stack for filo
            var carry       = 0;

            foreach (var(leftByte, rightByte) in enumerable)
            {
                var sum = carry + leftByte + rightByte;

                resultStack.Push((byte)(sum & 0xFF)); // push the byte value of sum
                carry = sum >> 8;                     // new carry value is sum shifted by 8 bits (a byte)
            }

            if (carry != 0)                    // if a carry value exists it should be pushed as it is the new MSB
            {
                resultStack.Push((byte)carry); // push carry
            }

            return(resultStack.ToArray());
        }
コード例 #2
0
        /// <summary>
        ///     Compare two unsigned big endian <see cref="byte" /> arrays
        /// </summary>
        /// <param name="left">the left side operand</param>
        /// <param name="right">the right side operand</param>
        public static int CompareUnsignedBigEndian([NotNull] byte[] left,
                                                   [NotNull] byte[] right)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }

            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            var enumerable = new ConcurrentBigEndianByteEnumerable(left, right).GetMsbToLsbEnumerable();

            foreach (var(leftByte, rightByte) in enumerable)
            {
                var comparison = leftByte.CompareTo(rightByte);

                if (comparison != 0)
                {
                    return(comparison > 0
                               ? 1
                               : -1);
                }
            }

            return(0); // bytes are equal
        }
コード例 #3
0
        public void ReverseIterate_FromByteEnumerable_Trimmed_Test(byte[] leftBytes,
                                                                   byte[] rightBytes)
        {
            // Arrange
            this._testOutputHelper.WriteLine($"left: [{leftBytes.ToString("h")}]");
            this._testOutputHelper.WriteLine($"right: [{rightBytes.ToString("h")}]");

            var expectedTrimmedLeftLength = leftBytes.SkipWhile(b => b == 0x00)
                                            .Count();
            var expectedTrimmedRightLength = rightBytes.SkipWhile(b => b == 0x00)
                                             .Count();
            var length = Math.Max(expectedTrimmedLeftLength, expectedTrimmedRightLength);

            this._testOutputHelper.WriteLine($"expectedLength: {length}");

            var expectedLeft = Enumerable.Repeat((byte)0x00, length - expectedTrimmedLeftLength)
                               .Concat(leftBytes.Skip(leftBytes.Length - expectedTrimmedLeftLength))
                               .Reverse()
                               .ToArray();

            var expectedRight = Enumerable.Repeat((byte)0x00, length - expectedTrimmedRightLength)
                                .Concat(rightBytes.Skip(rightBytes.Length - expectedTrimmedRightLength))
                                .Reverse()
                                .ToArray();

            this._testOutputHelper.WriteLine($"expected left: [{expectedLeft.ToString("h")}]");
            this._testOutputHelper.WriteLine($"expected right: [{expectedRight.ToString("h")}]");

            var enumerable = new ConcurrentBigEndianByteEnumerable(leftBytes, rightBytes);

            // Act
            var result = enumerable.ReverseEnumerable()
                         .ToList();

            // Assert
            Assert.NotNull(result);
            Assert.IsAssignableFrom <IReadOnlyCollection <(byte leftByte, byte rightByte)> >(result);

            Assert.Equal(length, result.Count);

            var leftResult = result.Select(tuple => tuple.leftByte)
                             .ToArray();
            var rightResult = result.Select(tuple => tuple.rightByte)
                              .ToArray();

            this._testOutputHelper.WriteLine($"resulting left: [{leftResult.ToString("h")}]");
            this._testOutputHelper.WriteLine($"resulting right: [{rightResult.ToString("h")}]");

            Assert.Equal(expectedLeft, leftResult);
            Assert.Equal(expectedRight, rightResult);
            Assert.Equal(length, enumerable.Count);
        }
コード例 #4
0
        public static byte[] SubtractUnsignedBigEndian([NotNull] byte[] left,
                                                       [NotNull] byte[] right)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }

            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            var byteComparison = CompareUnsignedBigEndian(left, right);

            if (byteComparison == 0)
            {
                return(Array.Empty <byte>());
            }

            if (byteComparison == -1)
            {
                throw new InvalidOperationException("This operation would create an unsupported signed result");
            }

            var enumerable  = new ConcurrentBigEndianByteEnumerable(left, right).GetLsbToMsbEnumerable();
            var resultStack = new Stack <byte>();
            var borrowed    = false;

            foreach (var(leftByte, rightByte) in enumerable)
            {
                byte minuend; // min·u·end /ˈminyəˌwend/ (noun) a quantity or number from which another is to be subtracted. Not to be confused with the subtrahend. Duh.
                var  canBorrow = leftByte > 0;

                if (borrowed && canBorrow)          // previous operation needed to borrow, and a borrow is possible
                {
                    minuend = (byte)(leftByte - 1); // decrement as this value has been borrowed from in the previous iteration
                }
                else if (borrowed)                  // && !canBorrow (implied)
                {
                    minuend = 0xff;                 // 0 byte becomes 255
                }
                else
                {
                    minuend = leftByte;
                }

                if (minuend >= rightByte) // left is big enough to subtract right
                {
                    var difference = (byte)(minuend - rightByte);
                    resultStack.Push(difference);

                    borrowed = borrowed && !canBorrow; // set borrow if a borrow happened some time previously but it could not be accommodated in this iteration; borrow from next
                }
                else // left is less than right, automatically borrow from next iteration
                {
                    var difference = (byte)((minuend + 0x0100) - rightByte); // handle borrowed
                    resultStack.Push(difference);
                    borrowed = true;
                }
            }

            return(resultStack.ToArray()
                   .TrimBigEndianLeadingZeroBytes());           // TODO, do without explicit trimming?
        }