mirror of
https://github.com/hashcat/hashcat.git
synced 2025-07-06 06:42:35 +00:00
415 lines
12 KiB
C++
415 lines
12 KiB
C++
#include "common.h"
|
|
#include <cmath>
|
|
#include <cstdint>
|
|
|
|
namespace SSE2NEON
|
|
{
|
|
int32_t NaN = ~0;
|
|
int64_t NaN64 = ~0;
|
|
|
|
result_t validateInt64(__m128i a, int64_t i0, int64_t i1)
|
|
{
|
|
const int64_t *t = (const int64_t *) &a;
|
|
ASSERT_RETURN(t[0] == i0);
|
|
ASSERT_RETURN(t[1] == i1);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateInt64(__m64 a, int64_t i0)
|
|
{
|
|
const int64_t *t = (const int64_t *) &a;
|
|
ASSERT_RETURN(t[0] == i0);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateUInt64(__m128i a, uint64_t u0, uint64_t u1)
|
|
{
|
|
const uint64_t *t = (const uint64_t *) &a;
|
|
ASSERT_RETURN(t[0] == u0);
|
|
ASSERT_RETURN(t[1] == u1);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateUInt64(__m64 a, uint64_t u0)
|
|
{
|
|
const uint64_t *t = (const uint64_t *) &a;
|
|
ASSERT_RETURN(t[0] == u0);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateInt32(__m128i a,
|
|
int32_t i0,
|
|
int32_t i1,
|
|
int32_t i2,
|
|
int32_t i3)
|
|
{
|
|
const int32_t *t = (const int32_t *) &a;
|
|
ASSERT_RETURN(t[0] == i0);
|
|
ASSERT_RETURN(t[1] == i1);
|
|
ASSERT_RETURN(t[2] == i2);
|
|
ASSERT_RETURN(t[3] == i3);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateUInt32(__m128i a,
|
|
uint32_t u0,
|
|
uint32_t u1,
|
|
uint32_t u2,
|
|
uint32_t u3)
|
|
{
|
|
const uint32_t *t = (const uint32_t *) &a;
|
|
ASSERT_RETURN(t[0] == u0);
|
|
ASSERT_RETURN(t[1] == u1);
|
|
ASSERT_RETURN(t[2] == u2);
|
|
ASSERT_RETURN(t[3] == u3);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateUInt32(__m64 a, uint32_t u0, uint32_t u1)
|
|
{
|
|
const uint32_t *t = (const uint32_t *) &a;
|
|
ASSERT_RETURN(t[0] == u0);
|
|
ASSERT_RETURN(t[1] == u1);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateInt16(__m128i a,
|
|
int16_t i0,
|
|
int16_t i1,
|
|
int16_t i2,
|
|
int16_t i3,
|
|
int16_t i4,
|
|
int16_t i5,
|
|
int16_t i6,
|
|
int16_t i7)
|
|
{
|
|
const int16_t *t = (const int16_t *) &a;
|
|
ASSERT_RETURN(t[0] == i0);
|
|
ASSERT_RETURN(t[1] == i1);
|
|
ASSERT_RETURN(t[2] == i2);
|
|
ASSERT_RETURN(t[3] == i3);
|
|
ASSERT_RETURN(t[4] == i4);
|
|
ASSERT_RETURN(t[5] == i5);
|
|
ASSERT_RETURN(t[6] == i6);
|
|
ASSERT_RETURN(t[7] == i7);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateInt16(__m64 a, int16_t i0, int16_t i1, int16_t i2, int16_t i3)
|
|
{
|
|
const int16_t *t = (const int16_t *) &a;
|
|
ASSERT_RETURN(t[0] == i0);
|
|
ASSERT_RETURN(t[1] == i1);
|
|
ASSERT_RETURN(t[2] == i2);
|
|
ASSERT_RETURN(t[3] == i3);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateUInt16(__m128i a,
|
|
uint16_t u0,
|
|
uint16_t u1,
|
|
uint16_t u2,
|
|
uint16_t u3,
|
|
uint16_t u4,
|
|
uint16_t u5,
|
|
uint16_t u6,
|
|
uint16_t u7)
|
|
{
|
|
const uint16_t *t = (const uint16_t *) &a;
|
|
ASSERT_RETURN(t[0] == u0);
|
|
ASSERT_RETURN(t[1] == u1);
|
|
ASSERT_RETURN(t[2] == u2);
|
|
ASSERT_RETURN(t[3] == u3);
|
|
ASSERT_RETURN(t[4] == u4);
|
|
ASSERT_RETURN(t[5] == u5);
|
|
ASSERT_RETURN(t[6] == u6);
|
|
ASSERT_RETURN(t[7] == u7);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateInt32(__m64 a, int32_t u0, int32_t u1)
|
|
{
|
|
const int32_t *t = (const int32_t *) &a;
|
|
ASSERT_RETURN(t[0] == u0);
|
|
ASSERT_RETURN(t[1] == u1);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateUInt16(__m64 a,
|
|
uint16_t u0,
|
|
uint16_t u1,
|
|
uint16_t u2,
|
|
uint16_t u3)
|
|
{
|
|
const uint16_t *t = (const uint16_t *) &a;
|
|
ASSERT_RETURN(t[0] == u0);
|
|
ASSERT_RETURN(t[1] == u1);
|
|
ASSERT_RETURN(t[2] == u2);
|
|
ASSERT_RETURN(t[3] == u3);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateInt8(__m128i a,
|
|
int8_t i0,
|
|
int8_t i1,
|
|
int8_t i2,
|
|
int8_t i3,
|
|
int8_t i4,
|
|
int8_t i5,
|
|
int8_t i6,
|
|
int8_t i7,
|
|
int8_t i8,
|
|
int8_t i9,
|
|
int8_t i10,
|
|
int8_t i11,
|
|
int8_t i12,
|
|
int8_t i13,
|
|
int8_t i14,
|
|
int8_t i15)
|
|
{
|
|
const int8_t *t = (const int8_t *) &a;
|
|
ASSERT_RETURN(t[0] == i0);
|
|
ASSERT_RETURN(t[1] == i1);
|
|
ASSERT_RETURN(t[2] == i2);
|
|
ASSERT_RETURN(t[3] == i3);
|
|
ASSERT_RETURN(t[4] == i4);
|
|
ASSERT_RETURN(t[5] == i5);
|
|
ASSERT_RETURN(t[6] == i6);
|
|
ASSERT_RETURN(t[7] == i7);
|
|
ASSERT_RETURN(t[8] == i8);
|
|
ASSERT_RETURN(t[9] == i9);
|
|
ASSERT_RETURN(t[10] == i10);
|
|
ASSERT_RETURN(t[11] == i11);
|
|
ASSERT_RETURN(t[12] == i12);
|
|
ASSERT_RETURN(t[13] == i13);
|
|
ASSERT_RETURN(t[14] == i14);
|
|
ASSERT_RETURN(t[15] == i15);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateInt8(__m64 a,
|
|
int8_t i0,
|
|
int8_t i1,
|
|
int8_t i2,
|
|
int8_t i3,
|
|
int8_t i4,
|
|
int8_t i5,
|
|
int8_t i6,
|
|
int8_t i7)
|
|
{
|
|
const int8_t *t = (const int8_t *) &a;
|
|
ASSERT_RETURN(t[0] == i0);
|
|
ASSERT_RETURN(t[1] == i1);
|
|
ASSERT_RETURN(t[2] == i2);
|
|
ASSERT_RETURN(t[3] == i3);
|
|
ASSERT_RETURN(t[4] == i4);
|
|
ASSERT_RETURN(t[5] == i5);
|
|
ASSERT_RETURN(t[6] == i6);
|
|
ASSERT_RETURN(t[7] == i7);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateUInt8(__m128i a,
|
|
uint8_t u0,
|
|
uint8_t u1,
|
|
uint8_t u2,
|
|
uint8_t u3,
|
|
uint8_t u4,
|
|
uint8_t u5,
|
|
uint8_t u6,
|
|
uint8_t u7,
|
|
uint8_t u8,
|
|
uint8_t u9,
|
|
uint8_t u10,
|
|
uint8_t u11,
|
|
uint8_t u12,
|
|
uint8_t u13,
|
|
uint8_t u14,
|
|
uint8_t u15)
|
|
{
|
|
const uint8_t *t = (const uint8_t *) &a;
|
|
ASSERT_RETURN(t[0] == u0);
|
|
ASSERT_RETURN(t[1] == u1);
|
|
ASSERT_RETURN(t[2] == u2);
|
|
ASSERT_RETURN(t[3] == u3);
|
|
ASSERT_RETURN(t[4] == u4);
|
|
ASSERT_RETURN(t[5] == u5);
|
|
ASSERT_RETURN(t[6] == u6);
|
|
ASSERT_RETURN(t[7] == u7);
|
|
ASSERT_RETURN(t[8] == u8);
|
|
ASSERT_RETURN(t[9] == u9);
|
|
ASSERT_RETURN(t[10] == u10);
|
|
ASSERT_RETURN(t[11] == u11);
|
|
ASSERT_RETURN(t[12] == u12);
|
|
ASSERT_RETURN(t[13] == u13);
|
|
ASSERT_RETURN(t[14] == u14);
|
|
ASSERT_RETURN(t[15] == u15);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateUInt8(__m64 a,
|
|
uint8_t u0,
|
|
uint8_t u1,
|
|
uint8_t u2,
|
|
uint8_t u3,
|
|
uint8_t u4,
|
|
uint8_t u5,
|
|
uint8_t u6,
|
|
uint8_t u7)
|
|
{
|
|
const uint8_t *t = (const uint8_t *) &a;
|
|
ASSERT_RETURN(t[0] == u0);
|
|
ASSERT_RETURN(t[1] == u1);
|
|
ASSERT_RETURN(t[2] == u2);
|
|
ASSERT_RETURN(t[3] == u3);
|
|
ASSERT_RETURN(t[4] == u4);
|
|
ASSERT_RETURN(t[5] == u5);
|
|
ASSERT_RETURN(t[6] == u6);
|
|
ASSERT_RETURN(t[7] == u7);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateSingleFloatPair(float a, float b)
|
|
{
|
|
const uint32_t *ua = (const uint32_t *) &a;
|
|
const uint32_t *ub = (const uint32_t *) &b;
|
|
// We do an integer (binary) compare rather than a
|
|
// floating point compare to take NaNs and infinities
|
|
// into account as well.
|
|
return (*ua) == (*ub) ? TEST_SUCCESS : TEST_FAIL;
|
|
}
|
|
|
|
result_t validateSingleDoublePair(double a, double b)
|
|
{
|
|
const uint64_t *ua = (const uint64_t *) &a;
|
|
const uint64_t *ub = (const uint64_t *) &b;
|
|
// We do an integer (binary) compare rather than a
|
|
// floating point compare to take NaNs and infinities
|
|
// into account as well.
|
|
|
|
if (std::isnan(a) && std::isnan(b)) {
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
return (*ua) == (*ub) ? TEST_SUCCESS : TEST_FAIL;
|
|
}
|
|
|
|
result_t validateFloat(__m128 a, float f0, float f1, float f2, float f3)
|
|
{
|
|
const float *t = (const float *) &a;
|
|
ASSERT_RETURN(validateSingleFloatPair(t[0], f0));
|
|
ASSERT_RETURN(validateSingleFloatPair(t[1], f1));
|
|
ASSERT_RETURN(validateSingleFloatPair(t[2], f2));
|
|
ASSERT_RETURN(validateSingleFloatPair(t[3], f3));
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateFloatEpsilon(__m128 a,
|
|
float f0,
|
|
float f1,
|
|
float f2,
|
|
float f3,
|
|
float epsilon)
|
|
{
|
|
const float *t = (const float *) &a;
|
|
float df0 = fabsf(t[0] - f0);
|
|
float df1 = fabsf(t[1] - f1);
|
|
float df2 = fabsf(t[2] - f2);
|
|
float df3 = fabsf(t[3] - f3);
|
|
|
|
// Due to floating-point error, subtracting floating-point number with NaN
|
|
// and zero value usually produces erroneous result. Therefore, we directly
|
|
// define the difference of two floating-point numbers to zero if both
|
|
// numbers are NaN or zero.
|
|
if ((std::isnan(t[0]) && std::isnan(f0)) || (t[0] == 0 && f0 == 0)) {
|
|
df0 = 0;
|
|
}
|
|
|
|
if ((std::isnan(t[1]) && std::isnan(f1)) || (t[1] == 0 && f1 == 0)) {
|
|
df1 = 0;
|
|
}
|
|
|
|
if ((std::isnan(t[2]) && std::isnan(f2)) || (t[2] == 0 && f2 == 0)) {
|
|
df2 = 0;
|
|
}
|
|
|
|
if ((std::isnan(t[3]) && std::isnan(f3)) || (t[3] == 0 && f3 == 0)) {
|
|
df3 = 0;
|
|
}
|
|
|
|
ASSERT_RETURN(df0 < epsilon);
|
|
ASSERT_RETURN(df1 < epsilon);
|
|
ASSERT_RETURN(df2 < epsilon);
|
|
ASSERT_RETURN(df3 < epsilon);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateFloatError(__m128 a,
|
|
float f0,
|
|
float f1,
|
|
float f2,
|
|
float f3,
|
|
float err)
|
|
{
|
|
const float *t = (const float *) &a;
|
|
float df0 = fabsf((t[0] - f0) / f0);
|
|
float df1 = fabsf((t[1] - f1) / f1);
|
|
float df2 = fabsf((t[2] - f2) / f2);
|
|
float df3 = fabsf((t[3] - f3) / f3);
|
|
|
|
if ((std::isnan(t[0]) && std::isnan(f0)) || (t[0] == 0 && f0 == 0) ||
|
|
(std::isinf(t[0]) && std::isinf(f0))) {
|
|
df0 = 0;
|
|
}
|
|
|
|
if ((std::isnan(t[1]) && std::isnan(f1)) || (t[1] == 0 && f1 == 0) ||
|
|
(std::isinf(t[1]) && std::isinf(f1))) {
|
|
df1 = 0;
|
|
}
|
|
|
|
if ((std::isnan(t[2]) && std::isnan(f2)) || (t[2] == 0 && f2 == 0) ||
|
|
(std::isinf(t[2]) && std::isinf(f2))) {
|
|
df2 = 0;
|
|
}
|
|
|
|
if ((std::isnan(t[3]) && std::isnan(f3)) || (t[3] == 0 && f3 == 0) ||
|
|
(std::isinf(t[3]) && std::isinf(f3))) {
|
|
df3 = 0;
|
|
}
|
|
|
|
ASSERT_RETURN(df0 < err);
|
|
ASSERT_RETURN(df1 < err);
|
|
ASSERT_RETURN(df2 < err);
|
|
ASSERT_RETURN(df3 < err);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateDouble(__m128d a, double d0, double d1)
|
|
{
|
|
const double *t = (const double *) &a;
|
|
ASSERT_RETURN(validateSingleDoublePair(t[0], d0));
|
|
ASSERT_RETURN(validateSingleDoublePair(t[1], d1));
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
result_t validateFloatError(__m128d a, double d0, double d1, double err)
|
|
{
|
|
const double *t = (const double *) &a;
|
|
double td0 = fabs((t[0] - d0) / d0);
|
|
double td1 = fabs((t[1] - d1) / d1);
|
|
|
|
if (std::isnan(t[0]) && std::isnan(d0)) {
|
|
td0 = 0;
|
|
}
|
|
|
|
if (std::isnan(t[1]) && std::isnan(d1)) {
|
|
td1 = 0;
|
|
}
|
|
|
|
ASSERT_RETURN(td0 < err);
|
|
ASSERT_RETURN(td1 < err);
|
|
return TEST_SUCCESS;
|
|
}
|
|
|
|
} // namespace SSE2NEON
|