Unsigned Arithmetic Operations
For now arithmetic operations within Gulliver have been limited to those involving the treatment of byte arrays as unsigned integer values. Negative numbers and floating point values are (for the moment) out of scope for the needs of this library.
Note
Unless otherwise stated the following methods are statically defined in the ByteArrayUtils class and do not modify their input.
Addition
Both the ByteArrayUtils.AddUnsignedBigEndian and ByteArrayUtils.AddUnsignedLittleEndian methods return the addition result of the provided right and left byte arrays accounting for the appropriate endiness of the input.
Big Endian
public static byte[] ByteArrayUtils.AddUnsignedBigEndian(byte[] right, byte[] left)
public static void AddUnsignedBigEndianExample()
{
// Setup
var lhs = new byte[] { 0xAD, 0xDE, 0xD0 };
var rhs = new byte[] { 0xC0, 0xDE };
// Act
var result = ByteArrayUtils.AddUnsignedBigEndian(lhs, rhs);
// Conclusion
Console.WriteLine("AddUnsignedBigEndian Example");
Console.WriteLine($"lhs:\t{lhs.ToString("H")}");
Console.WriteLine($"rhs:\t{rhs.ToString("H")}");
Console.WriteLine($"result:\t{result.ToString("H")}");
Console.WriteLine(string.Empty);
Console.WriteLine($"lhs:\t{lhs.ToString("IBE")}");
Console.WriteLine($"rhs:\t{rhs.ToString("IBE")}");
Console.WriteLine($"result:\t{result.ToString("IBE")}");
Console.WriteLine(string.Empty);
}
AddUnsignedBigEndian Example
lhs: AD DE D0
rhs: C0 DE
result: AE 9F AE
lhs: 11394768
rhs: 49374
result: 11444142
Little Endian
public static byte[] ByteArrayUtils.AddUnsignedLittleEndian(byte[] left, byte[] right)
public static void AddUnsignedLittleEndianExample()
{
// Setup
var lhs = new byte[] { 0xAD, 0xDE, 0xD0 };
var rhs = new byte[] { 0xC0, 0xDE };
// Act
var result = ByteArrayUtils.AddUnsignedLittleEndian(lhs, rhs);
// Conclusion
Console.WriteLine("AddUnsignedLittleEndian Example");
Console.WriteLine($"lhs:\t{lhs.ToString("H")}");
Console.WriteLine($"rhs:\t{rhs.ToString("H")}");
Console.WriteLine($"result:\t{result.ToString("H")}");
Console.WriteLine(string.Empty);
Console.WriteLine($"lhs:\t{lhs.ToString("ILE")}");
Console.WriteLine($"rhs:\t{rhs.ToString("ILE")}");
Console.WriteLine($"result:\t{result.ToString("ILE")}");
Console.WriteLine(string.Empty);
}
AddUnsignedLittleEndian Example
lhs: AD DE D0
rhs: C0 DE
result: 6D BD D1
lhs: 13688493
rhs: 57024
result: 13745517
Subtraction
Both the ByteArrayUtils.SubtractUnsignedBigEndian and ByteArrayUtils.SubtractUnsignedLittleEndian methods return the subtraction result of the provided right (minuend) and left (subtrahend) byte arrays accounting for the appropriate endiness of the input.
Warning
If the operation would result in a negative value, given we’re only dealing with unsigned integer operations, the execution will throw an InvalidOperationException.
Big Endian
public static byte[] ByteArrayUtils.SubtractUnsignedBigEndian(byte[] left, byte[] right)
public static void SubtractUnsignedBigEndianExample()
{
// Setup
var lhs = new byte[] { 0xDE, 0x1E, 0x7E, 0xD0 };
var rhs = new byte[] { 0xC0, 0xDE };
// Act
var result = ByteArrayUtils.SubtractUnsignedBigEndian(lhs, rhs);
// Conclusion
Console.WriteLine("SubtractUnsignedBigEndian Example");
Console.WriteLine($"lhs:\t{lhs.ToString("H")}");
Console.WriteLine($"rhs:\t{rhs.ToString("H")}");
Console.WriteLine($"result:\t{result.ToString("H")}");
Console.WriteLine(string.Empty);
Console.WriteLine($"lhs:\t{lhs.ToString("IBE")}");
Console.WriteLine($"rhs:\t{rhs.ToString("IBE")}");
Console.WriteLine($"result:\t{result.ToString("IBE")}");
Console.WriteLine(string.Empty);
}
SubtractUnsignedBigEndian Example
lhs: DE 1E 7E D0
rhs: C0 DE
result: DE 1D BD F2
lhs: 3726540496
rhs: 49374
result: 3726491122
Little Endian
public static byte[] ByteArrayUtils.SubtractUnsignedLittleEndian(byte[] left, byte[] right)
public static void SubtractUnsignedLittleEndianExample()
{
// Setup
var lhs = new byte[] { 0xDE, 0x1E, 0x7E, 0xD0 };
var rhs = new byte[] { 0xC0, 0xDE };
// Act
var result = ByteArrayUtils.SubtractUnsignedLittleEndian(lhs, rhs);
// Conclusion
Console.WriteLine("SubtractUnsignedLittleEndian Example");
Console.WriteLine($"lhs:\t{lhs.ToString("H")}");
Console.WriteLine($"rhs:\t{rhs.ToString("H")}");
Console.WriteLine($"result:\t{result.ToString("H")}");
Console.WriteLine(string.Empty);
Console.WriteLine($"lhs:\t{lhs.ToString("ILE")}");
Console.WriteLine($"rhs:\t{rhs.ToString("ILE")}");
Console.WriteLine($"result:\t{result.ToString("ILE")}");
Console.WriteLine(string.Empty);
}
SubtractUnsignedLittleEndian Example
lhs: DE 1E 7E D0
rhs: C0 DE
result: 1E 40 7D D0
lhs: 3497926366
rhs: 57024
result: 3497869342
Safe Summation
Safe summation allows for the the safe addition or subtraction of a long values delta from the given source byte array input. This is useful for iterating or decrementing byte arrays.
Both the ByteArrayUtils.TrySumBigEndian and ByteArrayUtils.TrySumLittleEndian methods return a bool stating if the operation was successful, and will out a non-null value of result on success.
Big Endian
public static bool ByteArrayUtils.TrySumBigEndian(byte[] source, long delta, out byte[] result)
public static void TrySumBigEndianExample()
{
// Setup
var bytes = new byte[] { 0xAD, 0xDE, 0xD0 };
const long delta = 42L;
// Act
var success = ByteArrayUtils.TrySumBigEndian(bytes, delta, out var result);
// Conclusion
Console.WriteLine("TrySumBigEndian Example");
Console.WriteLine($"bytes:\t{bytes.ToString("H")}");
Console.WriteLine($"delta:\t{delta}");
Console.WriteLine($"success:\t{success}");
Console.WriteLine($"result:\t{result.ToString("H")}");
Console.WriteLine(string.Empty);
Console.WriteLine($"bytes:\t{bytes.ToString("IBE")}");
Console.WriteLine($"result:\t{result.ToString("IBE")}");
Console.WriteLine(string.Empty);
}
TrySumBigEndian Example
bytes: AD DE D0
delta: 42
success: True
result: AD DE FA
bytes: 11394768
result: 11394810
Little Endian
public static bool ByteArrayUtils.TrySumLittleEndian(byte[] source, long delta, out byte[] result)
public static void TrySumLittleEndianExample()
{
// Setup
var bytes = new byte[] { 0xAD, 0xDE, 0xD0 };
const long delta = 42L;
// Act
var success = ByteArrayUtils.TrySumLittleEndian(bytes, delta, out var result);
// Conclusion
Console.WriteLine("TryLittleEndian Subtraction Example");
Console.WriteLine($"bytes:\t{bytes.ToString("H")}");
Console.WriteLine($"delta:\t{delta}");
Console.WriteLine($"success:\t{success}");
Console.WriteLine($"result:\t{result.ToString("H")}");
Console.WriteLine(string.Empty);
Console.WriteLine($"bytes:\t{bytes.ToString("ILE")}");
Console.WriteLine($"result:\t{result.ToString("ILE")}");
Console.WriteLine(string.Empty);
}
TrySumLittleEndian Example
bytes: AD DE D0
delta: -42
success: True
result: 83 DE D0
bytes: 13688493
result: 13688451
Safe Subtraction
Note
Seemingly conspicuously absent are the TrySubtractBigEndian and TrySubtractLittleEndian equivalents of the TrySumBigEndian and TrySumLittleEndian methods. In actuality the various TrySum methods allow for a negative delta and therefore are functionally equivalent for safe subtraction.
Comparison
It is often not enough to simply compare the lengths of two arbitrary byte arrays to determine the equality or the largest / smallest unsigned integer value encoded as bytes.
Both ByteArrayUtils.CompareUnsignedBigEndian and ByteArrayUtils.CompareUnsignedLittleEndian provide the ability to easily compare byte arrays as their unsigned integer values.
The result is similar to that of IComparer.Compare(left, right). The signed integer indicates the relative values of left and right:
If 0,
leftequalsrightIf less than 0,
leftis less than ‘right’If greater than 0,
rightis greater thanleft
Big Endian
public static int ByteArrayUtils.CompareUnsignedBigEndian(byte[] left, byte[] right)
public static void CompareUnsignedBigEndianExample()
{
// Setup
var lhs = new byte[] { 0xB1, 0x66, 0xE5, 0x70 };
var rhs = new byte[] { 0x5A, 0x11 };
// Act
var result = ByteArrayUtils.CompareUnsignedBigEndian(lhs, rhs);
// Conclusion
Console.WriteLine("CompareUnsignedBigEndian Example");
Console.WriteLine($"lhs:\t{lhs.ToString("H")}");
Console.WriteLine($"rhs:\t{rhs.ToString("H")}");
Console.WriteLine($"result:\t{result}");
Console.WriteLine(string.Empty);
Console.WriteLine($"lhs:\t{lhs.ToString("IBE")}");
Console.WriteLine($"rhs:\t{rhs.ToString("IBE")}");
Console.WriteLine($"result:\t{result}");
Console.WriteLine(string.Empty);
}
lhs: B1 66 E5 70
rhs: 5A 11
result: 1
lhs: 2976310640
rhs: 23057
result: 1
Little Endian
public static int ByteArrayUtils.CompareUnsignedLittleEndian(byte[] left, byte[] right)
public static void CompareUnsignedLittleEndianExample()
{
// Setup
var lhs = new byte[] { 0xB1, 0x66, 0xE5, 0x70 };
var rhs = new byte[] { 0x5A, 0x11 };
// Act
var result = ByteArrayUtils.CompareUnsignedLittleEndian(lhs, rhs);
// Conclusion
Console.WriteLine("CompareUnsignedLittleEndian Example");
Console.WriteLine($"lhs:\t{lhs.ToString("H")}");
Console.WriteLine($"rhs:\t{rhs.ToString("H")}");
Console.WriteLine($"result:\t{result}");
Console.WriteLine(string.Empty);
Console.WriteLine($"lhs:\t{lhs.ToString("ILE")}");
Console.WriteLine($"rhs:\t{rhs.ToString("ILE")}");
Console.WriteLine($"result:\t{result}");
Console.WriteLine(string.Empty);
}
CompareUnsignedLittleEndian Example
lhs: B1 66 E5 70
rhs: 5A 11
result: 1
lhs: 1894082225
rhs: 4442
result: 1