diff --git a/cauchy_reed_solomon_erasure_coding.hh b/cauchy_reed_solomon_erasure_coding.hh index 5bddbdd..0cf9a94 100644 --- a/cauchy_reed_solomon_erasure_coding.hh +++ b/cauchy_reed_solomon_erasure_coding.hh @@ -9,7 +9,7 @@ Copyright 2023 Ahmet Inan namespace CODE { template -struct CauchyReedSolomonEncoder +struct CauchyReedSolomonErasureCoding { typedef typename GF::value_type value_type; typedef typename GF::ValueType ValueType; @@ -20,36 +20,6 @@ struct CauchyReedSolomonEncoder ValueType row(i), col(ValueType::N - j); return rcp(index(row + col)); } - void operator()(const ValueType *data, ValueType *block, int block_num, int block_len, int block_cnt) - { - assert(block_num <= ValueType::N - block_cnt); - for (int k = 0; k < block_cnt; k++) { - IndexType a_ik = cauchy_matrix(block_num, k); - for (int j = 0; j < block_len; j++) { - if (k) - block[j] = fma(a_ik, data[block_len*k+j], block[j]); - else - block[j] = a_ik * data[block_len*k+j]; - } - } - } - void operator()(const value_type *data, value_type *block, int block_num, int block_len, int block_cnt) - { - (*this)(reinterpret_cast(data), reinterpret_cast(block), block_num, block_len, block_cnt); - } - void operator()(const void *data, void *block, int block_number, int block_bytes, int block_count) - { - assert(block_bytes % sizeof(value_type) == 0); - (*this)(reinterpret_cast(data), reinterpret_cast(block), block_number, block_bytes / sizeof(value_type), block_count); - } -}; - -template -struct CauchyReedSolomonDecoder -{ - typedef typename GF::value_type value_type; - typedef typename GF::ValueType ValueType; - typedef typename GF::IndexType IndexType; // $b_{ij} = \frac{\prod_{k=1}^{n}{(x_j + y_k)(x_k + y_i)}}{(x_j + y_i)\prod_{k \ne j}^{n}{(x_j - x_k)}\prod_{k \ne i}^{n}{(y_i - y_k)}}$ IndexType inverse_cauchy_matrix(const ValueType *rows, int i, int j, int n) { @@ -65,7 +35,20 @@ struct CauchyReedSolomonDecoder } return prod_xy / (index(rows[j] + col_i) * prod_x * prod_y); } - void operator()(ValueType *data, const ValueType *blocks, const ValueType *block_nums, int block_num, int block_len, int block_cnt) + void encode(const ValueType *data, ValueType *block, int block_num, int block_len, int block_cnt) + { + assert(block_num <= ValueType::N - block_cnt); + for (int k = 0; k < block_cnt; k++) { + IndexType a_ik = cauchy_matrix(block_num, k); + for (int j = 0; j < block_len; j++) { + if (k) + block[j] = fma(a_ik, data[block_len*k+j], block[j]); + else + block[j] = a_ik * data[block_len*k+j]; + } + } + } + void decode(ValueType *data, const ValueType *blocks, const ValueType *block_nums, int block_num, int block_len, int block_cnt) { for (int k = 0; k < block_cnt; k++) { IndexType b_ik = inverse_cauchy_matrix(block_nums, block_num, k, block_cnt); @@ -77,14 +60,23 @@ struct CauchyReedSolomonDecoder } } } - void operator()(value_type *data, const value_type *blocks, const value_type *block_nums, int block_num, int block_len, int block_cnt) + void encode(const value_type *data, value_type *block, int block_num, int block_len, int block_cnt) { - (*this)(reinterpret_cast(data), reinterpret_cast(blocks), reinterpret_cast(block_nums), block_num, block_len, block_cnt); + encode(reinterpret_cast(data), reinterpret_cast(block), block_num, block_len, block_cnt); } - void operator()(void *data, const void *blocks, const value_type *block_numbers, int block_number, int block_bytes, int block_count) + void decode(value_type *data, const value_type *blocks, const value_type *block_nums, int block_num, int block_len, int block_cnt) + { + decode(reinterpret_cast(data), reinterpret_cast(blocks), reinterpret_cast(block_nums), block_num, block_len, block_cnt); + } + void encode(const void *data, void *block, int block_number, int block_bytes, int block_count) { assert(block_bytes % sizeof(value_type) == 0); - (*this)(reinterpret_cast(data), reinterpret_cast(blocks), block_numbers, block_number, block_bytes / sizeof(value_type), block_count); + encode(reinterpret_cast(data), reinterpret_cast(block), block_number, block_bytes / sizeof(value_type), block_count); + } + void decode(void *data, const void *blocks, const value_type *block_numbers, int block_number, int block_bytes, int block_count) + { + assert(block_bytes % sizeof(value_type) == 0); + decode(reinterpret_cast(data), reinterpret_cast(blocks), block_numbers, block_number, block_bytes / sizeof(value_type), block_count); } }; diff --git a/tests/crs_regression_test.cc b/tests/crs_regression_test.cc index 39ad3f4..0ee641a 100644 --- a/tests/crs_regression_test.cc +++ b/tests/crs_regression_test.cc @@ -15,8 +15,7 @@ Copyright 2023 Ahmet Inan template void crs_test(int trials) { - CODE::CauchyReedSolomonEncoder encode; - CODE::CauchyReedSolomonDecoder decode; + CODE::CauchyReedSolomonErasureCoding crs; std::random_device rd; std::default_random_engine generator(rd()); typedef std::uniform_int_distribution distribution; @@ -41,14 +40,14 @@ void crs_test(int trials) } auto enc_start = std::chrono::system_clock::now(); for (int i = 0; i < block_count; ++i) - encode(orig, blocks + block_bytes * i, numbers[i], block_bytes, block_count); + crs.encode(orig, blocks + block_bytes * i, numbers[i], block_bytes, block_count); auto enc_end = std::chrono::system_clock::now(); auto enc_usec = std::chrono::duration_cast(enc_end - enc_start); double enc_mbs = double(data_bytes) / enc_usec.count(); uint8_t *data = new uint8_t[data_bytes]; auto dec_start = std::chrono::system_clock::now(); for (int i = 0; i < block_count; ++i) - decode(data + block_bytes * i, blocks, numbers, i, block_bytes, block_count); + crs.decode(data + block_bytes * i, blocks, numbers, i, block_bytes, block_count); auto dec_end = std::chrono::system_clock::now(); auto dec_usec = std::chrono::duration_cast(dec_end - dec_start); double dec_mbs = double(data_bytes) / dec_usec.count();