mirror of
https://github.com/aaru-dps/AaruBenchmark.git
synced 2025-12-16 19:24:36 +00:00
Copy algorithms from current Aaru 6 dev tree.
This commit is contained in:
@@ -55,8 +55,8 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="CRC16CCITTContext.cs"/>
|
||||
<Compile Include="CRC16IBMContext.cs"/>
|
||||
<Compile Include="CRC32CLMUL.cs"/>
|
||||
<Compile Include="CRC64CLMUL.cs"/>
|
||||
<Compile Include="CRC32\clmul.cs"/>
|
||||
<Compile Include="CRC64\clmul.cs"/>
|
||||
<Compile Include="SpamSumContext.cs"/>
|
||||
<Compile Include="Adler32Context.cs"/>
|
||||
<Compile Include="CRC16Context.cs"/>
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Aaru6.Checksums
|
||||
/// <summary>Implements the Adler-32 algorithm</summary>
|
||||
public sealed class Adler32Context : IChecksum
|
||||
{
|
||||
const uint ADLER_MODULE = 65521;
|
||||
const ushort ADLER_MODULE = 65521;
|
||||
const uint NMAX = 5552;
|
||||
ushort _sum1, _sum2;
|
||||
|
||||
@@ -56,10 +56,39 @@ namespace Aaru6.Checksums
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
public void Update(byte[] data, uint len) => Step(ref _sum1, ref _sum2, data, len);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
uint sum1 = _sum1;
|
||||
uint sum2 = _sum2;
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
|
||||
return BigEndianBitConverter.GetBytes(finalSum);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
var adlerOutput = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
|
||||
adlerOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
|
||||
|
||||
return adlerOutput.ToString();
|
||||
}
|
||||
|
||||
static void Step(ref ushort preSum1, ref ushort preSum2, byte[] data, uint len)
|
||||
{
|
||||
uint sum1 = preSum1;
|
||||
uint sum2 = preSum2;
|
||||
uint n;
|
||||
int dataOff = 0;
|
||||
|
||||
@@ -76,8 +105,8 @@ namespace Aaru6.Checksums
|
||||
if(sum2 >= ADLER_MODULE)
|
||||
sum2 -= ADLER_MODULE;
|
||||
|
||||
_sum1 = (ushort)(sum1 & 0xFFFF);
|
||||
_sum2 = (ushort)(sum2 & 0xFFFF);
|
||||
preSum1 = (ushort)(sum1 & 0xFFFF);
|
||||
preSum2 = (ushort)(sum2 & 0xFFFF);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -95,8 +124,8 @@ namespace Aaru6.Checksums
|
||||
sum1 -= ADLER_MODULE;
|
||||
|
||||
sum2 %= ADLER_MODULE; /* only added so many ADLER_MODULE's */
|
||||
_sum1 = (ushort)(sum1 & 0xFFFF);
|
||||
_sum2 = (ushort)(sum2 & 0xFFFF);
|
||||
preSum1 = (ushort)(sum1 & 0xFFFF);
|
||||
preSum2 = (ushort)(sum2 & 0xFFFF);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -203,35 +232,8 @@ namespace Aaru6.Checksums
|
||||
sum2 %= ADLER_MODULE;
|
||||
}
|
||||
|
||||
_sum1 = (ushort)(sum1 & 0xFFFF);
|
||||
_sum2 = (ushort)(sum2 & 0xFFFF);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
|
||||
return BigEndianBitConverter.GetBytes(finalSum);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
var adlerOutput = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
|
||||
adlerOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
|
||||
|
||||
return adlerOutput.ToString();
|
||||
preSum1 = (ushort)(sum1 & 0xFFFF);
|
||||
preSum2 = (ushort)(sum2 & 0xFFFF);
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
@@ -253,10 +255,13 @@ namespace Aaru6.Checksums
|
||||
ushort localSum1 = 1;
|
||||
ushort localSum2 = 0;
|
||||
|
||||
for(int i = 0; i < fileStream.Length; i++)
|
||||
byte[] buffer = new byte[65536];
|
||||
int read = fileStream.Read(buffer, 0, 65536);
|
||||
|
||||
while(read > 0)
|
||||
{
|
||||
localSum1 = (ushort)((localSum1 + fileStream.ReadByte()) % ADLER_MODULE);
|
||||
localSum2 = (ushort)((localSum2 + localSum1) % ADLER_MODULE);
|
||||
Step(ref localSum1, ref localSum2, buffer, (uint)read);
|
||||
read = fileStream.Read(buffer, 0, 65536);
|
||||
}
|
||||
|
||||
uint finalSum = (uint)((localSum2 << 16) | localSum1);
|
||||
@@ -282,11 +287,7 @@ namespace Aaru6.Checksums
|
||||
ushort localSum1 = 1;
|
||||
ushort localSum2 = 0;
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
localSum1 = (ushort)((localSum1 + data[i]) % ADLER_MODULE);
|
||||
localSum2 = (ushort)((localSum2 + localSum1) % ADLER_MODULE);
|
||||
}
|
||||
Step(ref localSum1, ref localSum2, data, len);
|
||||
|
||||
uint finalSum = (uint)((localSum2 << 16) | localSum1);
|
||||
|
||||
|
||||
@@ -30,22 +30,17 @@
|
||||
// Copyright © 2011-2021 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Helpers;
|
||||
|
||||
namespace Aaru6.Checksums
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>Implements the CRC16 algorithm with CCITT polynomial and seed</summary>
|
||||
public sealed class CRC16CCITTContext : IChecksum
|
||||
public sealed class CRC16CCITTContext : Crc16Context
|
||||
{
|
||||
/// <summary>CCITT CRC16 polynomial</summary>
|
||||
public const ushort CRC16_CCITT_POLY = 0x8408;
|
||||
/// <summary>CCITT CRC16 seed</summary>
|
||||
public const ushort CRC16_CCITT_SEED = 0x0000;
|
||||
|
||||
static readonly ushort[][] crc16_ccitt_table =
|
||||
static readonly ushort[][] _ccittCrc16Table =
|
||||
{
|
||||
new ushort[]
|
||||
{
|
||||
@@ -232,61 +227,10 @@ namespace Aaru6.Checksums
|
||||
0x8A95, 0x5357, 0x1484, 0xDCF1, 0x9B22, 0x5C3A, 0x1BE9, 0xD39C, 0x944F
|
||||
}
|
||||
};
|
||||
ushort _crc;
|
||||
|
||||
/// <summary>Initializes an instance of the CRC16 with IBM polynomial and seed.</summary>
|
||||
/// <summary>Initializes an instance of the CRC16 with CCITT polynomial and seed.</summary>
|
||||
/// <inheritdoc />
|
||||
public CRC16CCITTContext() => _crc = 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
// Unroll according to Intel slicing by uint8_t
|
||||
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
|
||||
// http://sourceforge.net/projects/slicing-by-8/
|
||||
|
||||
ushort crc;
|
||||
int current_pos = 0;
|
||||
const int unroll = 4;
|
||||
const int bytes_at_once = 8 * unroll;
|
||||
|
||||
crc = _crc;
|
||||
|
||||
while(len >= bytes_at_once)
|
||||
{
|
||||
int unrolling;
|
||||
|
||||
for(unrolling = 0; unrolling < unroll; unrolling++)
|
||||
{
|
||||
crc = (ushort)(crc16_ccitt_table[7][data[current_pos + 0] ^ (crc >> 8)] ^
|
||||
crc16_ccitt_table[6][data[current_pos + 1] ^ (crc & 0xFF)] ^
|
||||
crc16_ccitt_table[5][data[current_pos + 2]] ^
|
||||
crc16_ccitt_table[4][data[current_pos + 3]] ^
|
||||
crc16_ccitt_table[3][data[current_pos + 4]] ^
|
||||
crc16_ccitt_table[2][data[current_pos + 5]] ^
|
||||
crc16_ccitt_table[1][data[current_pos + 6]] ^
|
||||
crc16_ccitt_table[0][data[current_pos + 7]]);
|
||||
|
||||
current_pos += 8;
|
||||
}
|
||||
|
||||
len -= bytes_at_once;
|
||||
}
|
||||
|
||||
while(len-- != 0)
|
||||
crc = (ushort)((crc << 8) ^ crc16_ccitt_table[0][(crc >> 8) ^ data[current_pos++]]);
|
||||
|
||||
_crc = crc;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte[] Final() => BigEndianBitConverter.GetBytes(_crc);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string End() => throw new NotImplementedException();
|
||||
public CRC16CCITTContext() : base(CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true) {}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
@@ -300,21 +244,24 @@ namespace Aaru6.Checksums
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash) => throw new NotImplementedException();
|
||||
public static string File(string filename, out byte[] hash) =>
|
||||
File(filename, out hash, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true);
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash) => throw new NotImplementedException();
|
||||
public static string Data(byte[] data, uint len, out byte[] hash) =>
|
||||
Data(data, len, out hash, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true);
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
|
||||
/// <summary>Calculates the IBM CRC16 of the specified buffer with the specified parameters</summary>
|
||||
/// <summary>Calculates the CCITT CRC16 of the specified buffer with the specified parameters</summary>
|
||||
/// <param name="buffer">Buffer</param>
|
||||
public static ushort Calculate(byte[] buffer) => throw new NotImplementedException();
|
||||
public static ushort Calculate(byte[] buffer) =>
|
||||
Calculate(buffer, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true);
|
||||
}
|
||||
}
|
||||
@@ -30,13 +30,13 @@
|
||||
// Copyright © 2011-2021 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Helpers;
|
||||
|
||||
namespace Aaru.Checksums
|
||||
namespace Aaru6.Checksums
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>Implements a CRC16 algorithm</summary>
|
||||
@@ -44,11 +44,11 @@ namespace Aaru.Checksums
|
||||
{
|
||||
readonly ushort _finalSeed;
|
||||
readonly bool _inverse;
|
||||
readonly ushort[] _table;
|
||||
readonly ushort[][] _table;
|
||||
ushort _hashInt;
|
||||
|
||||
/// <summary>Initializes the CRC16 table with a custom polynomial and seed</summary>
|
||||
public Crc16Context(ushort polynomial, ushort seed, ushort[] table, bool inverse)
|
||||
public Crc16Context(ushort polynomial, ushort seed, ushort[][] table, bool inverse)
|
||||
{
|
||||
_hashInt = seed;
|
||||
_finalSeed = seed;
|
||||
@@ -62,14 +62,11 @@ namespace Aaru.Checksums
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
if(_inverse)
|
||||
_hashInt = (ushort)((_hashInt << 8) ^ _table[data[i] ^ (_hashInt >> 8)]);
|
||||
StepInverse(ref _hashInt, _table, data, len);
|
||||
else
|
||||
_hashInt = (ushort)((_hashInt >> 8) ^ _table[data[i] ^ (_hashInt & 0xFF)]);
|
||||
}
|
||||
Step(ref _hashInt, _table, data, len);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -79,7 +76,8 @@ namespace Aaru.Checksums
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final() => BigEndianBitConverter.GetBytes((ushort)(_hashInt ^ _finalSeed));
|
||||
public byte[] Final() => !_inverse ? BigEndianBitConverter.GetBytes((ushort)(_hashInt ^ _finalSeed))
|
||||
: BigEndianBitConverter.GetBytes((ushort)~(_hashInt ^ _finalSeed));
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
@@ -100,9 +98,88 @@ namespace Aaru.Checksums
|
||||
return crc16Output.ToString();
|
||||
}
|
||||
|
||||
static ushort[] GenerateTable(ushort polynomial, bool inverseTable)
|
||||
static void Step(ref ushort previousCrc, ushort[][] table, byte[] data, uint len)
|
||||
{
|
||||
ushort[] table = new ushort[256];
|
||||
// Unroll according to Intel slicing by uint8_t
|
||||
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
|
||||
// http://sourceforge.net/projects/slicing-by-8/
|
||||
|
||||
ushort crc;
|
||||
int current_pos = 0;
|
||||
const int unroll = 4;
|
||||
const int bytes_at_once = 8 * unroll;
|
||||
|
||||
crc = previousCrc;
|
||||
|
||||
while(len >= bytes_at_once)
|
||||
{
|
||||
int unrolling;
|
||||
|
||||
for(unrolling = 0; unrolling < unroll; unrolling++)
|
||||
{
|
||||
// TODO: What trick is Microsoft doing here that's faster than arithmetic conversion
|
||||
uint one = BitConverter.ToUInt32(data, current_pos) ^ crc;
|
||||
current_pos += 4;
|
||||
uint two = BitConverter.ToUInt32(data, current_pos);
|
||||
current_pos += 4;
|
||||
|
||||
crc = (ushort)(table[0][(two >> 24) & 0xFF] ^ table[1][(two >> 16) & 0xFF] ^
|
||||
table[2][(two >> 8) & 0xFF] ^ table[3][two & 0xFF] ^ table[4][(one >> 24) & 0xFF] ^
|
||||
table[5][(one >> 16) & 0xFF] ^ table[6][(one >> 8) & 0xFF] ^ table[7][one & 0xFF]);
|
||||
}
|
||||
|
||||
len -= bytes_at_once;
|
||||
}
|
||||
|
||||
while(len-- != 0)
|
||||
crc = (ushort)((crc >> 8) ^ table[0][(crc & 0xFF) ^ data[current_pos++]]);
|
||||
|
||||
previousCrc = crc;
|
||||
}
|
||||
|
||||
static void StepInverse(ref ushort previousCrc, ushort[][] table, byte[] data, uint len)
|
||||
{
|
||||
// Unroll according to Intel slicing by uint8_t
|
||||
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
|
||||
// http://sourceforge.net/projects/slicing-by-8/
|
||||
|
||||
ushort crc;
|
||||
int current_pos = 0;
|
||||
const int unroll = 4;
|
||||
const int bytes_at_once = 8 * unroll;
|
||||
|
||||
crc = previousCrc;
|
||||
|
||||
while(len >= bytes_at_once)
|
||||
{
|
||||
int unrolling;
|
||||
|
||||
for(unrolling = 0; unrolling < unroll; unrolling++)
|
||||
{
|
||||
crc = (ushort)(table[7][data[current_pos + 0] ^ (crc >> 8)] ^
|
||||
table[6][data[current_pos + 1] ^ (crc & 0xFF)] ^ table[5][data[current_pos + 2]] ^
|
||||
table[4][data[current_pos + 3]] ^ table[3][data[current_pos + 4]] ^
|
||||
table[2][data[current_pos + 5]] ^ table[1][data[current_pos + 6]] ^
|
||||
table[0][data[current_pos + 7]]);
|
||||
|
||||
current_pos += 8;
|
||||
}
|
||||
|
||||
len -= bytes_at_once;
|
||||
}
|
||||
|
||||
while(len-- != 0)
|
||||
crc = (ushort)((crc << 8) ^ table[0][(crc >> 8) ^ data[current_pos++]]);
|
||||
|
||||
previousCrc = crc;
|
||||
}
|
||||
|
||||
static ushort[][] GenerateTable(ushort polynomial, bool inverseTable)
|
||||
{
|
||||
ushort[][] table = new ushort[8][];
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
table[i] = new ushort[256];
|
||||
|
||||
if(!inverseTable)
|
||||
for(uint i = 0; i < 256; i++)
|
||||
@@ -115,7 +192,7 @@ namespace Aaru.Checksums
|
||||
else
|
||||
entry >>= 1;
|
||||
|
||||
table[i] = (ushort)entry;
|
||||
table[0][i] = (ushort)entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -130,11 +207,20 @@ namespace Aaru.Checksums
|
||||
else
|
||||
entry <<= 1;
|
||||
|
||||
table[i] = (ushort)entry;
|
||||
table[0][i] = (ushort)entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int slice = 1; slice < 8; slice++)
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
if(inverseTable)
|
||||
table[slice][i] = (ushort)((table[slice - 1][i] << 8) ^ table[0][table[slice - 1][i] >> 8]);
|
||||
else
|
||||
table[slice][i] = (ushort)((table[slice - 1][i] >> 8) ^ table[0][table[slice - 1][i] & 0xFF]);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
@@ -145,22 +231,27 @@ namespace Aaru.Checksums
|
||||
/// <param name="seed">CRC seed</param>
|
||||
/// <param name="table">CRC lookup table</param>
|
||||
/// <param name="inverse">Is CRC inverted?</param>
|
||||
public static string File(string filename, out byte[] hash, ushort polynomial, ushort seed, ushort[] table,
|
||||
public static string File(string filename, out byte[] hash, ushort polynomial, ushort seed, ushort[][] table,
|
||||
bool inverse)
|
||||
{
|
||||
var fileStream = new FileStream(filename, FileMode.Open);
|
||||
|
||||
ushort localHashInt = seed;
|
||||
|
||||
ushort[] localTable = table ?? GenerateTable(polynomial, inverse);
|
||||
ushort[][] localTable = table ?? GenerateTable(polynomial, inverse);
|
||||
|
||||
for(int i = 0; i < fileStream.Length; i++)
|
||||
byte[] buffer = new byte[65536];
|
||||
int read = fileStream.Read(buffer, 0, 65536);
|
||||
|
||||
while(read > 0)
|
||||
{
|
||||
if(inverse)
|
||||
localHashInt =
|
||||
(ushort)(localTable[(localHashInt >> 8) ^ fileStream.ReadByte()] ^ (localHashInt << 8));
|
||||
StepInverse(ref localHashInt, localTable, buffer, (uint)read);
|
||||
else
|
||||
localHashInt =
|
||||
(ushort)((localHashInt >> 8) ^ localTable[fileStream.ReadByte() ^ (localHashInt & 0xff)]);
|
||||
Step(ref localHashInt, localTable, buffer, (uint)read);
|
||||
|
||||
read = fileStream.Read(buffer, 0, 65536);
|
||||
}
|
||||
|
||||
localHashInt ^= seed;
|
||||
|
||||
@@ -188,17 +279,16 @@ namespace Aaru.Checksums
|
||||
/// <param name="table">CRC lookup table</param>
|
||||
/// <param name="inverse">Is CRC inverted?</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash, ushort polynomial, ushort seed,
|
||||
ushort[] table, bool inverse)
|
||||
ushort[][] table, bool inverse)
|
||||
{
|
||||
ushort localHashInt = seed;
|
||||
|
||||
ushort[] localTable = table ?? GenerateTable(polynomial, inverse);
|
||||
ushort[][] localTable = table ?? GenerateTable(polynomial, inverse);
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
if(inverse)
|
||||
localHashInt = (ushort)(localTable[(localHashInt >> 8) ^ data[i]] ^ (localHashInt << 8));
|
||||
StepInverse(ref localHashInt, localTable, data, len);
|
||||
else
|
||||
localHashInt = (ushort)((localHashInt >> 8) ^ localTable[data[i] ^ (localHashInt & 0xff)]);
|
||||
Step(ref localHashInt, localTable, data, len);
|
||||
|
||||
localHashInt ^= seed;
|
||||
|
||||
@@ -222,22 +312,23 @@ namespace Aaru.Checksums
|
||||
/// <param name="table">Pre-generated lookup table</param>
|
||||
/// <param name="inverse">Inverse CRC</param>
|
||||
/// <returns>CRC16</returns>
|
||||
public static ushort Calculate(byte[] buffer, ushort polynomial, ushort seed, ushort[] table, bool inverse)
|
||||
public static ushort Calculate(byte[] buffer, ushort polynomial, ushort seed, ushort[][] table, bool inverse)
|
||||
{
|
||||
ushort[] localTable = table ?? GenerateTable(polynomial, inverse);
|
||||
ushort localHashInt = seed;
|
||||
|
||||
ushort crc16 =
|
||||
buffer.Aggregate<byte, ushort>(0,
|
||||
(current, b) =>
|
||||
inverse ? (ushort)(localTable[(current >> 8) ^ b] ^ (current << 8))
|
||||
: (ushort)((current >> 8) ^ localTable[b ^ (current & 0xff)]));
|
||||
|
||||
crc16 ^= seed;
|
||||
ushort[][] localTable = table ?? GenerateTable(polynomial, inverse);
|
||||
|
||||
if(inverse)
|
||||
crc16 = (ushort)~crc16;
|
||||
StepInverse(ref localHashInt, localTable, buffer, (uint)buffer.Length);
|
||||
else
|
||||
Step(ref localHashInt, localTable, buffer, (uint)buffer.Length);
|
||||
|
||||
return crc16;
|
||||
localHashInt ^= seed;
|
||||
|
||||
if(inverse)
|
||||
localHashInt = (ushort)~localHashInt;
|
||||
|
||||
return localHashInt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,20 +30,16 @@
|
||||
// Copyright © 2011-2021 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Helpers;
|
||||
|
||||
namespace Aaru6.Checksums
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>Implements the CRC16 algorithm with IBM polynomial and seed</summary>
|
||||
public sealed class CRC16IBMContext : IChecksum
|
||||
public sealed class CRC16IBMContext : Crc16Context
|
||||
{
|
||||
const ushort CRC16_IBM_POLY = 0xA001;
|
||||
const ushort CRC16_IBM_SEED = 0x0000;
|
||||
|
||||
static readonly ushort[][] crc16_table =
|
||||
static readonly ushort[][] _ibmCrc16Table =
|
||||
{
|
||||
new ushort[]
|
||||
{
|
||||
@@ -230,60 +226,10 @@ namespace Aaru6.Checksums
|
||||
0xA24E, 0xE20E, 0x2ECF, 0x3B8F, 0xF74E, 0x110F, 0xDDCE, 0xC88E, 0x044F
|
||||
}
|
||||
};
|
||||
ushort _crc;
|
||||
|
||||
/// <summary>Initializes an instance of the CRC16 with IBM polynomial and seed.</summary>
|
||||
/// <inheritdoc />
|
||||
public CRC16IBMContext() => _crc = 0;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
// Unroll according to Intel slicing by uint8_t
|
||||
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
|
||||
// http://sourceforge.net/projects/slicing-by-8/
|
||||
|
||||
ushort crc;
|
||||
int current_pos = 0;
|
||||
const int unroll = 4;
|
||||
const int bytes_at_once = 8 * unroll;
|
||||
|
||||
crc = _crc;
|
||||
|
||||
while(len >= bytes_at_once)
|
||||
{
|
||||
int unrolling;
|
||||
|
||||
for(unrolling = 0; unrolling < unroll; unrolling++)
|
||||
{
|
||||
uint one = BitConverter.ToUInt32(data, current_pos) ^ crc;
|
||||
current_pos += 4;
|
||||
uint two = BitConverter.ToUInt32(data, current_pos);
|
||||
current_pos += 4;
|
||||
|
||||
crc = (ushort)(crc16_table[0][(two >> 24) & 0xFF] ^ crc16_table[1][(two >> 16) & 0xFF] ^
|
||||
crc16_table[2][(two >> 8) & 0xFF] ^ crc16_table[3][two & 0xFF] ^
|
||||
crc16_table[4][(one >> 24) & 0xFF] ^ crc16_table[5][(one >> 16) & 0xFF] ^
|
||||
crc16_table[6][(one >> 8) & 0xFF] ^ crc16_table[7][one & 0xFF]);
|
||||
}
|
||||
|
||||
len -= bytes_at_once;
|
||||
}
|
||||
|
||||
while(len-- != 0)
|
||||
crc = (ushort)((crc >> 8) ^ crc16_table[0][(crc & 0xFF) ^ data[current_pos++]]);
|
||||
|
||||
_crc = crc;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte[] Final() => BigEndianBitConverter.GetBytes(_crc);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string End() => throw new NotImplementedException();
|
||||
public CRC16IBMContext() : base(CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false) {}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
@@ -297,21 +243,19 @@ namespace Aaru6.Checksums
|
||||
/// <summary>Gets the hash of a file in hexadecimal and as a byte array.</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string File(string filename, out byte[] hash) => throw new NotImplementedException();
|
||||
public static string File(string filename, out byte[] hash) =>
|
||||
File(filename, out hash, CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false);
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of the data buffer to hash.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, uint len, out byte[] hash) => throw new NotImplementedException();
|
||||
public static string Data(byte[] data, uint len, out byte[] hash) =>
|
||||
Data(data, len, out hash, CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false);
|
||||
|
||||
/// <summary>Gets the hash of the specified data buffer.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="hash">Byte array of the hash value.</param>
|
||||
public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash);
|
||||
|
||||
/// <summary>Calculates the IBM CRC16 of the specified buffer with the specified parameters</summary>
|
||||
/// <param name="buffer">Buffer</param>
|
||||
public static ushort Calculate(byte[] buffer) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
541
Aaru6.Checksums/CRC32/clmul.cs
Normal file
541
Aaru6.Checksums/CRC32/clmul.cs
Normal file
@@ -0,0 +1,541 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : clmul.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
// Wajdi Feghali <wajdi.k.feghali@intel.com>
|
||||
// Jim Guilford <james.guilford@intel.com>
|
||||
// Vinodh Gopal <vinodh.gopal@intel.com>
|
||||
// Erdinc Ozturk <erdinc.ozturk@intel.com>
|
||||
// Jim Kukunas <james.t.kukunas@linux.intel.com>
|
||||
// Marian Beermann
|
||||
//
|
||||
// Component : Checksums.
|
||||
//
|
||||
// --[ Description ] ----------------------------------------------------------
|
||||
//
|
||||
// Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ
|
||||
// instruction.
|
||||
//
|
||||
// A white paper describing this algorithm can be found at:
|
||||
// http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
|
||||
//
|
||||
// --[ License ] --------------------------------------------------------------
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from
|
||||
// the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright © 2011-2021 Natalia Portillo
|
||||
// Copyright (c) 2016 Marian Beermann (add support for initial value, restructuring)
|
||||
// Copyright (C) 2013 Intel Corporation. All rights reserved.
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
namespace Aaru6.Checksums.CRC32
|
||||
{
|
||||
internal static class Clmul
|
||||
{
|
||||
static readonly uint[] _crcK =
|
||||
{
|
||||
0xccaa009e, 0x00000000, /* rk1 */ 0x751997d0, 0x00000001, /* rk2 */ 0xccaa009e, 0x00000000, /* rk5 */
|
||||
0x63cd6124, 0x00000001, /* rk6 */ 0xf7011640, 0x00000001, /* rk7 */ 0xdb710640, 0x00000001 /* rk8 */
|
||||
};
|
||||
|
||||
static readonly Vector128<uint>[] _pshufbShfTable =
|
||||
{
|
||||
Vector128.Create(0x84838281, 0x88878685, 0x8c8b8a89, 0x008f8e8d), /* shl 15 (16 - 1)/shr1 */
|
||||
Vector128.Create(0x85848382, 0x89888786, 0x8d8c8b8a, 0x01008f8e), /* shl 14 (16 - 3)/shr2 */
|
||||
Vector128.Create(0x86858483, 0x8a898887, 0x8e8d8c8b, 0x0201008f), /* shl 13 (16 - 4)/shr3 */
|
||||
Vector128.Create(0x87868584, 0x8b8a8988, 0x8f8e8d8c, 0x03020100), /* shl 12 (16 - 4)/shr4 */
|
||||
Vector128.Create(0x88878685, 0x8c8b8a89, 0x008f8e8d, 0x04030201), /* shl 11 (16 - 5)/shr5 */
|
||||
Vector128.Create(0x89888786, 0x8d8c8b8a, 0x01008f8e, 0x05040302), /* shl 10 (16 - 6)/shr6 */
|
||||
Vector128.Create(0x8a898887, 0x8e8d8c8b, 0x0201008f, 0x06050403), /* shl 9 (16 - 7)/shr7 */
|
||||
Vector128.Create(0x8b8a8988, 0x8f8e8d8c, 0x03020100, 0x07060504), /* shl 8 (16 - 8)/shr8 */
|
||||
Vector128.Create(0x8c8b8a89, 0x008f8e8d, 0x04030201, 0x08070605), /* shl 7 (16 - 9)/shr9 */
|
||||
Vector128.Create(0x8d8c8b8a, 0x01008f8e, 0x05040302, 0x09080706), /* shl 6 (16 -10)/shr10*/
|
||||
Vector128.Create(0x8e8d8c8b, 0x0201008f, 0x06050403, 0x0a090807), /* shl 5 (16 -11)/shr11*/
|
||||
Vector128.Create(0x8f8e8d8c, 0x03020100, 0x07060504, 0x0b0a0908), /* shl 4 (16 -12)/shr12*/
|
||||
Vector128.Create(0x008f8e8du, 0x04030201, 0x08070605, 0x0c0b0a09), /* shl 3 (16 -13)/shr13*/
|
||||
Vector128.Create(0x01008f8eu, 0x05040302, 0x09080706, 0x0d0c0b0a), /* shl 2 (16 -14)/shr14*/
|
||||
Vector128.Create(0x0201008fu, 0x06050403, 0x0a090807, 0x0e0d0c0b) /* shl 1 (16 -15)/shr15*/
|
||||
};
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static void Fold1(ref Vector128<uint> xmmCRC0, ref Vector128<uint> xmmCRC1, ref Vector128<uint> xmmCRC2,
|
||||
ref Vector128<uint> xmmCRC3)
|
||||
{
|
||||
Vector128<uint> xmmFold4 = Vector128.Create(0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001);
|
||||
|
||||
Vector128<uint> xTmp3 = xmmCRC3;
|
||||
|
||||
xmmCRC3 = xmmCRC0;
|
||||
xmmCRC0 = Pclmulqdq.CarrylessMultiply(xmmCRC0.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
|
||||
Vector128<float> psCRC0 = xmmCRC0.AsSingle();
|
||||
Vector128<float> psCRC3 = xmmCRC3.AsSingle();
|
||||
Vector128<float> psRes = Sse.Xor(psCRC0, psCRC3);
|
||||
|
||||
xmmCRC0 = xmmCRC1;
|
||||
xmmCRC1 = xmmCRC2;
|
||||
xmmCRC2 = xTmp3;
|
||||
xmmCRC3 = psRes.AsUInt32();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static void Fold2(ref Vector128<uint> xmmCRC0, ref Vector128<uint> xmmCRC1, ref Vector128<uint> xmmCRC2,
|
||||
ref Vector128<uint> xmmCRC3)
|
||||
{
|
||||
Vector128<uint> xmmFold4 = Vector128.Create(0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001);
|
||||
|
||||
Vector128<uint> xTmp3 = xmmCRC3;
|
||||
Vector128<uint> xTmp2 = xmmCRC2;
|
||||
|
||||
xmmCRC3 = xmmCRC1;
|
||||
xmmCRC1 = Pclmulqdq.CarrylessMultiply(xmmCRC1.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
|
||||
Vector128<float> psCRC3 = xmmCRC3.AsSingle();
|
||||
Vector128<float> psCRC1 = xmmCRC1.AsSingle();
|
||||
Vector128<float> psRes31 = Sse.Xor(psCRC3, psCRC1);
|
||||
|
||||
xmmCRC2 = xmmCRC0;
|
||||
xmmCRC0 = Pclmulqdq.CarrylessMultiply(xmmCRC0.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmmCRC2 = Pclmulqdq.CarrylessMultiply(xmmCRC2.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
|
||||
Vector128<float> psCRC0 = xmmCRC0.AsSingle();
|
||||
Vector128<float> psCRC2 = xmmCRC2.AsSingle();
|
||||
Vector128<float> psRes20 = Sse.Xor(psCRC0, psCRC2);
|
||||
|
||||
xmmCRC0 = xTmp2;
|
||||
xmmCRC1 = xTmp3;
|
||||
xmmCRC2 = psRes20.AsUInt32();
|
||||
xmmCRC3 = psRes31.AsUInt32();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static void Fold3(ref Vector128<uint> xmmCRC0, ref Vector128<uint> xmmCRC1, ref Vector128<uint> xmmCRC2,
|
||||
ref Vector128<uint> xmmCRC3)
|
||||
{
|
||||
Vector128<uint> xmmFold4 = Vector128.Create(0x54442bd4, 0x00000001, 0xc6e41596, 0x00000001);
|
||||
|
||||
Vector128<uint> xTmp3 = xmmCRC3;
|
||||
|
||||
xmmCRC3 = xmmCRC2;
|
||||
xmmCRC2 = Pclmulqdq.CarrylessMultiply(xmmCRC2.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
|
||||
Vector128<float> psCRC2 = xmmCRC2.AsSingle();
|
||||
Vector128<float> psCRC3 = xmmCRC3.AsSingle();
|
||||
Vector128<float> psRes32 = Sse.Xor(psCRC2, psCRC3);
|
||||
|
||||
xmmCRC2 = xmmCRC1;
|
||||
xmmCRC1 = Pclmulqdq.CarrylessMultiply(xmmCRC1.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmmCRC2 = Pclmulqdq.CarrylessMultiply(xmmCRC2.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
|
||||
Vector128<float> psCRC1 = xmmCRC1.AsSingle();
|
||||
psCRC2 = xmmCRC2.AsSingle();
|
||||
Vector128<float> psRes21 = Sse.Xor(psCRC1, psCRC2);
|
||||
|
||||
xmmCRC1 = xmmCRC0;
|
||||
xmmCRC0 = Pclmulqdq.CarrylessMultiply(xmmCRC0.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmmCRC1 = Pclmulqdq.CarrylessMultiply(xmmCRC1.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
|
||||
Vector128<float> psCRC0 = xmmCRC0.AsSingle();
|
||||
psCRC1 = xmmCRC1.AsSingle();
|
||||
Vector128<float> psRes10 = Sse.Xor(psCRC0, psCRC1);
|
||||
|
||||
xmmCRC0 = xTmp3;
|
||||
xmmCRC1 = psRes10.AsUInt32();
|
||||
xmmCRC2 = psRes21.AsUInt32();
|
||||
xmmCRC3 = psRes32.AsUInt32();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static void Fold4(ref Vector128<uint> xmmCRC0, ref Vector128<uint> xmmCRC1, ref Vector128<uint> xmmCRC2,
|
||||
ref Vector128<uint> xmmCRC3)
|
||||
{
|
||||
Vector128<uint> xmmFold4 = Vector128.Create(0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001);
|
||||
|
||||
Vector128<uint> xTmp0 = xmmCRC0;
|
||||
Vector128<uint> xTmp1 = xmmCRC1;
|
||||
Vector128<uint> xTmp2 = xmmCRC2;
|
||||
Vector128<uint> xTmp3 = xmmCRC3;
|
||||
|
||||
xmmCRC0 = Pclmulqdq.CarrylessMultiply(xmmCRC0.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xTmp0 = Pclmulqdq.CarrylessMultiply(xTmp0.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
|
||||
Vector128<float> psCRC0 = xmmCRC0.AsSingle();
|
||||
Vector128<float> psT0 = xTmp0.AsSingle();
|
||||
Vector128<float> psRes0 = Sse.Xor(psCRC0, psT0);
|
||||
|
||||
xmmCRC1 = Pclmulqdq.CarrylessMultiply(xmmCRC1.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xTmp1 = Pclmulqdq.CarrylessMultiply(xTmp1.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
|
||||
Vector128<float> psCRC1 = xmmCRC1.AsSingle();
|
||||
Vector128<float> psT1 = xTmp1.AsSingle();
|
||||
Vector128<float> psRes1 = Sse.Xor(psCRC1, psT1);
|
||||
|
||||
xmmCRC2 = Pclmulqdq.CarrylessMultiply(xmmCRC2.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xTmp2 = Pclmulqdq.CarrylessMultiply(xTmp2.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
|
||||
Vector128<float> psCRC2 = xmmCRC2.AsSingle();
|
||||
Vector128<float> psT2 = xTmp2.AsSingle();
|
||||
Vector128<float> psRes2 = Sse.Xor(psCRC2, psT2);
|
||||
|
||||
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xTmp3 = Pclmulqdq.CarrylessMultiply(xTmp3.AsUInt64(), xmmFold4.AsUInt64(), 0x10).AsUInt32();
|
||||
Vector128<float> psCRC3 = xmmCRC3.AsSingle();
|
||||
Vector128<float> psT3 = xTmp3.AsSingle();
|
||||
Vector128<float> psRes3 = Sse.Xor(psCRC3, psT3);
|
||||
|
||||
xmmCRC0 = psRes0.AsUInt32();
|
||||
xmmCRC1 = psRes1.AsUInt32();
|
||||
xmmCRC2 = psRes2.AsUInt32();
|
||||
xmmCRC3 = psRes3.AsUInt32();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static void PartialFold(long len, ref Vector128<uint> xmmCRC0, ref Vector128<uint> xmmCRC1,
|
||||
ref Vector128<uint> xmmCRC2, ref Vector128<uint> xmmCRC3,
|
||||
ref Vector128<uint> xmmCRCPart)
|
||||
{
|
||||
Vector128<uint> xmmFold4 = Vector128.Create(0x54442bd4, 0x00000001, 0xc6e41596, 0x00000001);
|
||||
Vector128<uint> xmmMask3 = Vector128.Create(0x80808080);
|
||||
|
||||
Vector128<uint> xmmShl = _pshufbShfTable[len - 1];
|
||||
Vector128<uint> xmmShr = xmmShl;
|
||||
xmmShr = Sse2.Xor(xmmShr, xmmMask3);
|
||||
|
||||
Vector128<uint> xmmA00 = Ssse3.Shuffle(xmmCRC0.AsByte(), xmmShl.AsByte()).AsUInt32();
|
||||
|
||||
xmmCRC0 = Ssse3.Shuffle(xmmCRC0.AsByte(), xmmShr.AsByte()).AsUInt32();
|
||||
Vector128<uint> xmmTmp1 = Ssse3.Shuffle(xmmCRC1.AsByte(), xmmShl.AsByte()).AsUInt32();
|
||||
xmmCRC0 = Sse2.Or(xmmCRC0, xmmTmp1);
|
||||
|
||||
xmmCRC1 = Ssse3.Shuffle(xmmCRC1.AsByte(), xmmShr.AsByte()).AsUInt32();
|
||||
Vector128<uint> xmmTmp2 = Ssse3.Shuffle(xmmCRC2.AsByte(), xmmShl.AsByte()).AsUInt32();
|
||||
xmmCRC1 = Sse2.Or(xmmCRC1, xmmTmp2);
|
||||
|
||||
xmmCRC2 = Ssse3.Shuffle(xmmCRC2.AsByte(), xmmShr.AsByte()).AsUInt32();
|
||||
Vector128<uint> xmmTmp3 = Ssse3.Shuffle(xmmCRC3.AsByte(), xmmShl.AsByte()).AsUInt32();
|
||||
xmmCRC2 = Sse2.Or(xmmCRC2, xmmTmp3);
|
||||
|
||||
xmmCRC3 = Ssse3.Shuffle(xmmCRC3.AsByte(), xmmShr.AsByte()).AsUInt32();
|
||||
xmmCRCPart = Ssse3.Shuffle(xmmCRCPart.AsByte(), xmmShl.AsByte()).AsUInt32();
|
||||
xmmCRC3 = Sse2.Or(xmmCRC3, xmmCRCPart);
|
||||
|
||||
Vector128<uint> xmmA01 = Pclmulqdq.CarrylessMultiply(xmmA00.AsUInt64(), xmmFold4.AsUInt64(), 0x10).
|
||||
AsUInt32();
|
||||
|
||||
xmmA00 = Pclmulqdq.CarrylessMultiply(xmmA00.AsUInt64(), xmmFold4.AsUInt64(), 0x01).AsUInt32();
|
||||
|
||||
Vector128<float> psCRC3 = xmmCRC3.AsSingle();
|
||||
Vector128<float> psa00 = xmmA00.AsSingle();
|
||||
Vector128<float> psa01 = xmmA01.AsSingle();
|
||||
|
||||
Vector128<float> psRes = Sse.Xor(psCRC3, psa00);
|
||||
psRes = Sse.Xor(psRes, psa01);
|
||||
|
||||
xmmCRC3 = psRes.AsUInt32();
|
||||
}
|
||||
|
||||
internal static uint Step(byte[] src, long len, uint initialCRC)
|
||||
{
|
||||
Vector128<uint> xmmT0, xmmT1, xmmT2;
|
||||
Vector128<uint> xmmInitial = Sse2.ConvertScalarToVector128UInt32(initialCRC);
|
||||
Vector128<uint> xmmCRC0 = Sse2.ConvertScalarToVector128UInt32(0x9db42487);
|
||||
Vector128<uint> xmmCRC1 = Vector128<uint>.Zero;
|
||||
Vector128<uint> xmmCRC2 = Vector128<uint>.Zero;
|
||||
Vector128<uint> xmmCRC3 = Vector128<uint>.Zero;
|
||||
Vector128<uint> xmmCRCPart;
|
||||
int bufPos = 0;
|
||||
|
||||
bool first = true;
|
||||
|
||||
/* fold 512 to 32 step variable declarations for ISO-C90 compat. */
|
||||
Vector128<uint> xmmMask = Vector128.Create(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000);
|
||||
Vector128<uint> xmmMask2 = Vector128.Create(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
|
||||
uint crc;
|
||||
|
||||
if(len < 16)
|
||||
{
|
||||
switch(len)
|
||||
{
|
||||
case 0: return initialCRC;
|
||||
case < 4:
|
||||
/*
|
||||
* no idea how to do this for <4 bytes, delegate to classic impl.
|
||||
*/
|
||||
crc = ~initialCRC;
|
||||
|
||||
switch(len)
|
||||
{
|
||||
case 3:
|
||||
crc = (crc >> 8) ^ Crc32Context._isoCrc32Table[0][(crc & 0xFF) ^ src[bufPos++]];
|
||||
goto case 2;
|
||||
case 2:
|
||||
crc = (crc >> 8) ^ Crc32Context._isoCrc32Table[0][(crc & 0xFF) ^ src[bufPos++]];
|
||||
goto case 1;
|
||||
case 1:
|
||||
crc = (crc >> 8) ^ Crc32Context._isoCrc32Table[0][(crc & 0xFF) ^ src[bufPos]];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
xmmCRCPart = Vector128.Create(BitConverter.ToUInt32(src, 0), BitConverter.ToUInt32(src, 4),
|
||||
BitConverter.ToUInt32(src, 8), BitConverter.ToUInt32(src, 12));
|
||||
|
||||
xmmCRCPart = Sse2.Xor(xmmCRCPart, xmmInitial);
|
||||
|
||||
goto partial;
|
||||
}
|
||||
|
||||
while((len -= 64) >= 0)
|
||||
{
|
||||
xmmT0 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
xmmT1 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
xmmT2 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
Vector128<uint> xmmT3 = Vector128.Create(BitConverter.ToUInt32(src, bufPos),
|
||||
BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
if(first)
|
||||
{
|
||||
first = false;
|
||||
xmmT0 = Sse2.Xor(xmmT0, xmmInitial);
|
||||
}
|
||||
|
||||
Fold4(ref xmmCRC0, ref xmmCRC1, ref xmmCRC2, ref xmmCRC3);
|
||||
|
||||
xmmCRC0 = Sse2.Xor(xmmCRC0, xmmT0);
|
||||
xmmCRC1 = Sse2.Xor(xmmCRC1, xmmT1);
|
||||
xmmCRC2 = Sse2.Xor(xmmCRC2, xmmT2);
|
||||
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmT3);
|
||||
}
|
||||
|
||||
/*
|
||||
* len = num bytes left - 64
|
||||
*/
|
||||
if(len + 16 >= 0)
|
||||
{
|
||||
len += 16;
|
||||
|
||||
xmmT0 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
xmmT1 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
xmmT2 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
if(first)
|
||||
xmmT0 = Sse2.Xor(xmmT0, xmmInitial);
|
||||
|
||||
Fold3(ref xmmCRC0, ref xmmCRC1, ref xmmCRC2, ref xmmCRC3);
|
||||
|
||||
xmmCRC1 = Sse2.Xor(xmmCRC1, xmmT0);
|
||||
xmmCRC2 = Sse2.Xor(xmmCRC2, xmmT1);
|
||||
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmT2);
|
||||
|
||||
if(len == 0)
|
||||
goto done;
|
||||
|
||||
xmmCRCPart = Vector128.Create(BitConverter.ToUInt32(src, bufPos),
|
||||
BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
}
|
||||
else if(len + 32 >= 0)
|
||||
{
|
||||
len += 32;
|
||||
|
||||
xmmT0 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
xmmT1 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
if(first)
|
||||
xmmT0 = Sse2.Xor(xmmT0, xmmInitial);
|
||||
|
||||
Fold2(ref xmmCRC0, ref xmmCRC1, ref xmmCRC2, ref xmmCRC3);
|
||||
|
||||
xmmCRC2 = Sse2.Xor(xmmCRC2, xmmT0);
|
||||
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmT1);
|
||||
|
||||
if(len == 0)
|
||||
goto done;
|
||||
|
||||
xmmCRCPart = Vector128.Create(BitConverter.ToUInt32(src, bufPos),
|
||||
BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
}
|
||||
else if(len + 48 >= 0)
|
||||
{
|
||||
len += 48;
|
||||
|
||||
xmmT0 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
if(first)
|
||||
xmmT0 = Sse2.Xor(xmmT0, xmmInitial);
|
||||
|
||||
Fold1(ref xmmCRC0, ref xmmCRC1, ref xmmCRC2, ref xmmCRC3);
|
||||
|
||||
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmT0);
|
||||
|
||||
if(len == 0)
|
||||
goto done;
|
||||
|
||||
xmmCRCPart = Vector128.Create(BitConverter.ToUInt32(src, bufPos),
|
||||
BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
}
|
||||
else
|
||||
{
|
||||
len += 64;
|
||||
|
||||
if(len == 0)
|
||||
goto done;
|
||||
|
||||
xmmCRCPart = Vector128.Create(BitConverter.ToUInt32(src, bufPos),
|
||||
BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
if(first)
|
||||
xmmCRCPart = Sse2.Xor(xmmCRCPart, xmmInitial);
|
||||
}
|
||||
|
||||
partial:
|
||||
PartialFold(len, ref xmmCRC0, ref xmmCRC1, ref xmmCRC2, ref xmmCRC3, ref xmmCRCPart);
|
||||
|
||||
done:
|
||||
|
||||
/* fold 512 to 32 */
|
||||
|
||||
/*
|
||||
* k1
|
||||
*/
|
||||
Vector128<uint> crcFold = Vector128.Create(_crcK[0], _crcK[1], _crcK[2], _crcK[3]);
|
||||
|
||||
Vector128<uint> xTmp0 = Pclmulqdq.CarrylessMultiply(xmmCRC0.AsUInt64(), crcFold.AsUInt64(), 0x10).
|
||||
AsUInt32();
|
||||
|
||||
xmmCRC0 = Pclmulqdq.CarrylessMultiply(xmmCRC0.AsUInt64(), crcFold.AsUInt64(), 0x01).AsUInt32();
|
||||
xmmCRC1 = Sse2.Xor(xmmCRC1, xTmp0);
|
||||
xmmCRC1 = Sse2.Xor(xmmCRC1, xmmCRC0);
|
||||
|
||||
Vector128<uint> xTmp1 = Pclmulqdq.CarrylessMultiply(xmmCRC1.AsUInt64(), crcFold.AsUInt64(), 0x10).
|
||||
AsUInt32();
|
||||
|
||||
xmmCRC1 = Pclmulqdq.CarrylessMultiply(xmmCRC1.AsUInt64(), crcFold.AsUInt64(), 0x01).AsUInt32();
|
||||
xmmCRC2 = Sse2.Xor(xmmCRC2, xTmp1);
|
||||
xmmCRC2 = Sse2.Xor(xmmCRC2, xmmCRC1);
|
||||
|
||||
Vector128<uint> xTmp2 = Pclmulqdq.CarrylessMultiply(xmmCRC2.AsUInt64(), crcFold.AsUInt64(), 0x10).
|
||||
AsUInt32();
|
||||
|
||||
xmmCRC2 = Pclmulqdq.CarrylessMultiply(xmmCRC2.AsUInt64(), crcFold.AsUInt64(), 0x01).AsUInt32();
|
||||
xmmCRC3 = Sse2.Xor(xmmCRC3, xTmp2);
|
||||
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC2);
|
||||
|
||||
/*
|
||||
* k5
|
||||
*/
|
||||
crcFold = Vector128.Create(_crcK[4], _crcK[5], _crcK[6], _crcK[7]);
|
||||
|
||||
xmmCRC0 = xmmCRC3;
|
||||
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), crcFold.AsUInt64(), 0).AsUInt32();
|
||||
xmmCRC0 = Sse2.ShiftRightLogical128BitLane(xmmCRC0, 8);
|
||||
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC0);
|
||||
|
||||
xmmCRC0 = xmmCRC3;
|
||||
xmmCRC3 = Sse2.ShiftLeftLogical128BitLane(xmmCRC3, 4);
|
||||
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), crcFold.AsUInt64(), 0x10).AsUInt32();
|
||||
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC0);
|
||||
xmmCRC3 = Sse2.And(xmmCRC3, xmmMask2);
|
||||
|
||||
/*
|
||||
* k7
|
||||
*/
|
||||
xmmCRC1 = xmmCRC3;
|
||||
xmmCRC2 = xmmCRC3;
|
||||
crcFold = Vector128.Create(_crcK[8], _crcK[9], _crcK[10], _crcK[11]);
|
||||
|
||||
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), crcFold.AsUInt64(), 0).AsUInt32();
|
||||
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC2);
|
||||
xmmCRC3 = Sse2.And(xmmCRC3, xmmMask);
|
||||
|
||||
xmmCRC2 = xmmCRC3;
|
||||
xmmCRC3 = Pclmulqdq.CarrylessMultiply(xmmCRC3.AsUInt64(), crcFold.AsUInt64(), 0x10).AsUInt32();
|
||||
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC2);
|
||||
xmmCRC3 = Sse2.Xor(xmmCRC3, xmmCRC1);
|
||||
|
||||
/*
|
||||
* could just as well write xmm_crc3[2], doing a movaps and truncating, but
|
||||
* no real advantage - it's a tiny bit slower per call, while no additional CPUs
|
||||
* would be supported by only requiring SSSE3 and CLMUL instead of SSE4.1 + CLMUL
|
||||
*/
|
||||
crc = Sse41.Extract(xmmCRC3, 2);
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,562 +0,0 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : clmul.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
// Wajdi Feghali <wajdi.k.feghali@intel.com>
|
||||
// Jim Guilford <james.guilford@intel.com>
|
||||
// Vinodh Gopal <vinodh.gopal@intel.com>
|
||||
// Erdinc Ozturk <erdinc.ozturk@intel.com>
|
||||
// Jim Kukunas <james.t.kukunas@linux.intel.com>
|
||||
// Marian Beermann
|
||||
//
|
||||
// Component : Checksums.
|
||||
//
|
||||
// --[ Description ] ----------------------------------------------------------
|
||||
//
|
||||
// Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ
|
||||
// instruction.
|
||||
//
|
||||
// A white paper describing this algorithm can be found at:
|
||||
// http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
|
||||
//
|
||||
// --[ License ] --------------------------------------------------------------
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from
|
||||
// the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright © 2011-2021 Natalia Portillo
|
||||
// Copyright (c) 2016 Marian Beermann (add support for initial value, restructuring)
|
||||
// Copyright (C) 2013 Intel Corporation. All rights reserved.
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
namespace Aaru6.Checksums
|
||||
{
|
||||
public static class CRC32CLMUL
|
||||
{
|
||||
static readonly uint[] crc_k =
|
||||
{
|
||||
0xccaa009e, 0x00000000, /* rk1 */ 0x751997d0, 0x00000001, /* rk2 */ 0xccaa009e, 0x00000000, /* rk5 */
|
||||
0x63cd6124, 0x00000001, /* rk6 */ 0xf7011640, 0x00000001, /* rk7 */ 0xdb710640, 0x00000001 /* rk8 */
|
||||
};
|
||||
|
||||
static readonly Vector128<uint>[] pshufb_shf_table =
|
||||
{
|
||||
Vector128.Create(0x84838281, 0x88878685, 0x8c8b8a89, 0x008f8e8d), /* shl 15 (16 - 1)/shr1 */
|
||||
Vector128.Create(0x85848382, 0x89888786, 0x8d8c8b8a, 0x01008f8e), /* shl 14 (16 - 3)/shr2 */
|
||||
Vector128.Create(0x86858483, 0x8a898887, 0x8e8d8c8b, 0x0201008f), /* shl 13 (16 - 4)/shr3 */
|
||||
Vector128.Create(0x87868584, 0x8b8a8988, 0x8f8e8d8c, 0x03020100), /* shl 12 (16 - 4)/shr4 */
|
||||
Vector128.Create(0x88878685, 0x8c8b8a89, 0x008f8e8d, 0x04030201), /* shl 11 (16 - 5)/shr5 */
|
||||
Vector128.Create(0x89888786, 0x8d8c8b8a, 0x01008f8e, 0x05040302), /* shl 10 (16 - 6)/shr6 */
|
||||
Vector128.Create(0x8a898887, 0x8e8d8c8b, 0x0201008f, 0x06050403), /* shl 9 (16 - 7)/shr7 */
|
||||
Vector128.Create(0x8b8a8988, 0x8f8e8d8c, 0x03020100, 0x07060504), /* shl 8 (16 - 8)/shr8 */
|
||||
Vector128.Create(0x8c8b8a89, 0x008f8e8d, 0x04030201, 0x08070605), /* shl 7 (16 - 9)/shr9 */
|
||||
Vector128.Create(0x8d8c8b8a, 0x01008f8e, 0x05040302, 0x09080706), /* shl 6 (16 -10)/shr10*/
|
||||
Vector128.Create(0x8e8d8c8b, 0x0201008f, 0x06050403, 0x0a090807), /* shl 5 (16 -11)/shr11*/
|
||||
Vector128.Create(0x8f8e8d8c, 0x03020100, 0x07060504, 0x0b0a0908), /* shl 4 (16 -12)/shr12*/
|
||||
Vector128.Create(0x008f8e8du, 0x04030201, 0x08070605, 0x0c0b0a09), /* shl 3 (16 -13)/shr13*/
|
||||
Vector128.Create(0x01008f8eu, 0x05040302, 0x09080706, 0x0d0c0b0a), /* shl 2 (16 -14)/shr14*/
|
||||
Vector128.Create(0x0201008fu, 0x06050403, 0x0a090807, 0x0e0d0c0b) /* shl 1 (16 -15)/shr15*/
|
||||
};
|
||||
|
||||
static void fold_1(ref Vector128<uint> xmm_crc0, ref Vector128<uint> xmm_crc1, ref Vector128<uint> xmm_crc2,
|
||||
ref Vector128<uint> xmm_crc3)
|
||||
{
|
||||
Vector128<uint> xmm_fold4 = Vector128.Create(0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001);
|
||||
|
||||
Vector128<uint> x_tmp3;
|
||||
Vector128<float> ps_crc0, ps_crc3, ps_res;
|
||||
|
||||
x_tmp3 = xmm_crc3;
|
||||
|
||||
xmm_crc3 = xmm_crc0;
|
||||
xmm_crc0 = Pclmulqdq.CarrylessMultiply(xmm_crc0.AsUInt64(), xmm_fold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmm_crc3 = Pclmulqdq.CarrylessMultiply(xmm_crc3.AsUInt64(), xmm_fold4.AsUInt64(), 0x10).AsUInt32();
|
||||
ps_crc0 = xmm_crc0.AsSingle();
|
||||
ps_crc3 = xmm_crc3.AsSingle();
|
||||
ps_res = Sse.Xor(ps_crc0, ps_crc3);
|
||||
|
||||
xmm_crc0 = xmm_crc1;
|
||||
xmm_crc1 = xmm_crc2;
|
||||
xmm_crc2 = x_tmp3;
|
||||
xmm_crc3 = ps_res.AsUInt32();
|
||||
}
|
||||
|
||||
static void fold_2(ref Vector128<uint> xmm_crc0, ref Vector128<uint> xmm_crc1, ref Vector128<uint> xmm_crc2,
|
||||
ref Vector128<uint> xmm_crc3)
|
||||
{
|
||||
Vector128<uint> xmm_fold4 = Vector128.Create(0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001);
|
||||
|
||||
Vector128<uint> x_tmp3, x_tmp2;
|
||||
Vector128<float> ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res31, ps_res20;
|
||||
|
||||
x_tmp3 = xmm_crc3;
|
||||
x_tmp2 = xmm_crc2;
|
||||
|
||||
xmm_crc3 = xmm_crc1;
|
||||
xmm_crc1 = Pclmulqdq.CarrylessMultiply(xmm_crc1.AsUInt64(), xmm_fold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmm_crc3 = Pclmulqdq.CarrylessMultiply(xmm_crc3.AsUInt64(), xmm_fold4.AsUInt64(), 0x10).AsUInt32();
|
||||
ps_crc3 = xmm_crc3.AsSingle();
|
||||
ps_crc1 = xmm_crc1.AsSingle();
|
||||
ps_res31 = Sse.Xor(ps_crc3, ps_crc1);
|
||||
|
||||
xmm_crc2 = xmm_crc0;
|
||||
xmm_crc0 = Pclmulqdq.CarrylessMultiply(xmm_crc0.AsUInt64(), xmm_fold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmm_crc2 = Pclmulqdq.CarrylessMultiply(xmm_crc2.AsUInt64(), xmm_fold4.AsUInt64(), 0x10).AsUInt32();
|
||||
ps_crc0 = xmm_crc0.AsSingle();
|
||||
ps_crc2 = xmm_crc2.AsSingle();
|
||||
ps_res20 = Sse.Xor(ps_crc0, ps_crc2);
|
||||
|
||||
xmm_crc0 = x_tmp2;
|
||||
xmm_crc1 = x_tmp3;
|
||||
xmm_crc2 = ps_res20.AsUInt32();
|
||||
xmm_crc3 = ps_res31.AsUInt32();
|
||||
}
|
||||
|
||||
static void fold_3(ref Vector128<uint> xmm_crc0, ref Vector128<uint> xmm_crc1, ref Vector128<uint> xmm_crc2,
|
||||
ref Vector128<uint> xmm_crc3)
|
||||
{
|
||||
Vector128<uint> xmm_fold4 = Vector128.Create(0x54442bd4, 0x00000001, 0xc6e41596, 0x00000001);
|
||||
|
||||
Vector128<uint> x_tmp3;
|
||||
Vector128<float> ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res32, ps_res21, ps_res10;
|
||||
|
||||
x_tmp3 = xmm_crc3;
|
||||
|
||||
xmm_crc3 = xmm_crc2;
|
||||
xmm_crc2 = Pclmulqdq.CarrylessMultiply(xmm_crc2.AsUInt64(), xmm_fold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmm_crc3 = Pclmulqdq.CarrylessMultiply(xmm_crc3.AsUInt64(), xmm_fold4.AsUInt64(), 0x10).AsUInt32();
|
||||
ps_crc2 = xmm_crc2.AsSingle();
|
||||
ps_crc3 = xmm_crc3.AsSingle();
|
||||
ps_res32 = Sse.Xor(ps_crc2, ps_crc3);
|
||||
|
||||
xmm_crc2 = xmm_crc1;
|
||||
xmm_crc1 = Pclmulqdq.CarrylessMultiply(xmm_crc1.AsUInt64(), xmm_fold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmm_crc2 = Pclmulqdq.CarrylessMultiply(xmm_crc2.AsUInt64(), xmm_fold4.AsUInt64(), 0x10).AsUInt32();
|
||||
ps_crc1 = xmm_crc1.AsSingle();
|
||||
ps_crc2 = xmm_crc2.AsSingle();
|
||||
ps_res21 = Sse.Xor(ps_crc1, ps_crc2);
|
||||
|
||||
xmm_crc1 = xmm_crc0;
|
||||
xmm_crc0 = Pclmulqdq.CarrylessMultiply(xmm_crc0.AsUInt64(), xmm_fold4.AsUInt64(), 0x01).AsUInt32();
|
||||
xmm_crc1 = Pclmulqdq.CarrylessMultiply(xmm_crc1.AsUInt64(), xmm_fold4.AsUInt64(), 0x10).AsUInt32();
|
||||
ps_crc0 = xmm_crc0.AsSingle();
|
||||
ps_crc1 = xmm_crc1.AsSingle();
|
||||
ps_res10 = Sse.Xor(ps_crc0, ps_crc1);
|
||||
|
||||
xmm_crc0 = x_tmp3;
|
||||
xmm_crc1 = ps_res10.AsUInt32();
|
||||
xmm_crc2 = ps_res21.AsUInt32();
|
||||
xmm_crc3 = ps_res32.AsUInt32();
|
||||
}
|
||||
|
||||
static void fold_4(ref Vector128<uint> xmm_crc0, ref Vector128<uint> xmm_crc1, ref Vector128<uint> xmm_crc2,
|
||||
ref Vector128<uint> xmm_crc3)
|
||||
{
|
||||
Vector128<uint> xmm_fold4 = Vector128.Create(0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001);
|
||||
|
||||
Vector128<uint> x_tmp0, x_tmp1, x_tmp2, x_tmp3;
|
||||
Vector128<float> ps_crc0, ps_crc1, ps_crc2, ps_crc3;
|
||||
Vector128<float> ps_t0, ps_t1, ps_t2, ps_t3;
|
||||
Vector128<float> ps_res0, ps_res1, ps_res2, ps_res3;
|
||||
|
||||
x_tmp0 = xmm_crc0;
|
||||
x_tmp1 = xmm_crc1;
|
||||
x_tmp2 = xmm_crc2;
|
||||
x_tmp3 = xmm_crc3;
|
||||
|
||||
xmm_crc0 = Pclmulqdq.CarrylessMultiply(xmm_crc0.AsUInt64(), xmm_fold4.AsUInt64(), 0x01).AsUInt32();
|
||||
x_tmp0 = Pclmulqdq.CarrylessMultiply(x_tmp0.AsUInt64(), xmm_fold4.AsUInt64(), 0x10).AsUInt32();
|
||||
ps_crc0 = xmm_crc0.AsSingle();
|
||||
ps_t0 = x_tmp0.AsSingle();
|
||||
ps_res0 = Sse.Xor(ps_crc0, ps_t0);
|
||||
|
||||
xmm_crc1 = Pclmulqdq.CarrylessMultiply(xmm_crc1.AsUInt64(), xmm_fold4.AsUInt64(), 0x01).AsUInt32();
|
||||
x_tmp1 = Pclmulqdq.CarrylessMultiply(x_tmp1.AsUInt64(), xmm_fold4.AsUInt64(), 0x10).AsUInt32();
|
||||
ps_crc1 = xmm_crc1.AsSingle();
|
||||
ps_t1 = x_tmp1.AsSingle();
|
||||
ps_res1 = Sse.Xor(ps_crc1, ps_t1);
|
||||
|
||||
xmm_crc2 = Pclmulqdq.CarrylessMultiply(xmm_crc2.AsUInt64(), xmm_fold4.AsUInt64(), 0x01).AsUInt32();
|
||||
x_tmp2 = Pclmulqdq.CarrylessMultiply(x_tmp2.AsUInt64(), xmm_fold4.AsUInt64(), 0x10).AsUInt32();
|
||||
ps_crc2 = xmm_crc2.AsSingle();
|
||||
ps_t2 = x_tmp2.AsSingle();
|
||||
ps_res2 = Sse.Xor(ps_crc2, ps_t2);
|
||||
|
||||
xmm_crc3 = Pclmulqdq.CarrylessMultiply(xmm_crc3.AsUInt64(), xmm_fold4.AsUInt64(), 0x01).AsUInt32();
|
||||
x_tmp3 = Pclmulqdq.CarrylessMultiply(x_tmp3.AsUInt64(), xmm_fold4.AsUInt64(), 0x10).AsUInt32();
|
||||
ps_crc3 = xmm_crc3.AsSingle();
|
||||
ps_t3 = x_tmp3.AsSingle();
|
||||
ps_res3 = Sse.Xor(ps_crc3, ps_t3);
|
||||
|
||||
xmm_crc0 = ps_res0.AsUInt32();
|
||||
xmm_crc1 = ps_res1.AsUInt32();
|
||||
xmm_crc2 = ps_res2.AsUInt32();
|
||||
xmm_crc3 = ps_res3.AsUInt32();
|
||||
}
|
||||
|
||||
static void partial_fold(long len, ref Vector128<uint> xmm_crc0, ref Vector128<uint> xmm_crc1,
|
||||
ref Vector128<uint> xmm_crc2, ref Vector128<uint> xmm_crc3,
|
||||
ref Vector128<uint> xmm_crc_part)
|
||||
{
|
||||
Vector128<uint> xmm_fold4 = Vector128.Create(0x54442bd4, 0x00000001, 0xc6e41596, 0x00000001);
|
||||
Vector128<uint> xmm_mask3 = Vector128.Create(0x80808080);
|
||||
|
||||
Vector128<uint> xmm_shl, xmm_shr, xmm_tmp1, xmm_tmp2, xmm_tmp3;
|
||||
Vector128<uint> xmm_a0_0, xmm_a0_1;
|
||||
Vector128<float> ps_crc3, psa0_0, psa0_1, ps_res;
|
||||
|
||||
xmm_shl = pshufb_shf_table[len - 1];
|
||||
xmm_shr = xmm_shl;
|
||||
xmm_shr = Sse2.Xor(xmm_shr, xmm_mask3);
|
||||
|
||||
xmm_a0_0 = Ssse3.Shuffle(xmm_crc0.AsByte(), xmm_shl.AsByte()).AsUInt32();
|
||||
|
||||
xmm_crc0 = Ssse3.Shuffle(xmm_crc0.AsByte(), xmm_shr.AsByte()).AsUInt32();
|
||||
xmm_tmp1 = Ssse3.Shuffle(xmm_crc1.AsByte(), xmm_shl.AsByte()).AsUInt32();
|
||||
xmm_crc0 = Sse2.Or(xmm_crc0, xmm_tmp1);
|
||||
|
||||
xmm_crc1 = Ssse3.Shuffle(xmm_crc1.AsByte(), xmm_shr.AsByte()).AsUInt32();
|
||||
xmm_tmp2 = Ssse3.Shuffle(xmm_crc2.AsByte(), xmm_shl.AsByte()).AsUInt32();
|
||||
xmm_crc1 = Sse2.Or(xmm_crc1, xmm_tmp2);
|
||||
|
||||
xmm_crc2 = Ssse3.Shuffle(xmm_crc2.AsByte(), xmm_shr.AsByte()).AsUInt32();
|
||||
xmm_tmp3 = Ssse3.Shuffle(xmm_crc3.AsByte(), xmm_shl.AsByte()).AsUInt32();
|
||||
xmm_crc2 = Sse2.Or(xmm_crc2, xmm_tmp3);
|
||||
|
||||
xmm_crc3 = Ssse3.Shuffle(xmm_crc3.AsByte(), xmm_shr.AsByte()).AsUInt32();
|
||||
xmm_crc_part = Ssse3.Shuffle(xmm_crc_part.AsByte(), xmm_shl.AsByte()).AsUInt32();
|
||||
xmm_crc3 = Sse2.Or(xmm_crc3, xmm_crc_part);
|
||||
|
||||
xmm_a0_1 = Pclmulqdq.CarrylessMultiply(xmm_a0_0.AsUInt64(), xmm_fold4.AsUInt64(), 0x10).AsUInt32();
|
||||
xmm_a0_0 = Pclmulqdq.CarrylessMultiply(xmm_a0_0.AsUInt64(), xmm_fold4.AsUInt64(), 0x01).AsUInt32();
|
||||
|
||||
ps_crc3 = xmm_crc3.AsSingle();
|
||||
psa0_0 = xmm_a0_0.AsSingle();
|
||||
psa0_1 = xmm_a0_1.AsSingle();
|
||||
|
||||
ps_res = Sse.Xor(ps_crc3, psa0_0);
|
||||
ps_res = Sse.Xor(ps_res, psa0_1);
|
||||
|
||||
xmm_crc3 = ps_res.AsUInt32();
|
||||
}
|
||||
|
||||
internal static uint crc32_clmul(byte[] src, long len, uint initial_crc)
|
||||
{
|
||||
Vector128<uint> xmm_t0, xmm_t1, xmm_t2, xmm_t3;
|
||||
Vector128<uint> xmm_initial = Sse2.ConvertScalarToVector128UInt32(initial_crc);
|
||||
Vector128<uint> xmm_crc0 = Sse2.ConvertScalarToVector128UInt32(0x9db42487);
|
||||
Vector128<uint> xmm_crc1 = Vector128<uint>.Zero;
|
||||
Vector128<uint> xmm_crc2 = Vector128<uint>.Zero;
|
||||
Vector128<uint> xmm_crc3 = Vector128<uint>.Zero;
|
||||
Vector128<uint> xmm_crc_part;
|
||||
int bufPos = 0;
|
||||
|
||||
bool first = true;
|
||||
|
||||
/* fold 512 to 32 step variable declarations for ISO-C90 compat. */
|
||||
Vector128<uint> xmm_mask = Vector128.Create(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000);
|
||||
Vector128<uint> xmm_mask2 = Vector128.Create(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
|
||||
uint crc;
|
||||
Vector128<uint> x_tmp0, x_tmp1, x_tmp2, crc_fold;
|
||||
|
||||
if(len < 16)
|
||||
{
|
||||
if(len == 0)
|
||||
return initial_crc;
|
||||
|
||||
if(len < 4)
|
||||
{
|
||||
/*
|
||||
* no idea how to do this for <4 bytes, delegate to classic impl.
|
||||
*/
|
||||
crc = ~initial_crc;
|
||||
|
||||
switch(len)
|
||||
{
|
||||
case 3:
|
||||
crc = (crc >> 8) ^ Crc32Context._isoCrc32Table[0][(crc & 0xFF) ^ src[bufPos++]];
|
||||
goto case 2;
|
||||
case 2:
|
||||
crc = (crc >> 8) ^ Crc32Context._isoCrc32Table[0][(crc & 0xFF) ^ src[bufPos++]];
|
||||
goto case 1;
|
||||
case 1:
|
||||
crc = (crc >> 8) ^ Crc32Context._isoCrc32Table[0][(crc & 0xFF) ^ src[bufPos++]];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
xmm_crc_part = Vector128.Create(BitConverter.ToUInt32(src, 0), BitConverter.ToUInt32(src, 4),
|
||||
BitConverter.ToUInt32(src, 8), BitConverter.ToUInt32(src, 12));
|
||||
|
||||
if(first)
|
||||
{
|
||||
first = false;
|
||||
xmm_crc_part = Sse2.Xor(xmm_crc_part, xmm_initial);
|
||||
}
|
||||
|
||||
goto partial;
|
||||
}
|
||||
|
||||
while((len -= 64) >= 0)
|
||||
{
|
||||
xmm_t0 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
xmm_t1 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
xmm_t2 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
xmm_t3 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
if(first)
|
||||
{
|
||||
first = false;
|
||||
xmm_t0 = Sse2.Xor(xmm_t0, xmm_initial);
|
||||
}
|
||||
|
||||
fold_4(ref xmm_crc0, ref xmm_crc1, ref xmm_crc2, ref xmm_crc3);
|
||||
|
||||
xmm_crc0 = Sse2.Xor(xmm_crc0, xmm_t0);
|
||||
xmm_crc1 = Sse2.Xor(xmm_crc1, xmm_t1);
|
||||
xmm_crc2 = Sse2.Xor(xmm_crc2, xmm_t2);
|
||||
xmm_crc3 = Sse2.Xor(xmm_crc3, xmm_t3);
|
||||
}
|
||||
|
||||
/*
|
||||
* len = num bytes left - 64
|
||||
*/
|
||||
if(len + 16 >= 0)
|
||||
{
|
||||
len += 16;
|
||||
|
||||
xmm_t0 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
xmm_t1 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
xmm_t2 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
if(first)
|
||||
{
|
||||
first = false;
|
||||
xmm_t0 = Sse2.Xor(xmm_t0, xmm_initial);
|
||||
}
|
||||
|
||||
fold_3(ref xmm_crc0, ref xmm_crc1, ref xmm_crc2, ref xmm_crc3);
|
||||
|
||||
xmm_crc1 = Sse2.Xor(xmm_crc1, xmm_t0);
|
||||
xmm_crc2 = Sse2.Xor(xmm_crc2, xmm_t1);
|
||||
xmm_crc3 = Sse2.Xor(xmm_crc3, xmm_t2);
|
||||
|
||||
if(len == 0)
|
||||
goto done;
|
||||
|
||||
xmm_crc_part = Vector128.Create(BitConverter.ToUInt32(src, bufPos),
|
||||
BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
}
|
||||
else if(len + 32 >= 0)
|
||||
{
|
||||
len += 32;
|
||||
|
||||
xmm_t0 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
xmm_t1 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
if(first)
|
||||
{
|
||||
first = false;
|
||||
xmm_t0 = Sse2.Xor(xmm_t0, xmm_initial);
|
||||
}
|
||||
|
||||
fold_2(ref xmm_crc0, ref xmm_crc1, ref xmm_crc2, ref xmm_crc3);
|
||||
|
||||
xmm_crc2 = Sse2.Xor(xmm_crc2, xmm_t0);
|
||||
xmm_crc3 = Sse2.Xor(xmm_crc3, xmm_t1);
|
||||
|
||||
if(len == 0)
|
||||
goto done;
|
||||
|
||||
xmm_crc_part = Vector128.Create(BitConverter.ToUInt32(src, bufPos),
|
||||
BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
}
|
||||
else if(len + 48 >= 0)
|
||||
{
|
||||
len += 48;
|
||||
|
||||
xmm_t0 = Vector128.Create(BitConverter.ToUInt32(src, bufPos), BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
if(first)
|
||||
{
|
||||
first = false;
|
||||
xmm_t0 = Sse2.Xor(xmm_t0, xmm_initial);
|
||||
}
|
||||
|
||||
fold_1(ref xmm_crc0, ref xmm_crc1, ref xmm_crc2, ref xmm_crc3);
|
||||
|
||||
xmm_crc3 = Sse2.Xor(xmm_crc3, xmm_t0);
|
||||
|
||||
if(len == 0)
|
||||
goto done;
|
||||
|
||||
xmm_crc_part = Vector128.Create(BitConverter.ToUInt32(src, bufPos),
|
||||
BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
}
|
||||
else
|
||||
{
|
||||
len += 64;
|
||||
|
||||
if(len == 0)
|
||||
goto done;
|
||||
|
||||
xmm_crc_part = Vector128.Create(BitConverter.ToUInt32(src, bufPos),
|
||||
BitConverter.ToUInt32(src, bufPos + 4),
|
||||
BitConverter.ToUInt32(src, bufPos + 8),
|
||||
BitConverter.ToUInt32(src, bufPos + 12));
|
||||
|
||||
if(first)
|
||||
{
|
||||
first = false;
|
||||
xmm_crc_part = Sse2.Xor(xmm_crc_part, xmm_initial);
|
||||
}
|
||||
}
|
||||
|
||||
partial:
|
||||
partial_fold(len, ref xmm_crc0, ref xmm_crc1, ref xmm_crc2, ref xmm_crc3, ref xmm_crc_part);
|
||||
|
||||
done:
|
||||
|
||||
/* fold 512 to 32 */
|
||||
|
||||
/*
|
||||
* k1
|
||||
*/
|
||||
crc_fold = Vector128.Create(crc_k[0], crc_k[1], crc_k[2], crc_k[3]);
|
||||
|
||||
x_tmp0 = Pclmulqdq.CarrylessMultiply(xmm_crc0.AsUInt64(), crc_fold.AsUInt64(), 0x10).AsUInt32();
|
||||
xmm_crc0 = Pclmulqdq.CarrylessMultiply(xmm_crc0.AsUInt64(), crc_fold.AsUInt64(), 0x01).AsUInt32();
|
||||
xmm_crc1 = Sse2.Xor(xmm_crc1, x_tmp0);
|
||||
xmm_crc1 = Sse2.Xor(xmm_crc1, xmm_crc0);
|
||||
|
||||
x_tmp1 = Pclmulqdq.CarrylessMultiply(xmm_crc1.AsUInt64(), crc_fold.AsUInt64(), 0x10).AsUInt32();
|
||||
xmm_crc1 = Pclmulqdq.CarrylessMultiply(xmm_crc1.AsUInt64(), crc_fold.AsUInt64(), 0x01).AsUInt32();
|
||||
xmm_crc2 = Sse2.Xor(xmm_crc2, x_tmp1);
|
||||
xmm_crc2 = Sse2.Xor(xmm_crc2, xmm_crc1);
|
||||
|
||||
x_tmp2 = Pclmulqdq.CarrylessMultiply(xmm_crc2.AsUInt64(), crc_fold.AsUInt64(), 0x10).AsUInt32();
|
||||
xmm_crc2 = Pclmulqdq.CarrylessMultiply(xmm_crc2.AsUInt64(), crc_fold.AsUInt64(), 0x01).AsUInt32();
|
||||
xmm_crc3 = Sse2.Xor(xmm_crc3, x_tmp2);
|
||||
xmm_crc3 = Sse2.Xor(xmm_crc3, xmm_crc2);
|
||||
|
||||
/*
|
||||
* k5
|
||||
*/
|
||||
crc_fold = Vector128.Create(crc_k[4], crc_k[5], crc_k[6], crc_k[7]);
|
||||
|
||||
xmm_crc0 = xmm_crc3;
|
||||
xmm_crc3 = Pclmulqdq.CarrylessMultiply(xmm_crc3.AsUInt64(), crc_fold.AsUInt64(), 0).AsUInt32();
|
||||
xmm_crc0 = Sse2.ShiftRightLogical128BitLane(xmm_crc0, 8);
|
||||
xmm_crc3 = Sse2.Xor(xmm_crc3, xmm_crc0);
|
||||
|
||||
xmm_crc0 = xmm_crc3;
|
||||
xmm_crc3 = Sse2.ShiftLeftLogical128BitLane(xmm_crc3, 4);
|
||||
xmm_crc3 = Pclmulqdq.CarrylessMultiply(xmm_crc3.AsUInt64(), crc_fold.AsUInt64(), 0x10).AsUInt32();
|
||||
xmm_crc3 = Sse2.Xor(xmm_crc3, xmm_crc0);
|
||||
xmm_crc3 = Sse2.And(xmm_crc3, xmm_mask2);
|
||||
|
||||
/*
|
||||
* k7
|
||||
*/
|
||||
xmm_crc1 = xmm_crc3;
|
||||
xmm_crc2 = xmm_crc3;
|
||||
crc_fold = Vector128.Create(crc_k[8], crc_k[9], crc_k[10], crc_k[11]);
|
||||
|
||||
xmm_crc3 = Pclmulqdq.CarrylessMultiply(xmm_crc3.AsUInt64(), crc_fold.AsUInt64(), 0).AsUInt32();
|
||||
xmm_crc3 = Sse2.Xor(xmm_crc3, xmm_crc2);
|
||||
xmm_crc3 = Sse2.And(xmm_crc3, xmm_mask);
|
||||
|
||||
xmm_crc2 = xmm_crc3;
|
||||
xmm_crc3 = Pclmulqdq.CarrylessMultiply(xmm_crc3.AsUInt64(), crc_fold.AsUInt64(), 0x10).AsUInt32();
|
||||
xmm_crc3 = Sse2.Xor(xmm_crc3, xmm_crc2);
|
||||
xmm_crc3 = Sse2.Xor(xmm_crc3, xmm_crc1);
|
||||
|
||||
/*
|
||||
* could just as well write xmm_crc3[2], doing a movaps and truncating, but
|
||||
* no real advantage - it's a tiny bit slower per call, while no additional CPUs
|
||||
* would be supported by only requiring SSSE3 and CLMUL instead of SSE4.1 + CLMUL
|
||||
*/
|
||||
crc = Sse41.Extract(xmm_crc3, 2);
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ using System.Runtime.Intrinsics.X86;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Helpers;
|
||||
using Aaru6.Checksums.CRC32;
|
||||
|
||||
namespace Aaru6.Checksums
|
||||
{
|
||||
@@ -332,6 +333,7 @@ namespace Aaru6.Checksums
|
||||
|
||||
readonly uint _finalSeed;
|
||||
readonly uint[][] _table;
|
||||
readonly bool _useIso;
|
||||
uint _hashInt;
|
||||
|
||||
/// <summary>Initializes the CRC32 table and seed as CRC32-ISO</summary>
|
||||
@@ -339,8 +341,8 @@ namespace Aaru6.Checksums
|
||||
{
|
||||
_hashInt = CRC32_ISO_SEED;
|
||||
_finalSeed = CRC32_ISO_SEED;
|
||||
|
||||
_table = _isoCrc32Table;
|
||||
_useIso = true;
|
||||
}
|
||||
|
||||
/// <summary>Initializes the CRC32 table with a custom polynomial and seed</summary>
|
||||
@@ -348,74 +350,16 @@ namespace Aaru6.Checksums
|
||||
{
|
||||
_hashInt = seed;
|
||||
_finalSeed = seed;
|
||||
/*
|
||||
_table = new uint[256];
|
||||
_useIso = polynomial == CRC32_ISO_POLY && seed == CRC32_ISO_SEED;
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
uint entry = (uint)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry >>= 1;
|
||||
|
||||
_table[i] = entry;
|
||||
}*/
|
||||
_table = GenerateTable(polynomial);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
if(Pclmulqdq.IsSupported &&
|
||||
Sse41.IsSupported &&
|
||||
Ssse3.IsSupported &&
|
||||
Sse2.IsSupported)
|
||||
{
|
||||
_hashInt = ~CRC32CLMUL.crc32_clmul(data, len, ~_hashInt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Unroll according to Intel slicing by uint8_t
|
||||
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
|
||||
// http://sourceforge.net/projects/slicing-by-8/
|
||||
|
||||
uint crc;
|
||||
int current_pos = 0;
|
||||
const int unroll = 4;
|
||||
const int bytes_at_once = 8 * unroll;
|
||||
|
||||
crc = _hashInt;
|
||||
|
||||
while(len >= bytes_at_once)
|
||||
{
|
||||
int unrolling;
|
||||
|
||||
for(unrolling = 0; unrolling < unroll; unrolling++)
|
||||
{
|
||||
uint one = BitConverter.ToUInt32(data, current_pos) ^ crc;
|
||||
current_pos += 4;
|
||||
uint two = BitConverter.ToUInt32(data, current_pos);
|
||||
current_pos += 4;
|
||||
|
||||
crc = _table[0][(two >> 24) & 0xFF] ^ _table[1][(two >> 16) & 0xFF] ^ _table[2][(two >> 8) & 0xFF] ^
|
||||
_table[3][two & 0xFF] ^ _table[4][(one >> 24) & 0xFF] ^ _table[5][(one >> 16) & 0xFF] ^
|
||||
_table[6][(one >> 8) & 0xFF] ^ _table[7][one & 0xFF];
|
||||
}
|
||||
|
||||
len -= bytes_at_once;
|
||||
}
|
||||
|
||||
while(len-- != 0)
|
||||
crc = (crc >> 8) ^ _table[0][(crc & 0xFF) ^ data[current_pos++]];
|
||||
|
||||
_hashInt = crc;
|
||||
}
|
||||
public void Update(byte[] data, uint len) => Step(ref _hashInt, _table, data, len, _useIso);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
@@ -438,6 +382,79 @@ namespace Aaru6.Checksums
|
||||
return crc32Output.ToString();
|
||||
}
|
||||
|
||||
static uint[][] GenerateTable(uint polynomial)
|
||||
{
|
||||
uint[][] table = new uint[8][];
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
table[i] = new uint[256];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
uint entry = (uint)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry >>= 1;
|
||||
|
||||
table[0][i] = entry;
|
||||
}
|
||||
|
||||
for(int slice = 1; slice < 8; slice++)
|
||||
for(int i = 0; i < 256; i++)
|
||||
table[slice][i] = (table[slice - 1][i] >> 8) ^ table[0][table[slice - 1][i] & 0xFF];
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
static void Step(ref uint previousCrc, uint[][] table, byte[] data, uint len, bool useIso)
|
||||
{
|
||||
if(useIso &&
|
||||
Pclmulqdq.IsSupported &&
|
||||
Sse41.IsSupported &&
|
||||
Ssse3.IsSupported &&
|
||||
Sse2.IsSupported)
|
||||
{
|
||||
previousCrc = ~Clmul.Step(data, len, ~previousCrc);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Unroll according to Intel slicing by uint8_t
|
||||
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
|
||||
// http://sourceforge.net/projects/slicing-by-8/
|
||||
int currentPos = 0;
|
||||
const int unroll = 4;
|
||||
const int bytesAtOnce = 8 * unroll;
|
||||
uint crc = previousCrc;
|
||||
|
||||
while(len >= bytesAtOnce)
|
||||
{
|
||||
int unrolling;
|
||||
|
||||
for(unrolling = 0; unrolling < unroll; unrolling++)
|
||||
{
|
||||
uint one = BitConverter.ToUInt32(data, currentPos) ^ crc;
|
||||
currentPos += 4;
|
||||
uint two = BitConverter.ToUInt32(data, currentPos);
|
||||
currentPos += 4;
|
||||
|
||||
crc = table[0][(two >> 24) & 0xFF] ^ table[1][(two >> 16) & 0xFF] ^ table[2][(two >> 8) & 0xFF] ^
|
||||
table[3][two & 0xFF] ^ table[4][(one >> 24) & 0xFF] ^ table[5][(one >> 16) & 0xFF] ^
|
||||
table[6][(one >> 8) & 0xFF] ^ table[7][one & 0xFF];
|
||||
}
|
||||
|
||||
len -= bytesAtOnce;
|
||||
}
|
||||
|
||||
while(len-- != 0)
|
||||
crc = (crc >> 8) ^ table[0][(crc & 0xFF) ^ data[currentPos++]];
|
||||
|
||||
previousCrc = crc;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
@@ -464,24 +481,19 @@ namespace Aaru6.Checksums
|
||||
|
||||
uint localHashInt = seed;
|
||||
|
||||
uint[] localTable = new uint[256];
|
||||
uint[][] localTable = GenerateTable(polynomial);
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
byte[] buffer = new byte[65536];
|
||||
int read = fileStream.Read(buffer, 0, 65536);
|
||||
|
||||
while(read > 0)
|
||||
{
|
||||
uint entry = (uint)i;
|
||||
Step(ref localHashInt, localTable, buffer, (uint)read,
|
||||
polynomial == CRC32_ISO_POLY && seed == CRC32_ISO_SEED);
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry >>= 1;
|
||||
|
||||
localTable[i] = entry;
|
||||
read = fileStream.Read(buffer, 0, 65536);
|
||||
}
|
||||
|
||||
for(int i = 0; i < fileStream.Length; i++)
|
||||
localHashInt = (localHashInt >> 8) ^ localTable[fileStream.ReadByte() ^ (localHashInt & 0xff)];
|
||||
|
||||
localHashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
@@ -512,23 +524,9 @@ namespace Aaru6.Checksums
|
||||
{
|
||||
uint localHashInt = seed;
|
||||
|
||||
uint[] localTable = new uint[256];
|
||||
uint[][] localTable = GenerateTable(polynomial);
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
uint entry = (uint)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry >>= 1;
|
||||
|
||||
localTable[i] = entry;
|
||||
}
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
localHashInt = (localHashInt >> 8) ^ localTable[data[i] ^ (localHashInt & 0xff)];
|
||||
Step(ref localHashInt, localTable, data, len, polynomial == CRC32_ISO_POLY && seed == CRC32_ISO_SEED);
|
||||
|
||||
localHashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
142
Aaru6.Checksums/CRC64/clmul.cs
Normal file
142
Aaru6.Checksums/CRC64/clmul.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
// /***************************************************************************
|
||||
// Aaru Data Preservation Suite
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Filename : clmul.cs
|
||||
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
||||
//
|
||||
// Component : Checksums.
|
||||
//
|
||||
// --[ Description ] ----------------------------------------------------------
|
||||
//
|
||||
// Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ
|
||||
// instruction.
|
||||
//
|
||||
// --[ License ] --------------------------------------------------------------
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as
|
||||
// published by the Free Software Foundation; either version 2.1 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright © 2011-2021 Natalia Portillo
|
||||
// ****************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
namespace Aaru6.Checksums.CRC64
|
||||
{
|
||||
internal static class Clmul
|
||||
{
|
||||
static readonly byte[] _shuffleMasks =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x8f, 0x8e,
|
||||
0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80
|
||||
};
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static void ShiftRight128(Vector128<ulong> initial, uint n, out Vector128<ulong> outLeft,
|
||||
out Vector128<ulong> outRight)
|
||||
{
|
||||
uint maskPos = 16 - n;
|
||||
|
||||
Vector128<byte> maskA = Vector128.Create(_shuffleMasks[maskPos], _shuffleMasks[maskPos + 1],
|
||||
_shuffleMasks[maskPos + 2], _shuffleMasks[maskPos + 3],
|
||||
_shuffleMasks[maskPos + 4], _shuffleMasks[maskPos + 5],
|
||||
_shuffleMasks[maskPos + 6], _shuffleMasks[maskPos + 7],
|
||||
_shuffleMasks[maskPos + 8], _shuffleMasks[maskPos + 9],
|
||||
_shuffleMasks[maskPos + 10], _shuffleMasks[maskPos + 11],
|
||||
_shuffleMasks[maskPos + 12], _shuffleMasks[maskPos + 13],
|
||||
_shuffleMasks[maskPos + 14], _shuffleMasks[maskPos + 15]);
|
||||
|
||||
Vector128<byte> maskB = Sse2.Xor(maskA, Sse2.CompareEqual(Vector128<byte>.Zero, Vector128<byte>.Zero));
|
||||
|
||||
outLeft = Ssse3.Shuffle(initial.AsByte(), maskB).AsUInt64();
|
||||
outRight = Ssse3.Shuffle(initial.AsByte(), maskA).AsUInt64();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static Vector128<ulong> Fold(Vector128<ulong> input, Vector128<ulong> foldConstants) =>
|
||||
Sse2.Xor(Pclmulqdq.CarrylessMultiply(input, foldConstants, 0x00),
|
||||
Pclmulqdq.CarrylessMultiply(input, foldConstants, 0x11));
|
||||
|
||||
internal static ulong Step(ulong crc, byte[] data, uint length)
|
||||
{
|
||||
int bufPos = 16;
|
||||
const ulong k1 = 0xe05dd497ca393ae4;
|
||||
const ulong k2 = 0xdabe95afc7875f40;
|
||||
const ulong mu = 0x9c3e466c172963d5;
|
||||
const ulong pol = 0x92d8af2baf0e1e85;
|
||||
Vector128<ulong> foldConstants1 = Vector128.Create(k1, k2);
|
||||
Vector128<ulong> foldConstants2 = Vector128.Create(mu, pol);
|
||||
uint leadOutSize = length % 16;
|
||||
Vector128<ulong> initialCrc = Vector128.Create(~crc, 0);
|
||||
Vector128<ulong> p;
|
||||
length -= 16;
|
||||
|
||||
// Initial CRC can simply be added to data
|
||||
ShiftRight128(initialCrc, 0, out Vector128<ulong> crc0, out Vector128<ulong> crc1);
|
||||
|
||||
Vector128<ulong> accumulator =
|
||||
Sse2.Xor(Fold(Sse2.Xor(crc0, Vector128.Create(BitConverter.ToUInt64(data, 0), BitConverter.ToUInt64(data, 8))), foldConstants1),
|
||||
crc1);
|
||||
|
||||
while(length >= 32)
|
||||
{
|
||||
accumulator =
|
||||
Fold(Sse2.Xor(Vector128.Create(BitConverter.ToUInt64(data, bufPos), BitConverter.ToUInt64(data, bufPos + 8)), accumulator),
|
||||
foldConstants1);
|
||||
|
||||
length -= 16;
|
||||
bufPos += 16;
|
||||
}
|
||||
|
||||
if(length == 16)
|
||||
{
|
||||
p = Sse2.Xor(accumulator,
|
||||
Vector128.Create(BitConverter.ToUInt64(data, bufPos),
|
||||
BitConverter.ToUInt64(data, bufPos + 8)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector128<ulong> end0 = Sse2.Xor(accumulator,
|
||||
Vector128.Create(BitConverter.ToUInt64(data, bufPos),
|
||||
BitConverter.ToUInt64(data, bufPos + 8)));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
Vector128<ulong> end1 =
|
||||
Vector128.Create(BitConverter.ToUInt64(data, bufPos), BitConverter.ToUInt64(data, bufPos + 8));
|
||||
|
||||
ShiftRight128(end0, leadOutSize, out Vector128<ulong> a, out Vector128<ulong> b);
|
||||
ShiftRight128(end1, leadOutSize, out Vector128<ulong> c, out _);
|
||||
|
||||
p = Sse2.Xor(Fold(a, foldConstants1), Sse2.Or(b, c));
|
||||
}
|
||||
|
||||
Vector128<ulong> r = Sse2.Xor(Pclmulqdq.CarrylessMultiply(p, foldConstants1, 0x10),
|
||||
Sse2.ShiftRightLogical128BitLane(p, 8));
|
||||
|
||||
// Final Barrett reduction
|
||||
Vector128<ulong> t1 = Pclmulqdq.CarrylessMultiply(r, foldConstants2, 0x00);
|
||||
|
||||
Vector128<ulong> t2 =
|
||||
Sse2.Xor(Sse2.Xor(Pclmulqdq.CarrylessMultiply(t1, foldConstants2, 0x10), Sse2.ShiftLeftLogical128BitLane(t1, 8)),
|
||||
r);
|
||||
|
||||
return ~(((ulong)Sse41.Extract(t2.AsUInt32(), 3) << 32) | Sse41.Extract(t2.AsUInt32(), 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
namespace Aaru6.Checksums
|
||||
{
|
||||
public class CRC64CLMUL
|
||||
{
|
||||
static readonly byte[] shuffleMasks =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x8f, 0x8e,
|
||||
0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80
|
||||
};
|
||||
|
||||
static void shiftRight128(Vector128<ulong> initial, uint n, out Vector128<ulong> outLeft,
|
||||
out Vector128<ulong> outRight)
|
||||
{
|
||||
uint maskPos = 16 - n;
|
||||
|
||||
Vector128<byte> maskA = Vector128.Create(shuffleMasks[maskPos], shuffleMasks[maskPos + 1],
|
||||
shuffleMasks[maskPos + 2], shuffleMasks[maskPos + 3],
|
||||
shuffleMasks[maskPos + 4], shuffleMasks[maskPos + 5],
|
||||
shuffleMasks[maskPos + 6], shuffleMasks[maskPos + 7],
|
||||
shuffleMasks[maskPos + 8], shuffleMasks[maskPos + 9],
|
||||
shuffleMasks[maskPos + 10], shuffleMasks[maskPos + 11],
|
||||
shuffleMasks[maskPos + 12], shuffleMasks[maskPos + 13],
|
||||
shuffleMasks[maskPos + 14], shuffleMasks[maskPos + 15]);
|
||||
|
||||
Vector128<byte> maskB = Sse2.Xor(maskA, Sse2.CompareEqual(Vector128<byte>.Zero, Vector128<byte>.Zero));
|
||||
|
||||
outLeft = Ssse3.Shuffle(initial.AsByte(), maskB).AsUInt64();
|
||||
outRight = Ssse3.Shuffle(initial.AsByte(), maskA).AsUInt64();
|
||||
}
|
||||
|
||||
static Vector128<ulong> fold(Vector128<ulong> input, Vector128<ulong> foldConstants) =>
|
||||
Sse2.Xor(Pclmulqdq.CarrylessMultiply(input, foldConstants, 0x00),
|
||||
Pclmulqdq.CarrylessMultiply(input, foldConstants, 0x11));
|
||||
|
||||
internal static ulong crc64_clmul(ulong crc, byte[] data, uint length)
|
||||
{
|
||||
int bufPos = 16;
|
||||
|
||||
const ulong k1 = 0xe05dd497ca393ae4; // bitReflect(expMod65(128 + 64, poly, 1)) << 1;
|
||||
const ulong k2 = 0xdabe95afc7875f40; // bitReflect(expMod65(128, poly, 1)) << 1;
|
||||
const ulong mu = 0x9c3e466c172963d5; // (bitReflect(div129by65(poly)) << 1) | 1;
|
||||
const ulong p = 0x92d8af2baf0e1e85; // (bitReflect(poly) << 1) | 1;
|
||||
|
||||
Vector128<ulong> foldConstants1 = Vector128.Create(k1, k2);
|
||||
Vector128<ulong> foldConstants2 = Vector128.Create(mu, p);
|
||||
|
||||
uint leadOutSize = length % 16;
|
||||
Vector128<ulong> initialCrc = Vector128.Create(~crc, 0);
|
||||
|
||||
Vector128<ulong> R;
|
||||
length -= 16;
|
||||
|
||||
// Initial CRC can simply be added to data
|
||||
shiftRight128(initialCrc, 0, out Vector128<ulong> crc0, out Vector128<ulong> crc1);
|
||||
|
||||
Vector128<ulong> accumulator =
|
||||
Sse2.Xor(fold(Sse2.Xor(crc0, Vector128.Create(BitConverter.ToUInt64(data, 0), BitConverter.ToUInt64(data, 8))), foldConstants1),
|
||||
crc1);
|
||||
|
||||
while(length >= 32)
|
||||
{
|
||||
accumulator =
|
||||
fold(Sse2.Xor(Vector128.Create(BitConverter.ToUInt64(data, bufPos), BitConverter.ToUInt64(data, bufPos + 8)), accumulator),
|
||||
foldConstants1);
|
||||
|
||||
length -= 16;
|
||||
bufPos += 16;
|
||||
}
|
||||
|
||||
Vector128<ulong> P;
|
||||
|
||||
if(length == 16)
|
||||
{
|
||||
P = Sse2.Xor(accumulator,
|
||||
Vector128.Create(BitConverter.ToUInt64(data, bufPos),
|
||||
BitConverter.ToUInt64(data, bufPos + 8)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector128<ulong> end0 = Sse2.Xor(accumulator,
|
||||
Vector128.Create(BitConverter.ToUInt64(data, bufPos),
|
||||
BitConverter.ToUInt64(data, bufPos + 8)));
|
||||
|
||||
bufPos += 16;
|
||||
|
||||
Vector128<ulong> end1 =
|
||||
Vector128.Create(BitConverter.ToUInt64(data, bufPos), BitConverter.ToUInt64(data, bufPos + 8));
|
||||
|
||||
shiftRight128(end0, leadOutSize, out Vector128<ulong> A, out Vector128<ulong> B);
|
||||
shiftRight128(end1, leadOutSize, out Vector128<ulong> C, out Vector128<ulong> D);
|
||||
|
||||
P = Sse2.Xor(fold(A, foldConstants1), Sse2.Or(B, C));
|
||||
}
|
||||
|
||||
R = Sse2.Xor(Pclmulqdq.CarrylessMultiply(P, foldConstants1, 0x10), Sse2.ShiftRightLogical128BitLane(P, 8));
|
||||
|
||||
// Final Barrett reduction
|
||||
Vector128<ulong> T1 = Pclmulqdq.CarrylessMultiply(R, foldConstants2, 0x00);
|
||||
|
||||
Vector128<ulong> T2 =
|
||||
Sse2.Xor(Sse2.Xor(Pclmulqdq.CarrylessMultiply(T1, foldConstants2, 0x10), Sse2.ShiftLeftLogical128BitLane(T1, 8)),
|
||||
R);
|
||||
|
||||
return ~(((ulong)Sse41.Extract(T2.AsUInt32(), 3) << 32) | Sse41.Extract(T2.AsUInt32(), 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,9 +32,11 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
using System.Text;
|
||||
using Aaru.CommonTypes.Interfaces;
|
||||
using Aaru.Helpers;
|
||||
using Aaru6.Checksums.CRC64;
|
||||
|
||||
namespace Aaru6.Checksums
|
||||
{
|
||||
@@ -273,80 +275,32 @@ namespace Aaru6.Checksums
|
||||
|
||||
readonly ulong _finalSeed;
|
||||
readonly ulong[][] _table;
|
||||
readonly bool _useEcma;
|
||||
ulong _hashInt;
|
||||
|
||||
/// <summary>Initializes the CRC64 table and seed as CRC64-ECMA</summary>
|
||||
public Crc64Context()
|
||||
{
|
||||
_hashInt = CRC64_ECMA_SEED;
|
||||
|
||||
_table = _ecmaCrc64Table;
|
||||
|
||||
_finalSeed = CRC64_ECMA_SEED;
|
||||
_useEcma = true;
|
||||
}
|
||||
|
||||
/// <summary>Initializes the CRC16 table with a custom polynomial and seed</summary>
|
||||
public Crc64Context(ulong polynomial, ulong seed)
|
||||
{
|
||||
_hashInt = seed;
|
||||
/*
|
||||
_table = new ulong[256];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
ulong entry = (ulong)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry >>= 1;
|
||||
|
||||
_table[i] = entry;
|
||||
}
|
||||
*/
|
||||
_table = GenerateTable(polynomial);
|
||||
_finalSeed = seed;
|
||||
_useEcma = polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
{
|
||||
_hashInt = ~CRC64CLMUL.crc64_clmul(~_hashInt, data, len);
|
||||
|
||||
return;
|
||||
|
||||
// Unroll according to Intel slicing by uint8_t
|
||||
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
|
||||
// http://sourceforge.net/projects/slicing-by-8/
|
||||
|
||||
ulong crc = _hashInt;
|
||||
int dataOff = 0;
|
||||
|
||||
if(len > 4)
|
||||
{
|
||||
long limit;
|
||||
|
||||
limit = dataOff + (len & ~(uint)3);
|
||||
len &= 3;
|
||||
|
||||
while(dataOff < limit)
|
||||
{
|
||||
uint tmp = (uint)(crc ^ BitConverter.ToUInt32(data, dataOff));
|
||||
dataOff += 4;
|
||||
|
||||
crc = _table[3][tmp & 0xFF] ^ _table[2][(tmp >> 8) & 0xFF] ^ (crc >> 32) ^
|
||||
_table[1][(tmp >> 16) & 0xFF] ^ _table[0][tmp >> 24];
|
||||
}
|
||||
}
|
||||
|
||||
while(len-- != 0)
|
||||
crc = _table[0][data[dataOff++] ^ (crc & 0xFF)] ^ (crc >> 8);
|
||||
|
||||
_hashInt = crc;
|
||||
}
|
||||
public void Update(byte[] data, uint len) => Step(ref _hashInt, _table, data, len, _useEcma);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
@@ -369,6 +323,74 @@ namespace Aaru6.Checksums
|
||||
return crc64Output.ToString();
|
||||
}
|
||||
|
||||
static ulong[][] GenerateTable(ulong polynomial)
|
||||
{
|
||||
ulong[][] table = new ulong[8][];
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
table[i] = new ulong[256];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
ulong entry = (ulong)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry >>= 1;
|
||||
|
||||
table[0][i] = entry;
|
||||
}
|
||||
|
||||
for(int slice = 1; slice < 4; slice++)
|
||||
for(int i = 0; i < 256; i++)
|
||||
table[slice][i] = (table[slice - 1][i] >> 8) ^ table[0][table[slice - 1][i] & 0xFF];
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
static void Step(ref ulong previousCrc, ulong[][] table, byte[] data, uint len, bool useEcma)
|
||||
{
|
||||
if(useEcma &&
|
||||
Pclmulqdq.IsSupported &&
|
||||
Sse41.IsSupported &&
|
||||
Ssse3.IsSupported &&
|
||||
Sse2.IsSupported)
|
||||
{
|
||||
previousCrc = ~Clmul.Step(~previousCrc, data, len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Unroll according to Intel slicing by uint8_t
|
||||
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
|
||||
// http://sourceforge.net/projects/slicing-by-8/
|
||||
|
||||
ulong crc = previousCrc;
|
||||
int dataOff = 0;
|
||||
|
||||
if(len > 4)
|
||||
{
|
||||
long limit = dataOff + (len & ~(uint)3);
|
||||
len &= 3;
|
||||
|
||||
while(dataOff < limit)
|
||||
{
|
||||
uint tmp = (uint)(crc ^ BitConverter.ToUInt32(data, dataOff));
|
||||
dataOff += 4;
|
||||
|
||||
crc = table[3][tmp & 0xFF] ^ table[2][(tmp >> 8) & 0xFF] ^ (crc >> 32) ^
|
||||
table[1][(tmp >> 16) & 0xFF] ^ table[0][tmp >> 24];
|
||||
}
|
||||
}
|
||||
|
||||
while(len-- != 0)
|
||||
crc = table[0][data[dataOff++] ^ (crc & 0xFF)] ^ (crc >> 8);
|
||||
|
||||
previousCrc = crc;
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
/// <param name="filename">File path.</param>
|
||||
public static byte[] File(string filename)
|
||||
@@ -395,24 +417,19 @@ namespace Aaru6.Checksums
|
||||
|
||||
ulong localHashInt = seed;
|
||||
|
||||
ulong[] localTable = new ulong[256];
|
||||
ulong[][] localTable = GenerateTable(polynomial);
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
byte[] buffer = new byte[65536];
|
||||
int read = fileStream.Read(buffer, 0, 65536);
|
||||
|
||||
while(read > 0)
|
||||
{
|
||||
ulong entry = (ulong)i;
|
||||
Step(ref localHashInt, localTable, buffer, (uint)read,
|
||||
polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED);
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry >>= 1;
|
||||
|
||||
localTable[i] = entry;
|
||||
read = fileStream.Read(buffer, 0, 65536);
|
||||
}
|
||||
|
||||
for(int i = 0; i < fileStream.Length; i++)
|
||||
localHashInt = (localHashInt >> 8) ^ localTable[(ulong)fileStream.ReadByte() ^ (localHashInt & 0xffL)];
|
||||
|
||||
localHashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
@@ -443,23 +460,9 @@ namespace Aaru6.Checksums
|
||||
{
|
||||
ulong localHashInt = seed;
|
||||
|
||||
ulong[] localTable = new ulong[256];
|
||||
ulong[][] localTable = GenerateTable(polynomial);
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
ulong entry = (ulong)i;
|
||||
|
||||
for(int j = 0; j < 8; j++)
|
||||
if((entry & 1) == 1)
|
||||
entry = (entry >> 1) ^ polynomial;
|
||||
else
|
||||
entry >>= 1;
|
||||
|
||||
localTable[i] = entry;
|
||||
}
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
localHashInt = (localHashInt >> 8) ^ localTable[data[i] ^ (localHashInt & 0xff)];
|
||||
Step(ref localHashInt, localTable, data, len, polynomial == CRC64_ECMA_POLY && seed == CRC64_ECMA_SEED);
|
||||
|
||||
localHashInt ^= seed;
|
||||
hash = BigEndianBitConverter.GetBytes(localHashInt);
|
||||
|
||||
@@ -57,10 +57,39 @@ namespace Aaru6.Checksums
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
public void Update(byte[] data, uint len) => Step(ref _sum1, ref _sum2, data, len);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
uint sum1 = _sum1;
|
||||
uint sum2 = _sum2;
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
|
||||
return BigEndianBitConverter.GetBytes(finalSum);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
var fletcherOutput = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
|
||||
fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
|
||||
|
||||
return fletcherOutput.ToString();
|
||||
}
|
||||
|
||||
static void Step(ref ushort previousSum1, ref ushort previousSum2, byte[] data, uint len)
|
||||
{
|
||||
uint sum1 = previousSum1;
|
||||
uint sum2 = previousSum2;
|
||||
uint n;
|
||||
int dataOff = 0;
|
||||
|
||||
@@ -77,8 +106,8 @@ namespace Aaru6.Checksums
|
||||
if(sum2 >= FLETCHER_MODULE)
|
||||
sum2 -= FLETCHER_MODULE;
|
||||
|
||||
_sum1 = (ushort)(sum1 & 0xFFFF);
|
||||
_sum2 = (ushort)(sum2 & 0xFFFF);
|
||||
previousSum1 = (ushort)(sum1 & 0xFFFF);
|
||||
previousSum2 = (ushort)(sum2 & 0xFFFF);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -96,8 +125,8 @@ namespace Aaru6.Checksums
|
||||
sum1 -= FLETCHER_MODULE;
|
||||
|
||||
sum2 %= FLETCHER_MODULE; /* only added so many FLETCHER_MODULE's */
|
||||
_sum1 = (ushort)(sum1 & 0xFFFF);
|
||||
_sum2 = (ushort)(sum2 & 0xFFFF);
|
||||
previousSum1 = (ushort)(sum1 & 0xFFFF);
|
||||
previousSum2 = (ushort)(sum2 & 0xFFFF);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -204,35 +233,8 @@ namespace Aaru6.Checksums
|
||||
sum2 %= FLETCHER_MODULE;
|
||||
}
|
||||
|
||||
_sum1 = (ushort)(sum1 & 0xFFFF);
|
||||
_sum2 = (ushort)(sum2 & 0xFFFF);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
|
||||
return BigEndianBitConverter.GetBytes(finalSum);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
uint finalSum = (uint)((_sum2 << 16) | _sum1);
|
||||
var fletcherOutput = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
|
||||
fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
|
||||
|
||||
return fletcherOutput.ToString();
|
||||
previousSum1 = (ushort)(sum1 & 0xFFFF);
|
||||
previousSum2 = (ushort)(sum2 & 0xFFFF);
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
@@ -254,10 +256,14 @@ namespace Aaru6.Checksums
|
||||
ushort localSum1 = 0xFFFF;
|
||||
ushort localSum2 = 0xFFFF;
|
||||
|
||||
for(int i = 0; i < fileStream.Length; i++)
|
||||
byte[] buffer = new byte[65536];
|
||||
int read = fileStream.Read(buffer, 0, 65536);
|
||||
|
||||
while(read > 0)
|
||||
{
|
||||
localSum1 = (ushort)((localSum1 + fileStream.ReadByte()) % FLETCHER_MODULE);
|
||||
localSum2 = (ushort)((localSum2 + localSum1) % FLETCHER_MODULE);
|
||||
Step(ref localSum1, ref localSum2, buffer, (uint)read);
|
||||
|
||||
read = fileStream.Read(buffer, 0, 65536);
|
||||
}
|
||||
|
||||
uint finalSum = (uint)((localSum2 << 16) | localSum1);
|
||||
@@ -283,11 +289,7 @@ namespace Aaru6.Checksums
|
||||
ushort localSum1 = 0xFFFF;
|
||||
ushort localSum2 = 0xFFFF;
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
localSum1 = (ushort)((localSum1 + data[i]) % FLETCHER_MODULE);
|
||||
localSum2 = (ushort)((localSum2 + localSum1) % FLETCHER_MODULE);
|
||||
}
|
||||
Step(ref localSum1, ref localSum2, data, len);
|
||||
|
||||
uint finalSum = (uint)((localSum2 << 16) | localSum1);
|
||||
|
||||
@@ -326,10 +328,39 @@ namespace Aaru6.Checksums
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
/// <param name="len">Length of buffer to hash.</param>
|
||||
public void Update(byte[] data, uint len)
|
||||
public void Update(byte[] data, uint len) => Step(ref _sum1, ref _sum2, data, len);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
uint sum1 = _sum1;
|
||||
uint sum2 = _sum2;
|
||||
ushort finalSum = (ushort)((_sum2 << 8) | _sum1);
|
||||
|
||||
return BigEndianBitConverter.GetBytes(finalSum);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
ushort finalSum = (ushort)((_sum2 << 8) | _sum1);
|
||||
var fletcherOutput = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
|
||||
fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
|
||||
|
||||
return fletcherOutput.ToString();
|
||||
}
|
||||
|
||||
static void Step(ref byte previousSum1, ref byte previousSum2, byte[] data, uint len)
|
||||
{
|
||||
uint sum1 = previousSum1;
|
||||
uint sum2 = previousSum2;
|
||||
uint n;
|
||||
int dataOff = 0;
|
||||
|
||||
@@ -346,8 +377,8 @@ namespace Aaru6.Checksums
|
||||
if(sum2 >= FLETCHER_MODULE)
|
||||
sum2 -= FLETCHER_MODULE;
|
||||
|
||||
_sum1 = (byte)(sum1 & 0xFF);
|
||||
_sum2 = (byte)(sum2 & 0xFF);
|
||||
previousSum1 = (byte)(sum1 & 0xFF);
|
||||
previousSum2 = (byte)(sum2 & 0xFF);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -365,8 +396,8 @@ namespace Aaru6.Checksums
|
||||
sum1 -= FLETCHER_MODULE;
|
||||
|
||||
sum2 %= FLETCHER_MODULE; /* only added so many FLETCHER_MODULE's */
|
||||
_sum1 = (byte)(sum1 & 0xFF);
|
||||
_sum2 = (byte)(sum2 & 0xFF);
|
||||
previousSum1 = (byte)(sum1 & 0xFF);
|
||||
previousSum2 = (byte)(sum2 & 0xFF);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -453,35 +484,8 @@ namespace Aaru6.Checksums
|
||||
sum2 %= FLETCHER_MODULE;
|
||||
}
|
||||
|
||||
_sum1 = (byte)(sum1 & 0xFF);
|
||||
_sum2 = (byte)(sum2 & 0xFF);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Updates the hash with data.</summary>
|
||||
/// <param name="data">Data buffer.</param>
|
||||
public void Update(byte[] data) => Update(data, (uint)data.Length);
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a byte array of the hash value.</summary>
|
||||
public byte[] Final()
|
||||
{
|
||||
ushort finalSum = (ushort)((_sum2 << 8) | _sum1);
|
||||
|
||||
return BigEndianBitConverter.GetBytes(finalSum);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>Returns a hexadecimal representation of the hash value.</summary>
|
||||
public string End()
|
||||
{
|
||||
ushort finalSum = (ushort)((_sum2 << 8) | _sum1);
|
||||
var fletcherOutput = new StringBuilder();
|
||||
|
||||
for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++)
|
||||
fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2"));
|
||||
|
||||
return fletcherOutput.ToString();
|
||||
previousSum1 = (byte)(sum1 & 0xFF);
|
||||
previousSum2 = (byte)(sum2 & 0xFF);
|
||||
}
|
||||
|
||||
/// <summary>Gets the hash of a file</summary>
|
||||
@@ -503,10 +507,14 @@ namespace Aaru6.Checksums
|
||||
byte localSum1 = 0xFF;
|
||||
byte localSum2 = 0xFF;
|
||||
|
||||
for(int i = 0; i < fileStream.Length; i++)
|
||||
byte[] buffer = new byte[65536];
|
||||
int read = fileStream.Read(buffer, 0, 65536);
|
||||
|
||||
while(read > 0)
|
||||
{
|
||||
localSum1 = (byte)((localSum1 + fileStream.ReadByte()) % FLETCHER_MODULE);
|
||||
localSum2 = (byte)((localSum2 + localSum1) % FLETCHER_MODULE);
|
||||
Step(ref localSum1, ref localSum2, buffer, (uint)read);
|
||||
|
||||
read = fileStream.Read(buffer, 0, 65536);
|
||||
}
|
||||
|
||||
ushort finalSum = (ushort)((localSum2 << 8) | localSum1);
|
||||
@@ -532,11 +540,7 @@ namespace Aaru6.Checksums
|
||||
byte localSum1 = 0xFF;
|
||||
byte localSum2 = 0xFF;
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
localSum1 = (byte)((localSum1 + data[i]) % FLETCHER_MODULE);
|
||||
localSum2 = (byte)((localSum2 + localSum1) % FLETCHER_MODULE);
|
||||
}
|
||||
Step(ref localSum1, ref localSum2, data, len);
|
||||
|
||||
ushort finalSum = (ushort)((localSum2 << 8) | localSum1);
|
||||
|
||||
|
||||
@@ -52,528 +52,12 @@ namespace Aaru6.Checksums
|
||||
{
|
||||
const uint ROLLING_WINDOW = 7;
|
||||
const uint MIN_BLOCKSIZE = 3;
|
||||
const uint HASH_INIT = 0x27;
|
||||
const uint HASH_PRIME = 0x01000193;
|
||||
const uint HASH_INIT = 0x28021967;
|
||||
const uint NUM_BLOCKHASHES = 31;
|
||||
const uint SPAMSUM_LENGTH = 64;
|
||||
const uint FUZZY_MAX_RESULT = (2 * SPAMSUM_LENGTH) + 20;
|
||||
|
||||
// Precomputed patrial FNV hash table
|
||||
static readonly byte[][] sum_table =
|
||||
{
|
||||
new byte[]
|
||||
{
|
||||
// 0x00
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
|
||||
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21,
|
||||
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32,
|
||||
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x01
|
||||
0x13, 0x12, 0x11, 0x10, 0x17, 0x16, 0x15, 0x14, 0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c, 0x03,
|
||||
0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c, 0x33, 0x32,
|
||||
0x31, 0x30, 0x37, 0x36, 0x35, 0x34, 0x3b, 0x3a, 0x39, 0x38, 0x3f, 0x3e, 0x3d, 0x3c, 0x23, 0x22, 0x21,
|
||||
0x20, 0x27, 0x26, 0x25, 0x24, 0x2b, 0x2a, 0x29, 0x28, 0x2f, 0x2e, 0x2d, 0x2c
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x02
|
||||
0x26, 0x27, 0x24, 0x25, 0x22, 0x23, 0x20, 0x21, 0x2e, 0x2f, 0x2c, 0x2d, 0x2a, 0x2b, 0x28, 0x29, 0x36,
|
||||
0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31, 0x3e, 0x3f, 0x3c, 0x3d, 0x3a, 0x3b, 0x38, 0x39, 0x06, 0x07,
|
||||
0x04, 0x05, 0x02, 0x03, 0x00, 0x01, 0x0e, 0x0f, 0x0c, 0x0d, 0x0a, 0x0b, 0x08, 0x09, 0x16, 0x17, 0x14,
|
||||
0x15, 0x12, 0x13, 0x10, 0x11, 0x1e, 0x1f, 0x1c, 0x1d, 0x1a, 0x1b, 0x18, 0x19
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x03
|
||||
0x39, 0x38, 0x3b, 0x3a, 0x3d, 0x3c, 0x3f, 0x3e, 0x31, 0x30, 0x33, 0x32, 0x35, 0x34, 0x37, 0x36, 0x29,
|
||||
0x28, 0x2b, 0x2a, 0x2d, 0x2c, 0x2f, 0x2e, 0x21, 0x20, 0x23, 0x22, 0x25, 0x24, 0x27, 0x26, 0x19, 0x18,
|
||||
0x1b, 0x1a, 0x1d, 0x1c, 0x1f, 0x1e, 0x11, 0x10, 0x13, 0x12, 0x15, 0x14, 0x17, 0x16, 0x09, 0x08, 0x0b,
|
||||
0x0a, 0x0d, 0x0c, 0x0f, 0x0e, 0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x04
|
||||
0x0c, 0x0d, 0x0e, 0x0f, 0x08, 0x09, 0x0a, 0x0b, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x1c,
|
||||
0x1d, 0x1e, 0x1f, 0x18, 0x19, 0x1a, 0x1b, 0x14, 0x15, 0x16, 0x17, 0x10, 0x11, 0x12, 0x13, 0x2c, 0x2d,
|
||||
0x2e, 0x2f, 0x28, 0x29, 0x2a, 0x2b, 0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23, 0x3c, 0x3d, 0x3e,
|
||||
0x3f, 0x38, 0x39, 0x3a, 0x3b, 0x34, 0x35, 0x36, 0x37, 0x30, 0x31, 0x32, 0x33
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x05
|
||||
0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
|
||||
0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x3f, 0x3e,
|
||||
0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d,
|
||||
0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x06
|
||||
0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35, 0x3a, 0x3b, 0x38, 0x39, 0x3e, 0x3f, 0x3c, 0x3d, 0x22,
|
||||
0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25, 0x2a, 0x2b, 0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d, 0x12, 0x13,
|
||||
0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x1a, 0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d, 0x02, 0x03, 0x00,
|
||||
0x01, 0x06, 0x07, 0x04, 0x05, 0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x07
|
||||
0x05, 0x04, 0x07, 0x06, 0x01, 0x00, 0x03, 0x02, 0x0d, 0x0c, 0x0f, 0x0e, 0x09, 0x08, 0x0b, 0x0a, 0x15,
|
||||
0x14, 0x17, 0x16, 0x11, 0x10, 0x13, 0x12, 0x1d, 0x1c, 0x1f, 0x1e, 0x19, 0x18, 0x1b, 0x1a, 0x25, 0x24,
|
||||
0x27, 0x26, 0x21, 0x20, 0x23, 0x22, 0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a, 0x35, 0x34, 0x37,
|
||||
0x36, 0x31, 0x30, 0x33, 0x32, 0x3d, 0x3c, 0x3f, 0x3e, 0x39, 0x38, 0x3b, 0x3a
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x08
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x08,
|
||||
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x38, 0x39,
|
||||
0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x28, 0x29, 0x2a,
|
||||
0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x09
|
||||
0x2b, 0x2a, 0x29, 0x28, 0x2f, 0x2e, 0x2d, 0x2c, 0x23, 0x22, 0x21, 0x20, 0x27, 0x26, 0x25, 0x24, 0x3b,
|
||||
0x3a, 0x39, 0x38, 0x3f, 0x3e, 0x3d, 0x3c, 0x33, 0x32, 0x31, 0x30, 0x37, 0x36, 0x35, 0x34, 0x0b, 0x0a,
|
||||
0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c, 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x1b, 0x1a, 0x19,
|
||||
0x18, 0x1f, 0x1e, 0x1d, 0x1c, 0x13, 0x12, 0x11, 0x10, 0x17, 0x16, 0x15, 0x14
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x0a
|
||||
0x3e, 0x3f, 0x3c, 0x3d, 0x3a, 0x3b, 0x38, 0x39, 0x36, 0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31, 0x2e,
|
||||
0x2f, 0x2c, 0x2d, 0x2a, 0x2b, 0x28, 0x29, 0x26, 0x27, 0x24, 0x25, 0x22, 0x23, 0x20, 0x21, 0x1e, 0x1f,
|
||||
0x1c, 0x1d, 0x1a, 0x1b, 0x18, 0x19, 0x16, 0x17, 0x14, 0x15, 0x12, 0x13, 0x10, 0x11, 0x0e, 0x0f, 0x0c,
|
||||
0x0d, 0x0a, 0x0b, 0x08, 0x09, 0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x00, 0x01
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x0b
|
||||
0x11, 0x10, 0x13, 0x12, 0x15, 0x14, 0x17, 0x16, 0x19, 0x18, 0x1b, 0x1a, 0x1d, 0x1c, 0x1f, 0x1e, 0x01,
|
||||
0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e, 0x31, 0x30,
|
||||
0x33, 0x32, 0x35, 0x34, 0x37, 0x36, 0x39, 0x38, 0x3b, 0x3a, 0x3d, 0x3c, 0x3f, 0x3e, 0x21, 0x20, 0x23,
|
||||
0x22, 0x25, 0x24, 0x27, 0x26, 0x29, 0x28, 0x2b, 0x2a, 0x2d, 0x2c, 0x2f, 0x2e
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x0c
|
||||
0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23, 0x2c, 0x2d, 0x2e, 0x2f, 0x28, 0x29, 0x2a, 0x2b, 0x34,
|
||||
0x35, 0x36, 0x37, 0x30, 0x31, 0x32, 0x33, 0x3c, 0x3d, 0x3e, 0x3f, 0x38, 0x39, 0x3a, 0x3b, 0x04, 0x05,
|
||||
0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x0c, 0x0d, 0x0e, 0x0f, 0x08, 0x09, 0x0a, 0x0b, 0x14, 0x15, 0x16,
|
||||
0x17, 0x10, 0x11, 0x12, 0x13, 0x1c, 0x1d, 0x1e, 0x1f, 0x18, 0x19, 0x1a, 0x1b
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x0d
|
||||
0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x27,
|
||||
0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x17, 0x16,
|
||||
0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x07, 0x06, 0x05,
|
||||
0x04, 0x03, 0x02, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x0e
|
||||
0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d, 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x1a,
|
||||
0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d, 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x2a, 0x2b,
|
||||
0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d, 0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25, 0x3a, 0x3b, 0x38,
|
||||
0x39, 0x3e, 0x3f, 0x3c, 0x3d, 0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x0f
|
||||
0x1d, 0x1c, 0x1f, 0x1e, 0x19, 0x18, 0x1b, 0x1a, 0x15, 0x14, 0x17, 0x16, 0x11, 0x10, 0x13, 0x12, 0x0d,
|
||||
0x0c, 0x0f, 0x0e, 0x09, 0x08, 0x0b, 0x0a, 0x05, 0x04, 0x07, 0x06, 0x01, 0x00, 0x03, 0x02, 0x3d, 0x3c,
|
||||
0x3f, 0x3e, 0x39, 0x38, 0x3b, 0x3a, 0x35, 0x34, 0x37, 0x36, 0x31, 0x30, 0x33, 0x32, 0x2d, 0x2c, 0x2f,
|
||||
0x2e, 0x29, 0x28, 0x2b, 0x2a, 0x25, 0x24, 0x27, 0x26, 0x21, 0x20, 0x23, 0x22
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x10
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x20,
|
||||
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x10, 0x11,
|
||||
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x01, 0x02,
|
||||
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x11
|
||||
0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c, 0x13,
|
||||
0x12, 0x11, 0x10, 0x17, 0x16, 0x15, 0x14, 0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c, 0x23, 0x22,
|
||||
0x21, 0x20, 0x27, 0x26, 0x25, 0x24, 0x2b, 0x2a, 0x29, 0x28, 0x2f, 0x2e, 0x2d, 0x2c, 0x33, 0x32, 0x31,
|
||||
0x30, 0x37, 0x36, 0x35, 0x34, 0x3b, 0x3a, 0x39, 0x38, 0x3f, 0x3e, 0x3d, 0x3c
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x12
|
||||
0x16, 0x17, 0x14, 0x15, 0x12, 0x13, 0x10, 0x11, 0x1e, 0x1f, 0x1c, 0x1d, 0x1a, 0x1b, 0x18, 0x19, 0x06,
|
||||
0x07, 0x04, 0x05, 0x02, 0x03, 0x00, 0x01, 0x0e, 0x0f, 0x0c, 0x0d, 0x0a, 0x0b, 0x08, 0x09, 0x36, 0x37,
|
||||
0x34, 0x35, 0x32, 0x33, 0x30, 0x31, 0x3e, 0x3f, 0x3c, 0x3d, 0x3a, 0x3b, 0x38, 0x39, 0x26, 0x27, 0x24,
|
||||
0x25, 0x22, 0x23, 0x20, 0x21, 0x2e, 0x2f, 0x2c, 0x2d, 0x2a, 0x2b, 0x28, 0x29
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x13
|
||||
0x29, 0x28, 0x2b, 0x2a, 0x2d, 0x2c, 0x2f, 0x2e, 0x21, 0x20, 0x23, 0x22, 0x25, 0x24, 0x27, 0x26, 0x39,
|
||||
0x38, 0x3b, 0x3a, 0x3d, 0x3c, 0x3f, 0x3e, 0x31, 0x30, 0x33, 0x32, 0x35, 0x34, 0x37, 0x36, 0x09, 0x08,
|
||||
0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e, 0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x19, 0x18, 0x1b,
|
||||
0x1a, 0x1d, 0x1c, 0x1f, 0x1e, 0x11, 0x10, 0x13, 0x12, 0x15, 0x14, 0x17, 0x16
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x14
|
||||
0x3c, 0x3d, 0x3e, 0x3f, 0x38, 0x39, 0x3a, 0x3b, 0x34, 0x35, 0x36, 0x37, 0x30, 0x31, 0x32, 0x33, 0x2c,
|
||||
0x2d, 0x2e, 0x2f, 0x28, 0x29, 0x2a, 0x2b, 0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23, 0x1c, 0x1d,
|
||||
0x1e, 0x1f, 0x18, 0x19, 0x1a, 0x1b, 0x14, 0x15, 0x16, 0x17, 0x10, 0x11, 0x12, 0x13, 0x0c, 0x0d, 0x0e,
|
||||
0x0f, 0x08, 0x09, 0x0a, 0x0b, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x15
|
||||
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x1f,
|
||||
0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x2f, 0x2e,
|
||||
0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x3f, 0x3e, 0x3d,
|
||||
0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x16
|
||||
0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25, 0x2a, 0x2b, 0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d, 0x32,
|
||||
0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35, 0x3a, 0x3b, 0x38, 0x39, 0x3e, 0x3f, 0x3c, 0x3d, 0x02, 0x03,
|
||||
0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d, 0x12, 0x13, 0x10,
|
||||
0x11, 0x16, 0x17, 0x14, 0x15, 0x1a, 0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x17
|
||||
0x35, 0x34, 0x37, 0x36, 0x31, 0x30, 0x33, 0x32, 0x3d, 0x3c, 0x3f, 0x3e, 0x39, 0x38, 0x3b, 0x3a, 0x25,
|
||||
0x24, 0x27, 0x26, 0x21, 0x20, 0x23, 0x22, 0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a, 0x15, 0x14,
|
||||
0x17, 0x16, 0x11, 0x10, 0x13, 0x12, 0x1d, 0x1c, 0x1f, 0x1e, 0x19, 0x18, 0x1b, 0x1a, 0x05, 0x04, 0x07,
|
||||
0x06, 0x01, 0x00, 0x03, 0x02, 0x0d, 0x0c, 0x0f, 0x0e, 0x09, 0x08, 0x0b, 0x0a
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x18
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x18,
|
||||
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x28, 0x29,
|
||||
0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x38, 0x39, 0x3a,
|
||||
0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x19
|
||||
0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c, 0x13, 0x12, 0x11, 0x10, 0x17, 0x16, 0x15, 0x14, 0x0b,
|
||||
0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c, 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x3b, 0x3a,
|
||||
0x39, 0x38, 0x3f, 0x3e, 0x3d, 0x3c, 0x33, 0x32, 0x31, 0x30, 0x37, 0x36, 0x35, 0x34, 0x2b, 0x2a, 0x29,
|
||||
0x28, 0x2f, 0x2e, 0x2d, 0x2c, 0x23, 0x22, 0x21, 0x20, 0x27, 0x26, 0x25, 0x24
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x1a
|
||||
0x2e, 0x2f, 0x2c, 0x2d, 0x2a, 0x2b, 0x28, 0x29, 0x26, 0x27, 0x24, 0x25, 0x22, 0x23, 0x20, 0x21, 0x3e,
|
||||
0x3f, 0x3c, 0x3d, 0x3a, 0x3b, 0x38, 0x39, 0x36, 0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31, 0x0e, 0x0f,
|
||||
0x0c, 0x0d, 0x0a, 0x0b, 0x08, 0x09, 0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x00, 0x01, 0x1e, 0x1f, 0x1c,
|
||||
0x1d, 0x1a, 0x1b, 0x18, 0x19, 0x16, 0x17, 0x14, 0x15, 0x12, 0x13, 0x10, 0x11
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x1b
|
||||
0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e, 0x11,
|
||||
0x10, 0x13, 0x12, 0x15, 0x14, 0x17, 0x16, 0x19, 0x18, 0x1b, 0x1a, 0x1d, 0x1c, 0x1f, 0x1e, 0x21, 0x20,
|
||||
0x23, 0x22, 0x25, 0x24, 0x27, 0x26, 0x29, 0x28, 0x2b, 0x2a, 0x2d, 0x2c, 0x2f, 0x2e, 0x31, 0x30, 0x33,
|
||||
0x32, 0x35, 0x34, 0x37, 0x36, 0x39, 0x38, 0x3b, 0x3a, 0x3d, 0x3c, 0x3f, 0x3e
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x1c
|
||||
0x14, 0x15, 0x16, 0x17, 0x10, 0x11, 0x12, 0x13, 0x1c, 0x1d, 0x1e, 0x1f, 0x18, 0x19, 0x1a, 0x1b, 0x04,
|
||||
0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x0c, 0x0d, 0x0e, 0x0f, 0x08, 0x09, 0x0a, 0x0b, 0x34, 0x35,
|
||||
0x36, 0x37, 0x30, 0x31, 0x32, 0x33, 0x3c, 0x3d, 0x3e, 0x3f, 0x38, 0x39, 0x3a, 0x3b, 0x24, 0x25, 0x26,
|
||||
0x27, 0x20, 0x21, 0x22, 0x23, 0x2c, 0x2d, 0x2e, 0x2f, 0x28, 0x29, 0x2a, 0x2b
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x1d
|
||||
0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x37,
|
||||
0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x07, 0x06,
|
||||
0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x17, 0x16, 0x15,
|
||||
0x14, 0x13, 0x12, 0x11, 0x10, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x1e
|
||||
0x3a, 0x3b, 0x38, 0x39, 0x3e, 0x3f, 0x3c, 0x3d, 0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35, 0x2a,
|
||||
0x2b, 0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d, 0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25, 0x1a, 0x1b,
|
||||
0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d, 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x0a, 0x0b, 0x08,
|
||||
0x09, 0x0e, 0x0f, 0x0c, 0x0d, 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x1f
|
||||
0x0d, 0x0c, 0x0f, 0x0e, 0x09, 0x08, 0x0b, 0x0a, 0x05, 0x04, 0x07, 0x06, 0x01, 0x00, 0x03, 0x02, 0x1d,
|
||||
0x1c, 0x1f, 0x1e, 0x19, 0x18, 0x1b, 0x1a, 0x15, 0x14, 0x17, 0x16, 0x11, 0x10, 0x13, 0x12, 0x2d, 0x2c,
|
||||
0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a, 0x25, 0x24, 0x27, 0x26, 0x21, 0x20, 0x23, 0x22, 0x3d, 0x3c, 0x3f,
|
||||
0x3e, 0x39, 0x38, 0x3b, 0x3a, 0x35, 0x34, 0x37, 0x36, 0x31, 0x30, 0x33, 0x32
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x20
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
|
||||
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x01,
|
||||
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
|
||||
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x21
|
||||
0x33, 0x32, 0x31, 0x30, 0x37, 0x36, 0x35, 0x34, 0x3b, 0x3a, 0x39, 0x38, 0x3f, 0x3e, 0x3d, 0x3c, 0x23,
|
||||
0x22, 0x21, 0x20, 0x27, 0x26, 0x25, 0x24, 0x2b, 0x2a, 0x29, 0x28, 0x2f, 0x2e, 0x2d, 0x2c, 0x13, 0x12,
|
||||
0x11, 0x10, 0x17, 0x16, 0x15, 0x14, 0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c, 0x03, 0x02, 0x01,
|
||||
0x00, 0x07, 0x06, 0x05, 0x04, 0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x22
|
||||
0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x00, 0x01, 0x0e, 0x0f, 0x0c, 0x0d, 0x0a, 0x0b, 0x08, 0x09, 0x16,
|
||||
0x17, 0x14, 0x15, 0x12, 0x13, 0x10, 0x11, 0x1e, 0x1f, 0x1c, 0x1d, 0x1a, 0x1b, 0x18, 0x19, 0x26, 0x27,
|
||||
0x24, 0x25, 0x22, 0x23, 0x20, 0x21, 0x2e, 0x2f, 0x2c, 0x2d, 0x2a, 0x2b, 0x28, 0x29, 0x36, 0x37, 0x34,
|
||||
0x35, 0x32, 0x33, 0x30, 0x31, 0x3e, 0x3f, 0x3c, 0x3d, 0x3a, 0x3b, 0x38, 0x39
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x23
|
||||
0x19, 0x18, 0x1b, 0x1a, 0x1d, 0x1c, 0x1f, 0x1e, 0x11, 0x10, 0x13, 0x12, 0x15, 0x14, 0x17, 0x16, 0x09,
|
||||
0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e, 0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x39, 0x38,
|
||||
0x3b, 0x3a, 0x3d, 0x3c, 0x3f, 0x3e, 0x31, 0x30, 0x33, 0x32, 0x35, 0x34, 0x37, 0x36, 0x29, 0x28, 0x2b,
|
||||
0x2a, 0x2d, 0x2c, 0x2f, 0x2e, 0x21, 0x20, 0x23, 0x22, 0x25, 0x24, 0x27, 0x26
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x24
|
||||
0x2c, 0x2d, 0x2e, 0x2f, 0x28, 0x29, 0x2a, 0x2b, 0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23, 0x3c,
|
||||
0x3d, 0x3e, 0x3f, 0x38, 0x39, 0x3a, 0x3b, 0x34, 0x35, 0x36, 0x37, 0x30, 0x31, 0x32, 0x33, 0x0c, 0x0d,
|
||||
0x0e, 0x0f, 0x08, 0x09, 0x0a, 0x0b, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x1c, 0x1d, 0x1e,
|
||||
0x1f, 0x18, 0x19, 0x1a, 0x1b, 0x14, 0x15, 0x16, 0x17, 0x10, 0x11, 0x12, 0x13
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x25
|
||||
0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f,
|
||||
0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
|
||||
0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d,
|
||||
0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x26
|
||||
0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x1a, 0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d, 0x02,
|
||||
0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d, 0x32, 0x33,
|
||||
0x30, 0x31, 0x36, 0x37, 0x34, 0x35, 0x3a, 0x3b, 0x38, 0x39, 0x3e, 0x3f, 0x3c, 0x3d, 0x22, 0x23, 0x20,
|
||||
0x21, 0x26, 0x27, 0x24, 0x25, 0x2a, 0x2b, 0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x27
|
||||
0x25, 0x24, 0x27, 0x26, 0x21, 0x20, 0x23, 0x22, 0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a, 0x35,
|
||||
0x34, 0x37, 0x36, 0x31, 0x30, 0x33, 0x32, 0x3d, 0x3c, 0x3f, 0x3e, 0x39, 0x38, 0x3b, 0x3a, 0x05, 0x04,
|
||||
0x07, 0x06, 0x01, 0x00, 0x03, 0x02, 0x0d, 0x0c, 0x0f, 0x0e, 0x09, 0x08, 0x0b, 0x0a, 0x15, 0x14, 0x17,
|
||||
0x16, 0x11, 0x10, 0x13, 0x12, 0x1d, 0x1c, 0x1f, 0x1e, 0x19, 0x18, 0x1b, 0x1a
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x28
|
||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x28,
|
||||
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x18, 0x19,
|
||||
0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x08, 0x09, 0x0a,
|
||||
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x29
|
||||
0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c, 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x1b,
|
||||
0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c, 0x13, 0x12, 0x11, 0x10, 0x17, 0x16, 0x15, 0x14, 0x2b, 0x2a,
|
||||
0x29, 0x28, 0x2f, 0x2e, 0x2d, 0x2c, 0x23, 0x22, 0x21, 0x20, 0x27, 0x26, 0x25, 0x24, 0x3b, 0x3a, 0x39,
|
||||
0x38, 0x3f, 0x3e, 0x3d, 0x3c, 0x33, 0x32, 0x31, 0x30, 0x37, 0x36, 0x35, 0x34
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x2a
|
||||
0x1e, 0x1f, 0x1c, 0x1d, 0x1a, 0x1b, 0x18, 0x19, 0x16, 0x17, 0x14, 0x15, 0x12, 0x13, 0x10, 0x11, 0x0e,
|
||||
0x0f, 0x0c, 0x0d, 0x0a, 0x0b, 0x08, 0x09, 0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x00, 0x01, 0x3e, 0x3f,
|
||||
0x3c, 0x3d, 0x3a, 0x3b, 0x38, 0x39, 0x36, 0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31, 0x2e, 0x2f, 0x2c,
|
||||
0x2d, 0x2a, 0x2b, 0x28, 0x29, 0x26, 0x27, 0x24, 0x25, 0x22, 0x23, 0x20, 0x21
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x2b
|
||||
0x31, 0x30, 0x33, 0x32, 0x35, 0x34, 0x37, 0x36, 0x39, 0x38, 0x3b, 0x3a, 0x3d, 0x3c, 0x3f, 0x3e, 0x21,
|
||||
0x20, 0x23, 0x22, 0x25, 0x24, 0x27, 0x26, 0x29, 0x28, 0x2b, 0x2a, 0x2d, 0x2c, 0x2f, 0x2e, 0x11, 0x10,
|
||||
0x13, 0x12, 0x15, 0x14, 0x17, 0x16, 0x19, 0x18, 0x1b, 0x1a, 0x1d, 0x1c, 0x1f, 0x1e, 0x01, 0x00, 0x03,
|
||||
0x02, 0x05, 0x04, 0x07, 0x06, 0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x2c
|
||||
0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x0c, 0x0d, 0x0e, 0x0f, 0x08, 0x09, 0x0a, 0x0b, 0x14,
|
||||
0x15, 0x16, 0x17, 0x10, 0x11, 0x12, 0x13, 0x1c, 0x1d, 0x1e, 0x1f, 0x18, 0x19, 0x1a, 0x1b, 0x24, 0x25,
|
||||
0x26, 0x27, 0x20, 0x21, 0x22, 0x23, 0x2c, 0x2d, 0x2e, 0x2f, 0x28, 0x29, 0x2a, 0x2b, 0x34, 0x35, 0x36,
|
||||
0x37, 0x30, 0x31, 0x32, 0x33, 0x3c, 0x3d, 0x3e, 0x3f, 0x38, 0x39, 0x3a, 0x3b
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x2d
|
||||
0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x07,
|
||||
0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x37, 0x36,
|
||||
0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x27, 0x26, 0x25,
|
||||
0x24, 0x23, 0x22, 0x21, 0x20, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x2e
|
||||
0x2a, 0x2b, 0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d, 0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25, 0x3a,
|
||||
0x3b, 0x38, 0x39, 0x3e, 0x3f, 0x3c, 0x3d, 0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35, 0x0a, 0x0b,
|
||||
0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d, 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x1a, 0x1b, 0x18,
|
||||
0x19, 0x1e, 0x1f, 0x1c, 0x1d, 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x2f
|
||||
0x3d, 0x3c, 0x3f, 0x3e, 0x39, 0x38, 0x3b, 0x3a, 0x35, 0x34, 0x37, 0x36, 0x31, 0x30, 0x33, 0x32, 0x2d,
|
||||
0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a, 0x25, 0x24, 0x27, 0x26, 0x21, 0x20, 0x23, 0x22, 0x1d, 0x1c,
|
||||
0x1f, 0x1e, 0x19, 0x18, 0x1b, 0x1a, 0x15, 0x14, 0x17, 0x16, 0x11, 0x10, 0x13, 0x12, 0x0d, 0x0c, 0x0f,
|
||||
0x0e, 0x09, 0x08, 0x0b, 0x0a, 0x05, 0x04, 0x07, 0x06, 0x01, 0x00, 0x03, 0x02
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x30
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00,
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x30, 0x31,
|
||||
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x20, 0x21, 0x22,
|
||||
0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x31
|
||||
0x23, 0x22, 0x21, 0x20, 0x27, 0x26, 0x25, 0x24, 0x2b, 0x2a, 0x29, 0x28, 0x2f, 0x2e, 0x2d, 0x2c, 0x33,
|
||||
0x32, 0x31, 0x30, 0x37, 0x36, 0x35, 0x34, 0x3b, 0x3a, 0x39, 0x38, 0x3f, 0x3e, 0x3d, 0x3c, 0x03, 0x02,
|
||||
0x01, 0x00, 0x07, 0x06, 0x05, 0x04, 0x0b, 0x0a, 0x09, 0x08, 0x0f, 0x0e, 0x0d, 0x0c, 0x13, 0x12, 0x11,
|
||||
0x10, 0x17, 0x16, 0x15, 0x14, 0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x32
|
||||
0x36, 0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31, 0x3e, 0x3f, 0x3c, 0x3d, 0x3a, 0x3b, 0x38, 0x39, 0x26,
|
||||
0x27, 0x24, 0x25, 0x22, 0x23, 0x20, 0x21, 0x2e, 0x2f, 0x2c, 0x2d, 0x2a, 0x2b, 0x28, 0x29, 0x16, 0x17,
|
||||
0x14, 0x15, 0x12, 0x13, 0x10, 0x11, 0x1e, 0x1f, 0x1c, 0x1d, 0x1a, 0x1b, 0x18, 0x19, 0x06, 0x07, 0x04,
|
||||
0x05, 0x02, 0x03, 0x00, 0x01, 0x0e, 0x0f, 0x0c, 0x0d, 0x0a, 0x0b, 0x08, 0x09
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x33
|
||||
0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e, 0x01, 0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x19,
|
||||
0x18, 0x1b, 0x1a, 0x1d, 0x1c, 0x1f, 0x1e, 0x11, 0x10, 0x13, 0x12, 0x15, 0x14, 0x17, 0x16, 0x29, 0x28,
|
||||
0x2b, 0x2a, 0x2d, 0x2c, 0x2f, 0x2e, 0x21, 0x20, 0x23, 0x22, 0x25, 0x24, 0x27, 0x26, 0x39, 0x38, 0x3b,
|
||||
0x3a, 0x3d, 0x3c, 0x3f, 0x3e, 0x31, 0x30, 0x33, 0x32, 0x35, 0x34, 0x37, 0x36
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x34
|
||||
0x1c, 0x1d, 0x1e, 0x1f, 0x18, 0x19, 0x1a, 0x1b, 0x14, 0x15, 0x16, 0x17, 0x10, 0x11, 0x12, 0x13, 0x0c,
|
||||
0x0d, 0x0e, 0x0f, 0x08, 0x09, 0x0a, 0x0b, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x3c, 0x3d,
|
||||
0x3e, 0x3f, 0x38, 0x39, 0x3a, 0x3b, 0x34, 0x35, 0x36, 0x37, 0x30, 0x31, 0x32, 0x33, 0x2c, 0x2d, 0x2e,
|
||||
0x2f, 0x28, 0x29, 0x2a, 0x2b, 0x24, 0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x35
|
||||
0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x3f,
|
||||
0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x0f, 0x0e,
|
||||
0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x1f, 0x1e, 0x1d,
|
||||
0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x36
|
||||
0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d, 0x12,
|
||||
0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x1a, 0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d, 0x22, 0x23,
|
||||
0x20, 0x21, 0x26, 0x27, 0x24, 0x25, 0x2a, 0x2b, 0x28, 0x29, 0x2e, 0x2f, 0x2c, 0x2d, 0x32, 0x33, 0x30,
|
||||
0x31, 0x36, 0x37, 0x34, 0x35, 0x3a, 0x3b, 0x38, 0x39, 0x3e, 0x3f, 0x3c, 0x3d
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x37
|
||||
0x15, 0x14, 0x17, 0x16, 0x11, 0x10, 0x13, 0x12, 0x1d, 0x1c, 0x1f, 0x1e, 0x19, 0x18, 0x1b, 0x1a, 0x05,
|
||||
0x04, 0x07, 0x06, 0x01, 0x00, 0x03, 0x02, 0x0d, 0x0c, 0x0f, 0x0e, 0x09, 0x08, 0x0b, 0x0a, 0x35, 0x34,
|
||||
0x37, 0x36, 0x31, 0x30, 0x33, 0x32, 0x3d, 0x3c, 0x3f, 0x3e, 0x39, 0x38, 0x3b, 0x3a, 0x25, 0x24, 0x27,
|
||||
0x26, 0x21, 0x20, 0x23, 0x22, 0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x38
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x38,
|
||||
0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x08, 0x09,
|
||||
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x18, 0x19, 0x1a,
|
||||
0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x39
|
||||
0x3b, 0x3a, 0x39, 0x38, 0x3f, 0x3e, 0x3d, 0x3c, 0x33, 0x32, 0x31, 0x30, 0x37, 0x36, 0x35, 0x34, 0x2b,
|
||||
0x2a, 0x29, 0x28, 0x2f, 0x2e, 0x2d, 0x2c, 0x23, 0x22, 0x21, 0x20, 0x27, 0x26, 0x25, 0x24, 0x1b, 0x1a,
|
||||
0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c, 0x13, 0x12, 0x11, 0x10, 0x17, 0x16, 0x15, 0x14, 0x0b, 0x0a, 0x09,
|
||||
0x08, 0x0f, 0x0e, 0x0d, 0x0c, 0x03, 0x02, 0x01, 0x00, 0x07, 0x06, 0x05, 0x04
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x3a
|
||||
0x0e, 0x0f, 0x0c, 0x0d, 0x0a, 0x0b, 0x08, 0x09, 0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x00, 0x01, 0x1e,
|
||||
0x1f, 0x1c, 0x1d, 0x1a, 0x1b, 0x18, 0x19, 0x16, 0x17, 0x14, 0x15, 0x12, 0x13, 0x10, 0x11, 0x2e, 0x2f,
|
||||
0x2c, 0x2d, 0x2a, 0x2b, 0x28, 0x29, 0x26, 0x27, 0x24, 0x25, 0x22, 0x23, 0x20, 0x21, 0x3e, 0x3f, 0x3c,
|
||||
0x3d, 0x3a, 0x3b, 0x38, 0x39, 0x36, 0x37, 0x34, 0x35, 0x32, 0x33, 0x30, 0x31
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x3b
|
||||
0x21, 0x20, 0x23, 0x22, 0x25, 0x24, 0x27, 0x26, 0x29, 0x28, 0x2b, 0x2a, 0x2d, 0x2c, 0x2f, 0x2e, 0x31,
|
||||
0x30, 0x33, 0x32, 0x35, 0x34, 0x37, 0x36, 0x39, 0x38, 0x3b, 0x3a, 0x3d, 0x3c, 0x3f, 0x3e, 0x01, 0x00,
|
||||
0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e, 0x11, 0x10, 0x13,
|
||||
0x12, 0x15, 0x14, 0x17, 0x16, 0x19, 0x18, 0x1b, 0x1a, 0x1d, 0x1c, 0x1f, 0x1e
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x3c
|
||||
0x34, 0x35, 0x36, 0x37, 0x30, 0x31, 0x32, 0x33, 0x3c, 0x3d, 0x3e, 0x3f, 0x38, 0x39, 0x3a, 0x3b, 0x24,
|
||||
0x25, 0x26, 0x27, 0x20, 0x21, 0x22, 0x23, 0x2c, 0x2d, 0x2e, 0x2f, 0x28, 0x29, 0x2a, 0x2b, 0x14, 0x15,
|
||||
0x16, 0x17, 0x10, 0x11, 0x12, 0x13, 0x1c, 0x1d, 0x1e, 0x1f, 0x18, 0x19, 0x1a, 0x1b, 0x04, 0x05, 0x06,
|
||||
0x07, 0x00, 0x01, 0x02, 0x03, 0x0c, 0x0d, 0x0e, 0x0f, 0x08, 0x09, 0x0a, 0x0b
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x3d
|
||||
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x17,
|
||||
0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x27, 0x26,
|
||||
0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x37, 0x36, 0x35,
|
||||
0x34, 0x33, 0x32, 0x31, 0x30, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x3e
|
||||
0x1a, 0x1b, 0x18, 0x19, 0x1e, 0x1f, 0x1c, 0x1d, 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x0a,
|
||||
0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d, 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05, 0x3a, 0x3b,
|
||||
0x38, 0x39, 0x3e, 0x3f, 0x3c, 0x3d, 0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35, 0x2a, 0x2b, 0x28,
|
||||
0x29, 0x2e, 0x2f, 0x2c, 0x2d, 0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25
|
||||
},
|
||||
new byte[]
|
||||
{
|
||||
// 0x3f
|
||||
0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a, 0x25, 0x24, 0x27, 0x26, 0x21, 0x20, 0x23, 0x22, 0x3d,
|
||||
0x3c, 0x3f, 0x3e, 0x39, 0x38, 0x3b, 0x3a, 0x35, 0x34, 0x37, 0x36, 0x31, 0x30, 0x33, 0x32, 0x0d, 0x0c,
|
||||
0x0f, 0x0e, 0x09, 0x08, 0x0b, 0x0a, 0x05, 0x04, 0x07, 0x06, 0x01, 0x00, 0x03, 0x02, 0x1d, 0x1c, 0x1f,
|
||||
0x1e, 0x19, 0x18, 0x1b, 0x1a, 0x15, 0x14, 0x17, 0x16, 0x11, 0x10, 0x13, 0x12
|
||||
}
|
||||
};
|
||||
|
||||
//"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
readonly byte[] _b64 =
|
||||
{
|
||||
@@ -654,7 +138,7 @@ namespace Aaru6.Checksums
|
||||
* we can cope with large blocksize values
|
||||
*/
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void roll_hash(uint c)
|
||||
void roll_hash(byte c)
|
||||
{
|
||||
_self.Roll.H2 -= _self.Roll.H1;
|
||||
_self.Roll.H2 += ROLLING_WINDOW * c;
|
||||
@@ -662,7 +146,7 @@ namespace Aaru6.Checksums
|
||||
_self.Roll.H1 += c;
|
||||
_self.Roll.H1 -= _self.Roll.Window[_self.Roll.N % ROLLING_WINDOW];
|
||||
|
||||
_self.Roll.Window[_self.Roll.N % ROLLING_WINDOW] = (byte)c;
|
||||
_self.Roll.Window[_self.Roll.N % ROLLING_WINDOW] = c;
|
||||
_self.Roll.N++;
|
||||
|
||||
/* The original spamsum AND'ed this value with 0xFFFFFFFF which
|
||||
@@ -677,7 +161,7 @@ namespace Aaru6.Checksums
|
||||
|
||||
/* A simple non-rolling hash, based on the FNV hash. */
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static uint sum_hash(uint c, uint h) => sum_table[h][c & 0x3f];
|
||||
static uint sum_hash(byte c, uint h) => (h * HASH_PRIME) ^ c;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static uint SSDEEP_BS(uint index) => MIN_BLOCKSIZE << (int)index;
|
||||
@@ -688,8 +172,8 @@ namespace Aaru6.Checksums
|
||||
if(_self.Bhend >= NUM_BLOCKHASHES)
|
||||
return;
|
||||
|
||||
/* if(_self.Bhend == 0) // assert
|
||||
throw new Exception("Assertion failed");*/
|
||||
if(_self.Bhend == 0) // assert
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
uint obh = _self.Bhend - 1;
|
||||
uint nbh = _self.Bhend;
|
||||
@@ -704,8 +188,8 @@ namespace Aaru6.Checksums
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void fuzzy_try_reduce_blockhash()
|
||||
{
|
||||
/* if(_self.Bhstart >= _self.Bhend)
|
||||
throw new Exception("Assertion failed");*/
|
||||
if(_self.Bhstart >= _self.Bhend)
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
if(_self.Bhend - _self.Bhstart < 2)
|
||||
/* Need at least two working hashes. */
|
||||
@@ -726,7 +210,7 @@ namespace Aaru6.Checksums
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void fuzzy_engine_step(uint c)
|
||||
void fuzzy_engine_step(byte c)
|
||||
{
|
||||
uint i;
|
||||
/* At each character we update the rolling hash and the normal hashes.
|
||||
@@ -792,8 +276,8 @@ namespace Aaru6.Checksums
|
||||
result = new byte[FUZZY_MAX_RESULT];
|
||||
|
||||
/* Verify that our elimination was not overeager. */
|
||||
/* if(!(bi == 0 || (ulong)SSDEEP_BS(bi) / 2 * SPAMSUM_LENGTH < _self.TotalSize))
|
||||
throw new Exception("Assertion failed");*/
|
||||
if(!(bi == 0 || (ulong)SSDEEP_BS(bi) / 2 * SPAMSUM_LENGTH < _self.TotalSize))
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
int resultOff;
|
||||
|
||||
@@ -814,9 +298,9 @@ namespace Aaru6.Checksums
|
||||
_self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2)
|
||||
--bi;
|
||||
|
||||
/* if(bi > 0 &&
|
||||
if(bi > 0 &&
|
||||
_self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2)
|
||||
throw new Exception("Assertion failed");*/
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
sb.AppendFormat("{0}:", SSDEEP_BS(bi));
|
||||
int i = Encoding.ASCII.GetBytes(sb.ToString()).Length;
|
||||
@@ -825,8 +309,8 @@ namespace Aaru6.Checksums
|
||||
/* Maybe snprintf has set errno here? */
|
||||
throw new OverflowException("The input exceeds data types.");
|
||||
|
||||
/* if(i >= remain)
|
||||
throw new Exception("Assertion failed");*/
|
||||
if(i >= remain)
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
remain -= i;
|
||||
|
||||
@@ -836,8 +320,8 @@ namespace Aaru6.Checksums
|
||||
|
||||
i = (int)_self.Bh[bi].Dlen;
|
||||
|
||||
/* if(i > remain)
|
||||
throw new Exception("Assertion failed");*/
|
||||
if(i > remain)
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
Array.Copy(_self.Bh[bi].Digest, 0, result, resultOff, i);
|
||||
resultOff += i;
|
||||
@@ -845,8 +329,8 @@ namespace Aaru6.Checksums
|
||||
|
||||
if(h != 0)
|
||||
{
|
||||
/* if(remain <= 0)
|
||||
throw new Exception("Assertion failed");*/
|
||||
if(remain <= 0)
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
result[resultOff] = _b64[_self.Bh[bi].H % 64];
|
||||
|
||||
@@ -876,8 +360,8 @@ namespace Aaru6.Checksums
|
||||
}
|
||||
}
|
||||
|
||||
/* if(remain <= 0)
|
||||
throw new Exception("Assertion failed");*/
|
||||
if(remain <= 0)
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
result[resultOff++] = 0x3A; // ':'
|
||||
--remain;
|
||||
@@ -887,8 +371,8 @@ namespace Aaru6.Checksums
|
||||
++bi;
|
||||
i = (int)_self.Bh[bi].Dlen;
|
||||
|
||||
/* if(i > remain)
|
||||
throw new Exception("Assertion failed");*/
|
||||
if(i > remain)
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
Array.Copy(_self.Bh[bi].Digest, 0, result, resultOff, i);
|
||||
resultOff += i;
|
||||
@@ -896,8 +380,8 @@ namespace Aaru6.Checksums
|
||||
|
||||
if(h != 0)
|
||||
{
|
||||
/* if(remain <= 0)
|
||||
throw new Exception("Assertion failed");*/
|
||||
if(remain <= 0)
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
h = _self.Bh[bi].Halfh;
|
||||
result[resultOff] = _b64[h % 64];
|
||||
@@ -917,8 +401,8 @@ namespace Aaru6.Checksums
|
||||
|
||||
if(i != 0)
|
||||
{
|
||||
/* if(remain <= 0)
|
||||
throw new Exception("Assertion failed");*/
|
||||
if(remain <= 0)
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
result[resultOff] = (byte)i;
|
||||
|
||||
@@ -935,11 +419,11 @@ namespace Aaru6.Checksums
|
||||
}
|
||||
else if(h != 0)
|
||||
{
|
||||
/* if(_self.Bh[bi].Dlen != 0)
|
||||
if(_self.Bh[bi].Dlen != 0)
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
if(remain <= 0)
|
||||
throw new Exception("Assertion failed");*/
|
||||
throw new Exception("Assertion failed");
|
||||
|
||||
result[resultOff++] = _b64[_self.Bh[bi].H % 64];
|
||||
/* No need to bother with FUZZY_FLAG_ELIMSEQ, because this
|
||||
|
||||
Reference in New Issue
Block a user