Doc fixes

This commit is contained in:
Christopher Taylor 2017-05-28 13:50:32 -07:00
parent 179d8d5284
commit d31d7c85bf
8 changed files with 86 additions and 54 deletions

View File

@ -38,12 +38,6 @@ namespace leopard { namespace ff16 {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Datatypes and Constants // Datatypes and Constants
// Modulus for field operations
static const ffe_t kModulus = 65535;
// LFSR Polynomial that generates the field elements
static const unsigned kPolynomial = 0x1002D;
// Basis used for generating logarithm tables // Basis used for generating logarithm tables
static const ffe_t kCantorBasis[kBits] = { static const ffe_t kCantorBasis[kBits] = {
0x0001, 0xACCA, 0x3C0E, 0x163E, 0x0001, 0xACCA, 0x3C0E, 0x163E,
@ -634,7 +628,7 @@ void Encode(
{ {
// work <- data // work <- data
// FIXME: Unroll first loop to eliminate this // TBD: Unroll first loop to eliminate this
for (unsigned i = 0; i < m; ++i) for (unsigned i = 0; i < m; ++i)
memcpy(work[i], data[i], buffer_bytes); memcpy(work[i], data[i], buffer_bytes);
@ -665,7 +659,7 @@ void Encode(
void** temp = work + m; void** temp = work + m;
// FIXME: Unroll first loop to eliminate this // TBD: Unroll first loop to eliminate this
for (unsigned j = 0; j < m; ++j) for (unsigned j = 0; j < m; ++j)
memcpy(temp[j], data[j], buffer_bytes); memcpy(temp[j], data[j], buffer_bytes);
@ -692,7 +686,7 @@ void Encode(
// work <- work XOR temp // work <- work XOR temp
// FIXME: Unroll last loop to eliminate this // TBD: Unroll last loop to eliminate this
for (unsigned j = 0; j < m; ++j) for (unsigned j = 0; j < m; ++j)
xor_mem(work[j], temp[j], buffer_bytes); xor_mem(work[j], temp[j], buffer_bytes);
} }
@ -737,7 +731,7 @@ void Encode(
// work <- work XOR temp // work <- work XOR temp
// FIXME: Unroll last loop to eliminate this // TBD: Unroll last loop to eliminate this
for (unsigned j = 0; j < m; ++j) for (unsigned j = 0; j < m; ++j)
xor_mem(work[j], temp[j], buffer_bytes); xor_mem(work[j], temp[j], buffer_bytes);
} }

View File

@ -54,6 +54,12 @@ static const unsigned kBits = 16;
// Finite field order: Number of elements in the field // Finite field order: Number of elements in the field
static const unsigned kOrder = 65536; static const unsigned kOrder = 65536;
// Modulus for field operations
static const ffe_t kModulus = 65535;
// LFSR Polynomial that generates the field elements
static const unsigned kPolynomial = 0x1002D;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Fast Walsh-Hadamard Transform (FWHT) (mod kModulus) // Fast Walsh-Hadamard Transform (FWHT) (mod kModulus)

View File

@ -38,18 +38,12 @@ namespace leopard { namespace ff8 {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Datatypes and Constants // Datatypes and Constants
// Modulus for field operations
static const ffe_t kModulus = 255;
// LFSR Polynomial that generates the field elements
static const unsigned kPolynomial = 0x11D;
// Basis used for generating logarithm tables // Basis used for generating logarithm tables
static const ffe_t kCantorBasis[kBits] = { static const ffe_t kCantorBasis[kBits] = {
1, 214, 152, 146, 86, 200, 88, 230 1, 214, 152, 146, 86, 200, 88, 230
}; };
// Using the Cantor basis here enables us to avoid a lot of extra calculations // Using the Cantor basis {2} here enables us to avoid a lot of extra calculations
// when applying the formal derivative in decoding. // when applying the formal derivative in decoding.
@ -59,7 +53,7 @@ static const ffe_t kCantorBasis[kBits] = {
// z = x + y (mod kModulus) // z = x + y (mod kModulus)
static inline ffe_t AddMod(const ffe_t a, const ffe_t b) static inline ffe_t AddMod(const ffe_t a, const ffe_t b)
{ {
const unsigned sum = (unsigned)a + b; const unsigned sum = static_cast<unsigned>(a) + b;
// Partial reduction step, allowing for kModulus to be returned // Partial reduction step, allowing for kModulus to be returned
return static_cast<ffe_t>(sum + (sum >> kBits)); return static_cast<ffe_t>(sum + (sum >> kBits));
@ -68,7 +62,7 @@ static inline ffe_t AddMod(const ffe_t a, const ffe_t b)
// z = x - y (mod kModulus) // z = x - y (mod kModulus)
static inline ffe_t SubMod(const ffe_t a, const ffe_t b) static inline ffe_t SubMod(const ffe_t a, const ffe_t b)
{ {
const unsigned dif = (unsigned)a - b; const unsigned dif = static_cast<unsigned>(a) - b;
// Partial reduction step, allowing for kModulus to be returned // Partial reduction step, allowing for kModulus to be returned
return static_cast<ffe_t>(dif + (dif >> kBits)); return static_cast<ffe_t>(dif + (dif >> kBits));
@ -123,7 +117,7 @@ static LEO_FORCE_INLINE void FWHT_4(ffe_t* data, unsigned s)
data[y] = t3; data[y] = t3;
} }
static inline void FWHT_8(ffe_t* data) static void FWHT_8(ffe_t* data)
{ {
ffe_t t0 = data[0]; ffe_t t0 = data[0];
ffe_t t1 = data[1]; ffe_t t1 = data[1];
@ -156,9 +150,9 @@ static inline void FWHT_8(ffe_t* data)
} }
// Decimation in time (DIT) version // Decimation in time (DIT) version
static void FWHT(ffe_t* data, const unsigned ldn) static void FWHT(ffe_t* data, const unsigned bits)
{ {
const unsigned n = (1UL << ldn); const unsigned n = (1UL << bits);
if (n <= 2) if (n <= 2)
{ {
@ -167,16 +161,16 @@ static void FWHT(ffe_t* data, const unsigned ldn)
return; return;
} }
for (unsigned ldm = ldn; ldm > 3; ldm -= 2) for (unsigned i = bits; i > 3; i -= 2)
{ {
unsigned m = (1UL << ldm); unsigned m = (1UL << i);
unsigned m4 = (m >> 2); unsigned m4 = (m >> 2);
for (unsigned r = 0; r < n; r += m) for (unsigned r = 0; r < n; r += m)
for (unsigned j = 0; j < m4; j++) for (unsigned j = 0; j < m4; j++)
FWHT_4(data + j + r, m4); FWHT_4(data + j + r, m4);
} }
if (ldn & 1) if (bits & 1)
{ {
for (unsigned i0 = 0; i0 < n; i0 += 8) for (unsigned i0 = 0; i0 < n; i0 += 8)
FWHT_8(data + i0); FWHT_8(data + i0);
@ -231,7 +225,7 @@ static void InitializeLogarithmTables()
} }
ExpLUT[0] = kModulus; ExpLUT[0] = kModulus;
// Conversion to Cantor basis: // Conversion to Cantor basis {2}:
LogLUT[0] = 0; LogLUT[0] = 0;
for (unsigned i = 0; i < kBits; ++i) for (unsigned i = 0; i < kBits; ++i)
@ -246,9 +240,12 @@ static void InitializeLogarithmTables()
for (unsigned i = 0; i < kOrder; ++i) for (unsigned i = 0; i < kOrder; ++i)
LogLUT[i] = ExpLUT[LogLUT[i]]; LogLUT[i] = ExpLUT[LogLUT[i]];
// Generate Exp table from Log table:
for (unsigned i = 0; i < kOrder; ++i) for (unsigned i = 0; i < kOrder; ++i)
ExpLUT[LogLUT[i]] = i; ExpLUT[LogLUT[i]] = i;
// Note: Handles modulus wrap around with LUT
ExpLUT[kModulus] = ExpLUT[0]; ExpLUT[kModulus] = ExpLUT[0];
} }
@ -271,6 +268,14 @@ struct {
// Returns a * Log(b) // Returns a * Log(b)
static ffe_t MultiplyLog(ffe_t a, ffe_t log_b) static ffe_t MultiplyLog(ffe_t a, ffe_t log_b)
{ {
/*
Note that this operation is not a normal multiplication in a finite
field because the right operand is already a logarithm. This is done
because it moves K table lookups from the Decode() method into the
initialization step that is less performance critical. The LogWalsh[]
table below contains precalculated logarithms so it is easier to do
all the other multiplies in that form as well.
*/
if (a == 0) if (a == 0)
return 0; return 0;
return ExpLUT[AddMod(LogLUT[a], log_b)]; return ExpLUT[AddMod(LogLUT[a], log_b)];
@ -737,6 +742,8 @@ static void FFTInitialize()
{ {
ffe_t temp[kBits - 1]; ffe_t temp[kBits - 1];
// Generate FFT skew vector {1}:
for (unsigned i = 1; i < kBits; ++i) for (unsigned i = 1; i < kBits; ++i)
temp[i - 1] = static_cast<ffe_t>(1UL << i); temp[i - 1] = static_cast<ffe_t>(1UL << i);
@ -779,9 +786,9 @@ void VectorFFTButterfly(
unsigned count, unsigned count,
void** x, void** x,
void** y, void** y,
const ffe_t skew) const ffe_t log_m)
{ {
if (skew == kModulus) if (log_m == kModulus)
{ {
VectorXOR(bytes, count, y, x); VectorXOR(bytes, count, y, x);
return; return;
@ -795,14 +802,14 @@ void VectorFFTButterfly(
x[1], y[1], x[1], y[1],
x[2], y[2], x[2], y[2],
x[3], y[3], x[3], y[3],
skew, bytes); log_m, bytes);
x += 4, y += 4; x += 4, y += 4;
count -= 4; count -= 4;
} }
#endif // LEO_USE_VECTOR4_OPT #endif // LEO_USE_VECTOR4_OPT
for (unsigned i = 0; i < count; ++i) for (unsigned i = 0; i < count; ++i)
fft_butterfly(x[i], y[i], skew, bytes); fft_butterfly(x[i], y[i], log_m, bytes);
} }
void VectorIFFTButterfly( void VectorIFFTButterfly(
@ -810,9 +817,9 @@ void VectorIFFTButterfly(
unsigned count, unsigned count,
void** x, void** x,
void** y, void** y,
const ffe_t skew) const ffe_t log_m)
{ {
if (skew == kModulus) if (log_m == kModulus)
{ {
VectorXOR(bytes, count, y, x); VectorXOR(bytes, count, y, x);
return; return;
@ -826,14 +833,14 @@ void VectorIFFTButterfly(
x[1], y[1], x[1], y[1],
x[2], y[2], x[2], y[2],
x[3], y[3], x[3], y[3],
skew, bytes); log_m, bytes);
x += 4, y += 4; x += 4, y += 4;
count -= 4; count -= 4;
} }
#endif // LEO_USE_VECTOR4_OPT #endif // LEO_USE_VECTOR4_OPT
for (unsigned i = 0; i < count; ++i) for (unsigned i = 0; i < count; ++i)
ifft_butterfly(x[i], y[i], skew, bytes); ifft_butterfly(x[i], y[i], log_m, bytes);
} }
@ -850,7 +857,7 @@ void Encode(
{ {
// work <- data // work <- data
// FIXME: Unroll first loop to eliminate this // TBD: Unroll first loop to eliminate this
unsigned first_end = m; unsigned first_end = m;
if (original_count < m) if (original_count < m)
{ {
@ -893,7 +900,7 @@ void Encode(
data += m; data += m;
void** temp = work + m; void** temp = work + m;
// FIXME: Unroll first loop to eliminate this // TBD: Unroll first loop to eliminate this
for (unsigned j = 0; j < m; ++j) for (unsigned j = 0; j < m; ++j)
memcpy(temp[j], data[j], buffer_bytes); memcpy(temp[j], data[j], buffer_bytes);
@ -916,7 +923,7 @@ void Encode(
// work <- work XOR temp // work <- work XOR temp
// FIXME: Unroll last loop to eliminate this // TBD: Unroll last loop to eliminate this
VectorXOR( VectorXOR(
buffer_bytes, buffer_bytes,
m, m,
@ -965,7 +972,7 @@ void Encode(
// work <- work XOR temp // work <- work XOR temp
// FIXME: Unroll last loop to eliminate this // TBD: Unroll last loop to eliminate this
VectorXOR( VectorXOR(
buffer_bytes, buffer_bytes,
m, m,

View File

@ -54,6 +54,12 @@ static const unsigned kBits = 8;
// Finite field order: Number of elements in the field // Finite field order: Number of elements in the field
static const unsigned kOrder = 256; static const unsigned kOrder = 256;
// Modulus for field operations
static const ffe_t kModulus = 255;
// LFSR Polynomial that generates the field elements
static const unsigned kPolynomial = 0x11D;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Fast Walsh-Hadamard Transform (FWHT) (mod kModulus) // Fast Walsh-Hadamard Transform (FWHT) (mod kModulus)
@ -78,8 +84,9 @@ void mul_mem(
// FFT Operations // FFT Operations
/* /*
if (log_m != kModulus) Precondition: log_m != kModulus
x[] ^= exp(log(y[]) + log_m)
x[] ^= exp(log(y[]) + log_m)
y[] ^= x[] y[] ^= x[]
*/ */
void fft_butterfly( void fft_butterfly(
@ -103,9 +110,10 @@ void fft_butterfly4(
// IFFT Operations // IFFT Operations
/* /*
Precondition: log_m != kModulus
y[] ^= x[] y[] ^= x[]
if (log_m != kModulus) x[] ^= exp(log(y[]) + log_m)
x[] ^= exp(log(y[]) + log_m)
*/ */
void ifft_butterfly( void ifft_butterfly(
void * LEO_RESTRICT x, void * LEO_RESTRICT y, void * LEO_RESTRICT x, void * LEO_RESTRICT y,
@ -127,19 +135,29 @@ void ifft_butterfly4(
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// FFT // FFT
/*
if (log_m != kModulus)
x[] ^= exp(log(y[]) + log_m)
y[] ^= x[]
*/
void VectorFFTButterfly( void VectorFFTButterfly(
const uint64_t bytes, const uint64_t bytes,
unsigned count, unsigned count,
void** x, void** x,
void** y, void** y,
const ffe_t skew); const ffe_t log_m);
/*
y[] ^= x[]
if (log_m != kModulus)
x[] ^= exp(log(y[]) + log_m)
*/
void VectorIFFTButterfly( void VectorIFFTButterfly(
const uint64_t bytes, const uint64_t bytes,
unsigned count, unsigned count,
void** x, void** x,
void** y, void** y,
const ffe_t skew); const ffe_t log_m);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -93,6 +93,9 @@ LEO_EXPORT LeopardResult leo_encode(
if (!original_data || !work_data) if (!original_data || !work_data)
return Leopard_InvalidInput; return Leopard_InvalidInput;
if (!m_Initialized)
return Leopard_CallInitialize;
const unsigned m = leopard::NextPow2(recovery_count); const unsigned m = leopard::NextPow2(recovery_count);
const unsigned n = leopard::NextPow2(m + original_count); const unsigned n = leopard::NextPow2(m + original_count);
@ -164,6 +167,9 @@ LEO_EXPORT LeopardResult leo_decode(
if (!original_data || !recovery_data || !work_data) if (!original_data || !recovery_data || !work_data)
return Leopard_InvalidInput; return Leopard_InvalidInput;
if (!m_Initialized)
return Leopard_CallInitialize;
const unsigned m = leopard::NextPow2(recovery_count); const unsigned m = leopard::NextPow2(recovery_count);
const unsigned n = leopard::NextPow2(m + original_count); const unsigned n = leopard::NextPow2(m + original_count);

View File

@ -32,10 +32,16 @@
/* /*
Leopard-RS: Reed-Solomon Error Correction Coding for Extremely Large Data Leopard-RS: Reed-Solomon Error Correction Coding for Extremely Large Data
S.-J. Lin, T. Y. Al-Naffouri, Y. S. Han, and W.-H. Chung,
References:
{1} S.-J. Lin, T. Y. Al-Naffouri, Y. S. Han, and W.-H. Chung,
"Novel Polynomial Basis with Fast Fourier Transform and Its Application to Reed-Solomon Erasure Codes" "Novel Polynomial Basis with Fast Fourier Transform and Its Application to Reed-Solomon Erasure Codes"
IEEE Trans. on Information Theory, pp. 6284-6299, November, 2016. IEEE Trans. on Information Theory, pp. 6284-6299, November, 2016.
http://ct.ee.ntust.edu.tw/it2016-2.pdf http://ct.ee.ntust.edu.tw/it2016-2.pdf
{2} D. G. Cantor, "On arithmetical algorithms over finite fields",
Journal of Combinatorial Theory, Series A, vol. 50, no. 2, pp. 285-300, 1989.
*/ */
// Library version // Library version
@ -99,6 +105,7 @@ typedef enum LeopardResultT
Leopard_InvalidCounts = -3, // Invalid counts provided Leopard_InvalidCounts = -3, // Invalid counts provided
Leopard_InvalidInput = -4, // A function parameter was invalid Leopard_InvalidInput = -4, // A function parameter was invalid
Leopard_Platform = -5, // Platform is unsupported Leopard_Platform = -5, // Platform is unsupported
Leopard_CallInitialize = -6, // Call leo_init() first
} LeopardResult; } LeopardResult;
// Flags // Flags

View File

@ -159,13 +159,13 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization> <Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed> <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>false</OmitFramePointers> <OmitFramePointers>true</OmitFramePointers>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck> <BufferSecurityCheck>true</BufferSecurityCheck>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

View File

@ -105,12 +105,6 @@ ffe_t kGFBasis[kGFBits] = {
}; };
#endif #endif
/*
Cantor Basis introduced by:
D. G. Cantor, "On arithmetical algorithms over finite fields",
Journal of Combinatorial Theory, Series A, vol. 50, no. 2, pp. 285-300, 1989.
*/
static const unsigned kFieldSize = (unsigned)1 << kGFBits; //Field size static const unsigned kFieldSize = (unsigned)1 << kGFBits; //Field size
static const unsigned kModulus = kFieldSize - 1; static const unsigned kModulus = kFieldSize - 1;