mirror of
https://github.com/aaru-dps/AaruBenchmark.git
synced 2025-12-16 19:24:36 +00:00
Add native CRC64.
This commit is contained in:
@@ -32,11 +32,12 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Aaru6.Checksums.CRC64;
|
|
||||||
using Aaru.CommonTypes.Interfaces;
|
using Aaru.CommonTypes.Interfaces;
|
||||||
using Aaru.Helpers;
|
using Aaru.Helpers;
|
||||||
|
using Aaru6.Checksums.CRC64;
|
||||||
|
|
||||||
namespace Aaru6.Checksums
|
namespace Aaru6.Checksums
|
||||||
{
|
{
|
||||||
@@ -274,8 +275,10 @@ namespace Aaru6.Checksums
|
|||||||
};
|
};
|
||||||
|
|
||||||
readonly ulong _finalSeed;
|
readonly ulong _finalSeed;
|
||||||
|
readonly IntPtr _nativeContext;
|
||||||
readonly ulong[][] _table;
|
readonly ulong[][] _table;
|
||||||
readonly bool _useEcma;
|
readonly bool _useEcma;
|
||||||
|
readonly bool _useNative;
|
||||||
ulong _hashInt;
|
ulong _hashInt;
|
||||||
|
|
||||||
/// <summary>Initializes the CRC64 table and seed as CRC64-ECMA</summary>
|
/// <summary>Initializes the CRC64 table and seed as CRC64-ECMA</summary>
|
||||||
@@ -285,22 +288,36 @@ namespace Aaru6.Checksums
|
|||||||
_table = _ecmaCrc64Table;
|
_table = _ecmaCrc64Table;
|
||||||
_finalSeed = CRC64_ECMA_SEED;
|
_finalSeed = CRC64_ECMA_SEED;
|
||||||
_useEcma = true;
|
_useEcma = true;
|
||||||
|
|
||||||
|
if(!Native.IsSupported)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_nativeContext = crc64_init();
|
||||||
|
_useNative = _nativeContext != IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Initializes the CRC16 table with a custom polynomial and seed</summary>
|
/// <summary>Initializes the CRC16 table with a custom polynomial and seed</summary>
|
||||||
public Crc64Context(ulong polynomial, ulong seed)
|
public Crc64Context(ulong polynomial, ulong seed)
|
||||||
{
|
{
|
||||||
_hashInt = seed;
|
_hashInt = seed;
|
||||||
_table = GenerateTable(polynomial);
|
|
||||||
_finalSeed = seed;
|
_finalSeed = seed;
|
||||||
_useEcma = polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED;
|
_useEcma = polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED;
|
||||||
|
|
||||||
|
if(Native.IsSupported && _useEcma)
|
||||||
|
{
|
||||||
|
_nativeContext = crc64_init();
|
||||||
|
_useNative = _nativeContext != IntPtr.Zero;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_table = GenerateTable(polynomial);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
/// <summary>Updates the hash with data.</summary>
|
/// <summary>Updates the hash with data.</summary>
|
||||||
/// <param name="data">Data buffer.</param>
|
/// <param name="data">Data buffer.</param>
|
||||||
/// <param name="len">Length of buffer to hash.</param>
|
/// <param name="len">Length of buffer to hash.</param>
|
||||||
public void Update(byte[] data, uint len) => Step(ref _hashInt, _table, data, len, _useEcma);
|
public void Update(byte[] data, uint len) =>
|
||||||
|
Step(ref _hashInt, _table, data, len, _useEcma, _useNative, _nativeContext);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
/// <summary>Updates the hash with data.</summary>
|
/// <summary>Updates the hash with data.</summary>
|
||||||
@@ -309,20 +326,52 @@ namespace Aaru6.Checksums
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
/// <summary>Returns a byte array of the hash value.</summary>
|
/// <summary>Returns a byte array of the hash value.</summary>
|
||||||
public byte[] Final() => BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed);
|
public byte[] Final()
|
||||||
|
{
|
||||||
|
ulong crc = _hashInt ^ _finalSeed;
|
||||||
|
|
||||||
|
if(!_useNative ||
|
||||||
|
!_useEcma)
|
||||||
|
return BigEndianBitConverter.GetBytes(crc);
|
||||||
|
|
||||||
|
crc64_final(_nativeContext, ref crc);
|
||||||
|
crc64_free(_nativeContext);
|
||||||
|
|
||||||
|
return BigEndianBitConverter.GetBytes(crc);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||||
public string End()
|
public string End()
|
||||||
{
|
{
|
||||||
|
ulong crc = _hashInt ^ _finalSeed;
|
||||||
|
|
||||||
var crc64Output = new StringBuilder();
|
var crc64Output = new StringBuilder();
|
||||||
|
|
||||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed).Length; i++)
|
if(_useNative && _useEcma)
|
||||||
crc64Output.Append(BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed)[i].ToString("x2"));
|
{
|
||||||
|
crc64_final(_nativeContext, ref crc);
|
||||||
|
crc64_free(_nativeContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < BigEndianBitConverter.GetBytes(crc).Length; i++)
|
||||||
|
crc64Output.Append(BigEndianBitConverter.GetBytes(crc)[i].ToString("x2"));
|
||||||
|
|
||||||
return crc64Output.ToString();
|
return crc64Output.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||||
|
static extern IntPtr crc64_init();
|
||||||
|
|
||||||
|
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||||
|
static extern int crc64_update(IntPtr ctx, byte[] data, uint len);
|
||||||
|
|
||||||
|
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||||
|
static extern int crc64_final(IntPtr ctx, ref ulong crc);
|
||||||
|
|
||||||
|
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||||
|
static extern void crc64_free(IntPtr ctx);
|
||||||
|
|
||||||
static ulong[][] GenerateTable(ulong polynomial)
|
static ulong[][] GenerateTable(ulong polynomial)
|
||||||
{
|
{
|
||||||
ulong[][] table = new ulong[8][];
|
ulong[][] table = new ulong[8][];
|
||||||
@@ -350,8 +399,16 @@ namespace Aaru6.Checksums
|
|||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Step(ref ulong previousCrc, ulong[][] table, byte[] data, uint len, bool useEcma)
|
static void Step(ref ulong previousCrc, ulong[][] table, byte[] data, uint len, bool useEcma, bool useNative,
|
||||||
|
IntPtr nativeContext)
|
||||||
{
|
{
|
||||||
|
if(useNative && useEcma)
|
||||||
|
{
|
||||||
|
crc64_update(nativeContext, data, len);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int dataOff = 0;
|
int dataOff = 0;
|
||||||
|
|
||||||
if(useEcma &&
|
if(useEcma &&
|
||||||
@@ -424,6 +481,16 @@ namespace Aaru6.Checksums
|
|||||||
/// <param name="seed">CRC seed</param>
|
/// <param name="seed">CRC seed</param>
|
||||||
public static string File(string filename, out byte[] hash, ulong polynomial, ulong seed)
|
public static string File(string filename, out byte[] hash, ulong polynomial, ulong seed)
|
||||||
{
|
{
|
||||||
|
bool useEcma = polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED;
|
||||||
|
bool useNative = Native.IsSupported;
|
||||||
|
IntPtr nativeContext = IntPtr.Zero;
|
||||||
|
|
||||||
|
if(useNative && useEcma)
|
||||||
|
{
|
||||||
|
nativeContext = crc64_init();
|
||||||
|
useNative = nativeContext != IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
var fileStream = new FileStream(filename, FileMode.Open);
|
var fileStream = new FileStream(filename, FileMode.Open);
|
||||||
|
|
||||||
ulong localHashInt = seed;
|
ulong localHashInt = seed;
|
||||||
@@ -435,13 +502,19 @@ namespace Aaru6.Checksums
|
|||||||
|
|
||||||
while(read > 0)
|
while(read > 0)
|
||||||
{
|
{
|
||||||
Step(ref localHashInt, localTable, buffer, (uint)read,
|
Step(ref localHashInt, localTable, buffer, (uint)read, useEcma, useNative, nativeContext);
|
||||||
polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED);
|
|
||||||
|
|
||||||
read = fileStream.Read(buffer, 0, 65536);
|
read = fileStream.Read(buffer, 0, 65536);
|
||||||
}
|
}
|
||||||
|
|
||||||
localHashInt ^= seed;
|
localHashInt ^= seed;
|
||||||
|
|
||||||
|
if(useNative && useEcma)
|
||||||
|
{
|
||||||
|
crc64_final(nativeContext, ref localHashInt);
|
||||||
|
crc64_free(nativeContext);
|
||||||
|
}
|
||||||
|
|
||||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||||
|
|
||||||
var crc64Output = new StringBuilder();
|
var crc64Output = new StringBuilder();
|
||||||
@@ -469,13 +542,30 @@ namespace Aaru6.Checksums
|
|||||||
/// <param name="seed">CRC seed</param>
|
/// <param name="seed">CRC seed</param>
|
||||||
public static string Data(byte[] data, uint len, out byte[] hash, ulong polynomial, ulong seed)
|
public static string Data(byte[] data, uint len, out byte[] hash, ulong polynomial, ulong seed)
|
||||||
{
|
{
|
||||||
|
bool useEcma = polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED;
|
||||||
|
bool useNative = Native.IsSupported;
|
||||||
|
IntPtr nativeContext = IntPtr.Zero;
|
||||||
|
|
||||||
|
if(useNative && useEcma)
|
||||||
|
{
|
||||||
|
nativeContext = crc64_init();
|
||||||
|
useNative = nativeContext != IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
ulong localHashInt = seed;
|
ulong localHashInt = seed;
|
||||||
|
|
||||||
ulong[][] localTable = GenerateTable(polynomial);
|
ulong[][] localTable = GenerateTable(polynomial);
|
||||||
|
|
||||||
Step(ref localHashInt, localTable, data, len, polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED);
|
Step(ref localHashInt, localTable, data, len, useEcma, useNative, nativeContext);
|
||||||
|
|
||||||
localHashInt ^= seed;
|
localHashInt ^= seed;
|
||||||
|
|
||||||
|
if(useNative && useEcma)
|
||||||
|
{
|
||||||
|
crc64_final(nativeContext, ref localHashInt);
|
||||||
|
crc64_free(nativeContext);
|
||||||
|
}
|
||||||
|
|
||||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||||
|
|
||||||
var crc64Output = new StringBuilder();
|
var crc64Output = new StringBuilder();
|
||||||
|
|||||||
@@ -205,6 +205,8 @@ namespace AaruBenchmark.Checksums
|
|||||||
|
|
||||||
public static void Crc64()
|
public static void Crc64()
|
||||||
{
|
{
|
||||||
|
Native.ForceManaged = true;
|
||||||
|
|
||||||
byte[] data = new byte[1048576];
|
byte[] data = new byte[1048576];
|
||||||
|
|
||||||
var fs = new FileStream(Path.Combine(Program.Folder, "random"), FileMode.Open, FileAccess.Read);
|
var fs = new FileStream(Path.Combine(Program.Folder, "random"), FileMode.Open, FileAccess.Read);
|
||||||
|
|||||||
@@ -100,18 +100,6 @@ namespace AaruBenchmark.Checksums
|
|||||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||||
static extern void fletcher32_free(IntPtr ctx);
|
static extern void fletcher32_free(IntPtr ctx);
|
||||||
|
|
||||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
|
||||||
static extern IntPtr crc64_init();
|
|
||||||
|
|
||||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
|
||||||
static extern int crc64_update(IntPtr ctx, byte[] data, uint len);
|
|
||||||
|
|
||||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
|
||||||
static extern int crc64_final(IntPtr ctx, ref ulong crc);
|
|
||||||
|
|
||||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
|
||||||
static extern void crc64_free(IntPtr ctx);
|
|
||||||
|
|
||||||
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
[DllImport("libAaru.Checksums.Native", SetLastError = true)]
|
||||||
static extern IntPtr spamsum_init();
|
static extern IntPtr spamsum_init();
|
||||||
|
|
||||||
@@ -289,40 +277,23 @@ namespace AaruBenchmark.Checksums
|
|||||||
|
|
||||||
public static void Crc64()
|
public static void Crc64()
|
||||||
{
|
{
|
||||||
|
Native.ForceManaged = false;
|
||||||
|
|
||||||
byte[] data = new byte[1048576];
|
byte[] data = new byte[1048576];
|
||||||
ulong crc64 = 0;
|
|
||||||
byte[] hash;
|
|
||||||
|
|
||||||
var fs = new FileStream(Path.Combine(Program.Folder, "random"), FileMode.Open, FileAccess.Read);
|
var fs = new FileStream(Path.Combine(Program.Folder, "random"), FileMode.Open, FileAccess.Read);
|
||||||
|
|
||||||
fs.Read(data, 0, 1048576);
|
fs.Read(data, 0, 1048576);
|
||||||
fs.Close();
|
fs.Close();
|
||||||
fs.Dispose();
|
fs.Dispose();
|
||||||
|
IChecksum ctx = new Crc64Context();
|
||||||
|
ctx.Update(data);
|
||||||
|
byte[] result = ctx.Final();
|
||||||
|
|
||||||
IntPtr ctx = crc64_init();
|
if(result?.Length != _expectedRandomCrc64.Length)
|
||||||
|
throw new Exception("Invalid hash length");
|
||||||
|
|
||||||
if(ctx == IntPtr.Zero)
|
if(result.Where((t, i) => t != _expectedRandomCrc64[i]).Any())
|
||||||
throw new Exception("Could not initialize digest");
|
|
||||||
|
|
||||||
int ret = crc64_update(ctx, data, (uint)data.Length);
|
|
||||||
|
|
||||||
if(ret != 0)
|
|
||||||
throw new Exception("Could not digest block");
|
|
||||||
|
|
||||||
ret = crc64_final(ctx, ref crc64);
|
|
||||||
|
|
||||||
if(ret != 0)
|
|
||||||
throw new Exception("Could not finalize hash");
|
|
||||||
|
|
||||||
crc64_free(ctx);
|
|
||||||
|
|
||||||
crc64 = ((crc64 & 0x00000000FFFFFFFF) << 32) | ((crc64 & 0xFFFFFFFF00000000) >> 32);
|
|
||||||
crc64 = ((crc64 & 0x0000FFFF0000FFFF) << 16) | ((crc64 & 0xFFFF0000FFFF0000) >> 16);
|
|
||||||
crc64 = ((crc64 & 0x00FF00FF00FF00FF) << 8) | ((crc64 & 0xFF00FF00FF00FF00) >> 8);
|
|
||||||
|
|
||||||
hash = BitConverter.GetBytes(crc64);
|
|
||||||
|
|
||||||
if(hash.Where((t, i) => t != _expectedRandomCrc64[i]).Any())
|
|
||||||
throw new Exception("Invalid hash value");
|
throw new Exception("Invalid hash value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user