diff --git a/SabreTools.Hashing/Checksum/BitOperations.cs b/SabreTools.Hashing/Checksum/BitOperations.cs
index 2405933..edb14b2 100644
--- a/SabreTools.Hashing/Checksum/BitOperations.cs
+++ b/SabreTools.Hashing/Checksum/BitOperations.cs
@@ -5,7 +5,11 @@ namespace SabreTools.Hashing.Checksum
///
/// Clamp a value to a certain bit width and convert to a byte array
///
+#if NET7_0_OR_GREATER
+ public static byte[] ClampValueToBytes(System.UInt128 value, int bitWidth)
+#else
public static byte[] ClampValueToBytes(ulong value, int bitWidth)
+#endif
{
value &= ulong.MaxValue >> (64 - bitWidth);
byte[] bytes = new byte[(bitWidth + 7) / 8];
diff --git a/SabreTools.Hashing/Checksum/ChecksumBase.cs b/SabreTools.Hashing/Checksum/ChecksumBase.cs
index 7c4b798..53fa1d8 100644
--- a/SabreTools.Hashing/Checksum/ChecksumBase.cs
+++ b/SabreTools.Hashing/Checksum/ChecksumBase.cs
@@ -40,11 +40,76 @@ namespace SabreTools.Hashing.Checksum
long l => BitConverter.GetBytes(l),
ulong l => BitConverter.GetBytes(l),
+#if NET7_0_OR_GREATER
+ Int128 i => GetBytes(i),
+ UInt128 i => GetBytes(i),
+#endif
+
_ => [],
};
Array.Reverse(hashArr);
return hashArr;
}
+
+#if NET7_0_OR_GREATER
+ ///
+ /// Convert an Int64 to a byte array
+ ///
+ /// Reads in little-endian format
+ private static byte[] GetBytes(Int128 value)
+ {
+ byte[] output =
+ [
+ (byte)(value & 0xFF),
+ (byte)((value >> 8) & 0xFF),
+ (byte)((value >> 16) & 0xFF),
+ (byte)((value >> 24) & 0xFF),
+ (byte)((value >> 32) & 0xFF),
+ (byte)((value >> 40) & 0xFF),
+ (byte)((value >> 48) & 0xFF),
+ (byte)((value >> 56) & 0xFF),
+ (byte)((value >> 64) & 0xFF),
+ (byte)((value >> 72) & 0xFF),
+ (byte)((value >> 80) & 0xFF),
+ (byte)((value >> 88) & 0xFF),
+ (byte)((value >> 96) & 0xFF),
+ (byte)((value >> 104) & 0xFF),
+ (byte)((value >> 112) & 0xFF),
+ (byte)((value >> 120) & 0xFF),
+ ];
+
+ return output;
+ }
+
+ ///
+ /// Convert a UInt64 to a byte array
+ ///
+ /// Reads in little-endian format
+ private static byte[] GetBytes(UInt128 value)
+ {
+ byte[] output =
+ [
+ (byte)(value & 0xFF),
+ (byte)((value >> 8) & 0xFF),
+ (byte)((value >> 16) & 0xFF),
+ (byte)((value >> 24) & 0xFF),
+ (byte)((value >> 32) & 0xFF),
+ (byte)((value >> 40) & 0xFF),
+ (byte)((value >> 48) & 0xFF),
+ (byte)((value >> 56) & 0xFF),
+ (byte)((value >> 64) & 0xFF),
+ (byte)((value >> 72) & 0xFF),
+ (byte)((value >> 80) & 0xFF),
+ (byte)((value >> 88) & 0xFF),
+ (byte)((value >> 96) & 0xFF),
+ (byte)((value >> 104) & 0xFF),
+ (byte)((value >> 112) & 0xFF),
+ (byte)((value >> 120) & 0xFF),
+ ];
+
+ return output;
+ }
+#endif
}
}
diff --git a/SabreTools.Hashing/Checksum/Crc.cs b/SabreTools.Hashing/Checksum/Crc.cs
index 560f138..1f96019 100644
--- a/SabreTools.Hashing/Checksum/Crc.cs
+++ b/SabreTools.Hashing/Checksum/Crc.cs
@@ -3,7 +3,11 @@ using static SabreTools.Hashing.HashOperations;
namespace SabreTools.Hashing.Checksum
{
+#if NET7_0_OR_GREATER
+ public class Crc : ChecksumBase
+#else
public class Crc : ChecksumBase
+#endif
{
///
public override int HashSize => Def.Width;
@@ -50,7 +54,11 @@ namespace SabreTools.Hashing.Checksum
protected override byte[] HashFinal()
{
// Create a copy of the hash
+#if NET7_0_OR_GREATER
+ UInt128 localHash = _hash;
+#else
ulong localHash = _hash;
+#endif
// Handle mutual reflection
if (Def.ReflectIn ^ Def.ReflectOut)
diff --git a/SabreTools.Hashing/Checksum/CrcDefinition.cs b/SabreTools.Hashing/Checksum/CrcDefinition.cs
index 2f4b246..7d7518f 100644
--- a/SabreTools.Hashing/Checksum/CrcDefinition.cs
+++ b/SabreTools.Hashing/Checksum/CrcDefinition.cs
@@ -21,7 +21,11 @@ namespace SabreTools.Hashing.Checksum
/// corresponds to the inward end of the shift register, and is always
/// set. The highest-order term is omitted.
///
+#if NET7_0_OR_GREATER
+ public System.UInt128 Poly { get; set; }
+#else
public ulong Poly { get; set; }
+#endif
///
/// The settings of the bit cells at the start of each calculation,
@@ -29,7 +33,11 @@ namespace SabreTools.Hashing.Checksum
/// hexadecimal, direct notation found in MSB-first code. The least
/// significant bit corresponds to the inward end of the shift register.
///
+#if NET7_0_OR_GREATER
+ public System.UInt128 Init { get; set; }
+#else
public ulong Init { get; set; }
+#endif
///
/// If equal to false, specifies that the characters of the message
@@ -60,6 +68,10 @@ namespace SabreTools.Hashing.Checksum
/// is written in hexadecimal notation, having the same endianness as
/// the CRC such that its true image appears in the characters of the CRC.
///
+#if NET7_0_OR_GREATER
+ public System.UInt128 XorOut { get; set; }
+#else
public ulong XorOut { get; set; }
+#endif
}
}
diff --git a/SabreTools.Hashing/Checksum/CrcTable.cs b/SabreTools.Hashing/Checksum/CrcTable.cs
index 2a1bd2a..b911765 100644
--- a/SabreTools.Hashing/Checksum/CrcTable.cs
+++ b/SabreTools.Hashing/Checksum/CrcTable.cs
@@ -23,12 +23,20 @@ namespace SabreTools.Hashing.Checksum
///
/// Bit mask based on the CRC width
///
+#if NET7_0_OR_GREATER
+ private UInt128 BitMask => 1UL << (_definition.Width - 1);
+#else
private ulong BitMask => 1UL << (_definition.Width - 1);
+#endif
///
/// Mapping table
///
+#if NET7_0_OR_GREATER
+ private readonly UInt128[,] _table;
+#else
private readonly ulong[,] _table;
+#endif
///
/// Definition used to build the table
@@ -44,13 +52,21 @@ namespace SabreTools.Hashing.Checksum
{
// Initialize the internal
_definition = def;
+#if NET7_0_OR_GREATER
+ _table = new UInt128[SliceCount, 1 << BitsPerStep];
+#else
_table = new ulong[SliceCount, 1 << BitsPerStep];
+#endif
// Build the standard table
for (uint i = 0; i < (1 << BitsPerStep); i++)
{
// Get the starting value for this index
+#if NET7_0_OR_GREATER
+ UInt128 point = i;
+#else
ulong point = i;
+#endif
if (!Bitwise && def.ReflectIn)
point = ReverseBits(point, BitsPerStep);
@@ -87,7 +103,11 @@ namespace SabreTools.Hashing.Checksum
// Build each slice from the previous
for (int j = 0; j < 1 << BitsPerStep; j++)
{
+#if NET7_0_OR_GREATER
+ UInt128 last = _table[i - 1, j];
+#else
ulong last = _table[i - 1, j];
+#endif
if (_definition.ReflectIn)
_table[i, j] = (last >> BitsPerStep) ^ _table[0, (byte)last];
else
@@ -108,7 +128,11 @@ namespace SabreTools.Hashing.Checksum
/// or when + is greater
/// than the data length.
///
+#if NET7_0_OR_GREATER
+ public void TransformBlock(ref UInt128 hash, byte[] data, int offset, int length)
+#else
public void TransformBlock(ref ulong hash, byte[] data, int offset, int length)
+#endif
{
// Empty data just returns
if (data.Length == 0)
@@ -137,7 +161,11 @@ namespace SabreTools.Hashing.Checksum
/// Current hash value, updated on run
/// Byte array representing the data
/// Offset in the data to process
+#if NET7_0_OR_GREATER
+ private void PerformChecksumStep(ref UInt128 hash, byte[] data, int offset)
+#else
private void PerformChecksumStep(ref ulong hash, byte[] data, int offset)
+#endif
{
// Per-bit processing
if (Bitwise)
@@ -164,7 +192,11 @@ namespace SabreTools.Hashing.Checksum
///
/// Perform an optimized transform step
///
+#if NET7_0_OR_GREATER
+ private bool TransformBlockFast(ref UInt128 hash, byte[] data, int offset, int length)
+#else
private bool TransformBlockFast(ref ulong hash, byte[] data, int offset, int length)
+#endif
{
// Bitwise transformations are not optimized
if (Bitwise)
@@ -196,10 +228,18 @@ namespace SabreTools.Hashing.Checksum
/// Optimized transformation for CRC with reflection
///
/// Reads 4 bytes at a time
+#if NET7_0_OR_GREATER
+ private void TransformBlockFast4Reflect(ref UInt128 hash, byte[] data, int offset, int length)
+#else
private void TransformBlockFast4Reflect(ref ulong hash, byte[] data, int offset, int length)
+#endif
{
// Process on a copy of the hash
+#if NET7_0_OR_GREATER
+ UInt128 local = hash;
+#else
ulong local = hash;
+#endif
// Process aligned data
if (length > 4)
@@ -209,11 +249,20 @@ namespace SabreTools.Hashing.Checksum
while (offset < end)
{
+#if NET7_0_OR_GREATER
+ UInt128 low = local ^ (uint)(
+ data[offset + 0]
+ + (data[offset + 1] << 8)
+ + (data[offset + 2] << 16)
+ + (data[offset + 3] << 24));
+#else
ulong low = local ^ (uint)(
data[offset + 0]
+ (data[offset + 1] << 8)
+ (data[offset + 2] << 16)
+ (data[offset + 3] << 24));
+#endif
+
offset += 4;
local = _table[3, (byte)low]
@@ -238,10 +287,18 @@ namespace SabreTools.Hashing.Checksum
/// Optimized transformation for CRC with reflection
///
/// Reads 8 bytes at a time
+#if NET7_0_OR_GREATER
+ private void TransformBlockFast8Reflect(ref UInt128 hash, byte[] data, int offset, int length)
+#else
private void TransformBlockFast8Reflect(ref ulong hash, byte[] data, int offset, int length)
+#endif
{
// Process on a copy of the hash
+#if NET7_0_OR_GREATER
+ UInt128 local = hash;
+#else
ulong local = hash;
+#endif
// Process aligned data
if (length > 8)
@@ -251,6 +308,18 @@ namespace SabreTools.Hashing.Checksum
while (offset < end)
{
+#if NET7_0_OR_GREATER
+ UInt128 low = local ^ (uint)(
+ data[offset + 0]
+ + (data[offset + 1] << 8)
+ + (data[offset + 2] << 16)
+ + (data[offset + 3] << 24));
+ UInt128 high = (uint)(
+ data[offset + 4]
+ + (data[offset + 5] << 8)
+ + (data[offset + 6] << 16)
+ + (data[offset + 7] << 24));
+#else
ulong low = local ^ (uint)(
data[offset + 0]
+ (data[offset + 1] << 8)
@@ -261,6 +330,7 @@ namespace SabreTools.Hashing.Checksum
+ (data[offset + 5] << 8)
+ (data[offset + 6] << 16)
+ (data[offset + 7] << 24));
+#endif
offset += 8;
local = _table[7, (byte)low]
@@ -289,10 +359,18 @@ namespace SabreTools.Hashing.Checksum
/// Optimized transformation for 32-bit CRC with no reflection
///
/// Reads 8 bytes at a time
+#if NET7_0_OR_GREATER
+ private void TransformBlockFast8NoReflect(ref UInt128 hash, byte[] data, int offset, int length)
+#else
private void TransformBlockFast8NoReflect(ref ulong hash, byte[] data, int offset, int length)
+#endif
{
// Process on a copy of the hash
+#if NET7_0_OR_GREATER
+ UInt128 local = hash;
+#else
ulong local = hash;
+#endif
// Process aligned data
if (length > 8)
@@ -302,6 +380,18 @@ namespace SabreTools.Hashing.Checksum
while (offset < end)
{
+#if NET7_0_OR_GREATER
+ UInt128 low = local ^ (uint)(
+ data[offset + 3]
+ + (data[offset + 2] << 8)
+ + (data[offset + 1] << 16)
+ + (data[offset + 0] << 24));
+ UInt128 high = (uint)(
+ data[offset + 7]
+ + (data[offset + 6] << 8)
+ + (data[offset + 5] << 16)
+ + (data[offset + 4] << 24));
+#else
ulong low = local ^ (uint)(
data[offset + 3]
+ (data[offset + 2] << 8)
@@ -312,6 +402,7 @@ namespace SabreTools.Hashing.Checksum
+ (data[offset + 6] << 8)
+ (data[offset + 5] << 16)
+ (data[offset + 4] << 24));
+#endif
offset += 8;
local = _table[4, (byte)low]
diff --git a/SabreTools.Hashing/HashOperations.cs b/SabreTools.Hashing/HashOperations.cs
index 20b52c3..8cdf0dc 100644
--- a/SabreTools.Hashing/HashOperations.cs
+++ b/SabreTools.Hashing/HashOperations.cs
@@ -117,9 +117,17 @@ namespace SabreTools.Hashing
///
/// Reverse the endianness of a value
///
+#if NET7_0_OR_GREATER
+ public static UInt128 ReverseBits(UInt128 value, int bitWidth)
+#else
public static ulong ReverseBits(ulong value, int bitWidth)
+#endif
{
+#if NET7_0_OR_GREATER
+ UInt128 reverse = 0;
+#else
ulong reverse = 0;
+#endif
for (int i = 0; i < bitWidth; i++)
{
reverse <<= 1;