diff --git a/application/remote_desk/xmake.lua b/application/remote_desk/xmake.lua index 91c72a2..c063a70 100644 --- a/application/remote_desk/xmake.lua +++ b/application/remote_desk/xmake.lua @@ -15,7 +15,6 @@ if is_os("windows") then add_links("Shell32", "windowsapp", "dwmapi", "User32", "kernel32") add_requires("vcpkg::ffmpeg 5.1.2", {configs = {shared = false}}) elseif is_os("linux") then - add_requireconfs("ffmpeg.x264", {configs = {pic = true}}) add_requires("ffmpeg 5.1.2", {system = false}) add_syslinks("pthread", "dl") elseif is_os("macosx") then diff --git a/tests/fec/simple_client.cpp b/tests/fec/simple_client.cpp new file mode 100755 index 0000000..ca18f43 --- /dev/null +++ b/tests/fec/simple_client.cpp @@ -0,0 +1,471 @@ +/* $Id: simple_client.c 216 2014-12-13 13:21:07Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009-2014 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/* this is the decoder */ +#define OF_USE_DECODER + +#include "simple_client_server.h" + +/* + * Chose which decoding method to use... Both should be equivalent. + */ +#define USE_DECODE_WITH_NEW_SYMBOL + +/* Prototypes */ + +/** + * Opens and initializes a UDP socket, ready for receptions. + */ +static SOCKET init_socket(void); + +/** + * This function receives packets on the incoming UDP socket. + * It allocates a buffer of size *len and updates the pkt/len arguments with + * what has been actually received. It works in blocking mode the first time + * it's called (as the client can be launched a few seconds before the server), + * and after that in non blocking (i.e. polling) mode. If no packet is received + * even after having waited a certain time (0.2s), it return OF_STATUS_FAILURE + * to indicate that the sender probably stopped all transmissions. + */ +static of_status_t get_next_pkt(SOCKET so, void **pkt, INT32 *len); + +/** + * Dumps len32 32-bit words of a buffer (typically a symbol). + */ +static void dump_buffer_32(void *buf, UINT32 len32); + +/*************************************************************************************************/ + +int main(int argc, char *argv[]) { + of_codec_id_t codec_id; /* identifier of the codec to use */ + of_session_t *ses = NULL; /* openfec codec instance identifier */ + of_parameters_t *params = + NULL; /* structure used to initialize the openfec session */ + void **recvd_symbols_tab = + NULL; /* table containing pointers to received symbols (no FPI here). + * The allocated buffer start 4 bytes (i.e., sizeof(FPI)) before... + */ + void **src_symbols_tab = NULL; /* table containing pointers to the source + symbol buffers (no FPI here) */ + UINT32 symb_sz_32 = + SYMBOL_SIZE / 4; /* symbol size in units of 32 bit words */ + UINT32 k; /* number of source symbols in the block */ + UINT32 n; /* number of encoding symbols (i.e. source + repair) in the block */ + UINT32 esi; /* Encoding Symbol ID, used to identify each encoding symbol */ + SOCKET so = + INVALID_SOCKET; /* UDP socket for server => client communications */ + void *pkt_with_fpi = NULL; /* pointer to a buffer containing the FPI followed + by the fixed size packet */ + fec_oti_t *fec_oti = NULL; /* FEC Object Transmission Information as received + from the server */ + INT32 len; /* len of the received packet */ + SOCKADDR_IN dst_host; + UINT32 n_received = + 0; /* number of symbols (source or repair) received so far */ + bool done = false; /* true as soon as all source symbols have been received or + recovered */ + UINT32 ret; + + /* First of all, initialize the UDP socket and wait for the FEC OTI to be + * received. This is absolutely required to synchronize encoder and decoder. + * We assume this first packet is NEVER lost otherwise decoding is not + * possible. In practice the sender can transmit it periodically, or it is + * sent through a separate reliable channel. */ + if ((so = init_socket()) == INVALID_SOCKET) { + OF_PRINT_ERROR(("Error initializing socket!\n")) + ret = -1; + goto end; + } + len = sizeof(fec_oti_t); /* size of the expected packet */ + if ((ret = get_next_pkt(so, (void **)&fec_oti, &len)) != OF_STATUS_OK) { + OF_PRINT_ERROR(("get_next_pkt failed (FEC OTI reception)\n")) + ret = -1; + goto end; + } + if (len != sizeof(fec_oti_t)) { + OF_PRINT_ERROR( + ("FEC OTI reception failed: bad size, expected %lu but received %d " + "instead\n", + sizeof(fec_oti_t), ret)) + ret = -1; + goto end; + } + /* convert back to host endianess */ + codec_id = (of_codec_id_t)ntohl(fec_oti->codec_id); + fec_oti->codec_id = ntohl(fec_oti->codec_id); + k = fec_oti->k = ntohl(fec_oti->k); + n = fec_oti->n = ntohl(fec_oti->n); + + printf("\nReceiving packets from %s/%d\n", DEST_IP, DEST_PORT); + + /* and check the correctness of data received */ + if (k > n || k > 40000 || n > 40000) { + OF_PRINT_ERROR( + ("Invalid FEC OTI received: k=%u or n=%u received are probably out of " + "range\n", + k, n)) + ret = -1; + goto end; + } + /* now we know which codec the sender has used along with the codec + * parameters, we can prepar the params structure accordingly */ + switch (codec_id) { + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: { + /* fill in the code specific part of the of_..._parameters_t structure */ + of_rs_2_m_parameters_t *my_params; + + printf( + "\nInitialize a Reed-Solomon over GF(2^m) codec instance, (n, " + "k)=(%u, %u)...\n", + n, k); + if ((my_params = (of_rs_2_m_parameters_t *)calloc( + 1, sizeof(*my_params))) == NULL) { + OF_PRINT_ERROR(("no memory for codec %d\n", codec_id)) + ret = -1; + goto end; + } + my_params->m = 8; + params = (of_parameters_t *)my_params; + break; + } + + case OF_CODEC_LDPC_STAIRCASE_STABLE: { + /* fill in the code specific part of the of_..._parameters_t structure */ + of_ldpc_parameters_t *my_params; + + printf( + "\nInitialize an LDPC-Staircase codec instance, (n, k)=(%u, %u)...\n", + n, k); + if ((my_params = (of_ldpc_parameters_t *)calloc(1, sizeof(*my_params))) == + NULL) { + OF_PRINT_ERROR(("no memory for codec %d\n", codec_id)) + ret = -1; + goto end; + } + my_params->prng_seed = rand(); + my_params->N1 = 7; + params = (of_parameters_t *)my_params; + break; + } + + default: + OF_PRINT_ERROR( + ("Invalid FEC OTI received: codec_id=%u received is not valid\n", + codec_id)) + ret = -1; + goto end; + } + params->nb_source_symbols = + k; /* fill in the generic part of the of_parameters_t structure */ + params->nb_repair_symbols = n - k; + params->encoding_symbol_length = SYMBOL_SIZE; + + /* Open and initialize the openfec decoding session now that we know the + * various parameters used by the sender/encoder... */ + if ((ret = of_create_codec_instance(&ses, codec_id, OF_DECODER, VERBOSITY)) != + OF_STATUS_OK) { + OF_PRINT_ERROR(("of_create_codec_instance() failed\n")) + ret = -1; + goto end; + } + if (of_set_fec_parameters(ses, params) != OF_STATUS_OK) { + OF_PRINT_ERROR( + ("of_set_fec_parameters() failed for codec_id %d\n", codec_id)) + ret = -1; + goto end; + } + + printf("\nDecoding in progress. Waiting for new packets...\n"); + + /* allocate a table for the received encoding symbol buffers. We'll update it + * progressively */ + if (((recvd_symbols_tab = (void **)calloc(n, sizeof(void *))) == NULL) || + ((src_symbols_tab = (void **)calloc(n, sizeof(void *))) == NULL)) { + OF_PRINT_ERROR(("no memory (calloc failed for enc_symbols_tab, n=%u)\n", n)) + ret = -1; + goto end; + } + + len = SYMBOL_SIZE + 4; /* size of the expected packet */ +#ifdef USE_DECODE_WITH_NEW_SYMBOL + /* + * this is the standard method: submit each fresh symbol to the library ASAP, + * upon reception (or later, but using the standard + * of_decode_with_new_symbol() function). + */ + while ((ret = get_next_pkt(so, &pkt_with_fpi, &len)) == OF_STATUS_OK) { + /* OK, new packet received... */ + n_received++; + esi = ntohl(*(UINT32 *)pkt_with_fpi); + if (esi > n) /* a sanity check, in case... */ + { + OF_PRINT_ERROR(("invalid esi=%u received in a packet's FPI\n", esi)) + ret = -1; + goto end; + } + recvd_symbols_tab[esi] = (char *)pkt_with_fpi + 4; /* remember */ + printf("%05d => receiving symbol esi=%u (%s)\n", n_received, esi, + (esi < k) ? "src" : "repair"); + if (of_decode_with_new_symbol(ses, (char *)pkt_with_fpi + 4, esi) == + OF_STATUS_ERROR) { + OF_PRINT_ERROR(("of_decode_with_new_symbol() failed\n")) + ret = -1; + goto end; + } + /* check if completed in case we received k packets or more */ + if ((n_received >= k) && (of_is_decoding_complete(ses) == true)) { + /* done, we recovered everything, no need to continue reception */ + done = true; + break; + } + len = SYMBOL_SIZE + + 4; /* make sure len contains the size of the expected packet */ + } +#else + /* + * this is the alternative method: wait to receive all the symbols, then + * submit them all to the library using the of_set_available_symbols() + * function. In that case decoding will occur during the of_finish_decoding() + * call. + */ + while ((ret = get_next_pkt(so, &pkt_with_fpi, &len)) == OF_STATUS_OK) { + /* OK, new packet received... */ + n_received++; + esi = ntohl(*(UINT32 *)pkt_with_fpi); + if (esi > n) /* a sanity check, in case... */ + { + OF_PRINT_ERROR(("invalid esi=%u received in a packet's FPI\n", esi)) + ret = -1; + goto end; + } + recvd_symbols_tab[esi] = (char *)pkt_with_fpi + 4; /* remember */ + printf("%05d => receiving symbol esi=%u (%s)\n", n_received, esi, + (esi < k) ? "src" : "repair"); + len = SYMBOL_SIZE + + 4; /* make sure len contains the size of the expected packet */ + } + /* now we received everything, submit them all to the codec if we received a + * sufficiently high number of symbols (i.e. >= k) */ + if (n_received >= k && + (of_set_available_symbols(ses, recvd_symbols_tab) != OF_STATUS_OK)) { + OF_PRINT_ERROR(("of_set_available_symbols() failed with error (%d)\n", ret)) + ret = -1; + goto end; + } +#endif + if (!done && (ret == OF_STATUS_FAILURE) && (n_received >= k)) { + /* there's no packet any more but we received at least k, and the use of + * of_decode_with_new_symbol() didn't succedd to decode, so try with + * of_finish_decoding. NB: this is useless with MDS codes (e.g. + * Reed-Solomon), but it is essential with LDPC-Staircase as + * of_decode_with_new_symbol performs ITerative decoding, whereas + * of_finish_decoding performs ML decoding */ + ret = of_finish_decoding(ses); + if (ret == OF_STATUS_ERROR || ret == OF_STATUS_FATAL_ERROR) { + OF_PRINT_ERROR(("of_finish_decoding() failed with error (%d)\n", ret)) + ret = -1; + goto end; + } else if (ret == OF_STATUS_OK) { + done = true; + } + /* else ret == OF_STATUS_FAILURE, meaning of_finish_decoding didn't manage + * to recover all source symbols */ + } + if (done) { + /* finally, get a copy of the pointers to all the source symbols, those + * received (that we already know) and those decoded. In case of received + * symbols, the library does not change the pointers (same value). */ + if (of_get_source_symbols_tab(ses, src_symbols_tab) != OF_STATUS_OK) { + OF_PRINT_ERROR(("of_get_source_symbols_tab() failed\n")) + ret = -1; + goto end; + } + printf("\nDone! All source symbols rebuilt after receiving %u packets\n", + n_received); + if (VERBOSITY > 1) { + for (esi = 0; esi < k; esi++) { + printf("src[%u]= ", esi); + dump_buffer_32(src_symbols_tab[esi], 1); + } + } + } else { + printf( + "\nFailed to recover all erased source symbols even after receiving %u " + "packets\n", + n_received); + } + +end: + /* Cleanup everything... */ + if (so != INVALID_SOCKET) { + close(so); + } + if (ses) { + of_release_codec_instance(ses); + } + if (params) { + free(params); + } + if (fec_oti) { + free(fec_oti); + } + if (recvd_symbols_tab && src_symbols_tab) { + for (esi = 0; esi < n; esi++) { + if (recvd_symbols_tab[esi]) { + /* this is a symbol received from the network, without its FPI that + * starts 4 bytes before */ + free((char *)recvd_symbols_tab[esi] - 4); + } else if (esi < k && src_symbols_tab[esi]) { + /* this is a source symbol decoded by the openfec codec, so free it */ + ASSERT(recvd_symbols_tab[esi] == NULL); + free(src_symbols_tab[esi]); + } + } + free(recvd_symbols_tab); + free(src_symbols_tab); + } + return ret; +} + +/** + * Opens and initializes a UDP socket, ready for receptions. + */ +static SOCKET init_socket() { + SOCKET s; + SOCKADDR_IN bindAddr; + UINT32 sz = 1024 * 1024; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) { + printf("Error: call to socket() failed\n"); + return INVALID_SOCKET; + } + bindAddr.sin_family = AF_INET; + bindAddr.sin_port = htons((short)DEST_PORT); + bindAddr.sin_addr.s_addr = INADDR_ANY; + if (bind(s, (SOCKADDR *)&bindAddr, sizeof(bindAddr)) == SOCKET_ERROR) { + printf("bind() failed. Port %d may be already in use\n", DEST_PORT); + return INVALID_SOCKET; + } + /* increase the reception socket size as the default value may lead to a high + * datagram loss rate */ + if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) == -1) { + printf("setsockopt() failed to set new UDP socket size to %u\n", sz); + return INVALID_SOCKET; + } + return s; +} + +/** + * Receives packets on the incoming UDP socket. + */ +static of_status_t get_next_pkt(SOCKET so, void **pkt, INT32 *len) { + static bool first_call = true; + INT32 saved_len = + *len; /* save it, in case we need to do several calls to recvfrom */ + + if ((*pkt = malloc(saved_len)) == NULL) { + OF_PRINT_ERROR(("no memory (malloc failed for p)\n")) + return OF_STATUS_ERROR; + } + if (first_call) { + /* the first time we must be in blocking mode since the flow may be launched + * after a few seconds... */ + first_call = false; + *len = recvfrom(so, *pkt, saved_len, 0, NULL, NULL); + if (*len < 0) { + /* this is an anormal error, exit */ + perror("recvfrom"); + OF_PRINT_ERROR(("recvfrom failed\n")) + free(*pkt); /* don't forget to free it, otherwise it will leak */ + return OF_STATUS_ERROR; + } + /* set the non blocking mode for this socket now that the flow has been + * launched */ + if (fcntl(so, F_SETFL, O_NONBLOCK) < 0) { + OF_PRINT_ERROR(("ERROR, fcntl failed to set non blocking mode\n")) + exit(-1); + } + if (VERBOSITY > 1) + printf("%s: pkt received 0, len=%u\n", __FUNCTION__, *len); + return OF_STATUS_OK; + } + /* otherwise we are in non-blocking mode... */ + *len = recvfrom(so, *pkt, saved_len, 0, NULL, NULL); + if (*len > 0) { + if (VERBOSITY > 1) + printf("%s: pkt received 1, len=%u\n", __FUNCTION__, *len); + return OF_STATUS_OK; + } else if (errno == EAGAIN || errno == EWOULDBLOCK) { + /* no packet available, sleep a little bit and retry */ + SLEEP(200); /* (in milliseconds) */ + *len = recvfrom(so, *pkt, saved_len, 0, NULL, NULL); + if (*len > 0) { + if (VERBOSITY > 1) + printf("%s: pkt received 2, len=%u\n", __FUNCTION__, *len); + return OF_STATUS_OK; + } else { + /* that's the end of the test, no packet available any more, we're sure of + * that now... */ + if (VERBOSITY > 1) + printf("%s: end of test, no packet after the sleep\n", __FUNCTION__); + free(*pkt); /* don't forget to free it, otherwise it will leak */ + return OF_STATUS_FAILURE; + } + } else { + /* this is an anormal error, exit */ + perror("recvfrom"); + OF_PRINT_ERROR(("ERROR, recvfrom failed\n")) + free(*pkt); /* don't forget to free it, otherwise it will leak */ + return OF_STATUS_ERROR; + } + return OF_STATUS_ERROR; /* never called */ +} + +/** + * Dumps len32 32-bit words of a buffer (typically a symbol). + */ +static void dump_buffer_32(void *buf, UINT32 len32) { + UINT32 *ptr; + UINT32 j = 0; + + printf("0x"); + for (ptr = (UINT32 *)buf; len32 > 0; len32--, ptr++) { + /* convert to big endian format to be sure of byte order */ + printf("%08X", htonl(*ptr)); + if (++j == 10) { + j = 0; + printf("\n"); + } + } + printf("\n"); +} diff --git a/tests/fec/simple_client_server.h b/tests/fec/simple_client_server.h new file mode 100755 index 0000000..6976d97 --- /dev/null +++ b/tests/fec/simple_client_server.h @@ -0,0 +1,103 @@ +/* $Id: simple_client_server.h 207 2014-12-10 19:47:50Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009-2014 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for gettimeofday */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#include "lib_common/of_openfec_api.h" +#ifdef __cplusplus +}; +#endif + +/* + * OS dependant definitions + */ +#define SOCKET int +#define SOCKADDR struct sockaddr +#define SOCKADDR_IN struct sockaddr_in +#define INVALID_SOCKET (-1) +#define SOCKET_ERROR (-1) +#define closesocket close +#define SLEEP(t) usleep(t * 1000) + +/* + * Simulation parameters... + * Change as required + */ +#define SYMBOL_SIZE \ + 1024 /* symbol size, in bytes (must be multiple of 4 in this simple example) \ + */ +#define DEFAULT_K 100 /* default k value */ +#define CODE_RATE 0.667 /* k/n = 2/3 means we add 50% of repair symbols */ +#define LOSS_RATE \ + 0.30 /* we consider 30% of packet losses... It assumes there's no additional \ + loss during UDP transmissions */ + +#define VERBOSITY \ + 2 /* Define the verbosity level: \ + * 0 : no trace \ + * 1 : main traces \ + * 2 : full traces with packet dumps */ + +#define DEST_IP "127.0.0.1" /* Destination IPv4 address */ +#define DEST_PORT 10978 /* Destination port (UDP) */ + +/* + * Simplified FEC Object Transmission Information structure, used to synchronize + * sender and receiver. + * + * NB: all the fields MUST be in Network Endian while sent over the network, so + * use htonl (resp. ntohl) at the sender (resp. receiver). + */ +typedef struct { + UINT32 codec_id; /* identifies the code/codec being used. In practice, the + * "FEC encoding ID" that identifies the FEC Scheme should be + * used instead (see [RFC5052]). In our example, we are not + * compliant with the RFCs anyway, so keep it simple. */ + UINT32 k; + UINT32 n; +} fec_oti_t; diff --git a/tests/fec/simple_server.cpp b/tests/fec/simple_server.cpp new file mode 100755 index 0000000..8734837 --- /dev/null +++ b/tests/fec/simple_server.cpp @@ -0,0 +1,362 @@ +/* $Id: simple_server.c 216 2014-12-13 13:21:07Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009-2014 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/* this is the encoder */ +#define OF_USE_ENCODER + +#include "simple_client_server.h" + +/* Prototypes */ + +/** + * Opens and initializes a UDP socket, ready for receptions. + */ +static SOCKET init_socket(SOCKADDR_IN *dst_host); + +/** + * Shuffles the array randomly. + */ +static void randomize_array(UINT32 **array, UINT32 arrayLen); + +/** + * Dumps len32 32-bit words of a buffer (typically a symbol). + */ +static void dump_buffer_32(void *buf, UINT32 len32); + +/*************************************************************************************************/ + +int main(int argc, char *argv[]) { + of_codec_id_t codec_id; /* identifier of the codec to use */ + of_session_t *ses = NULL; /* openfec codec instance identifier */ + of_parameters_t *params = + NULL; /* structure used to initialize the openfec session */ + void **enc_symbols_tab = NULL; /* table containing pointers to the encoding + (i.e. source + repair) symbols buffers */ + UINT32 symb_sz_32 = + SYMBOL_SIZE / 4; /* symbol size in units of 32 bit words */ + UINT32 k; /* number of source symbols in the block */ + UINT32 n; /* number of encoding symbols (i.e. source + repair) in the block */ + UINT32 esi; /* Encoding Symbol ID, used to identify each encoding symbol */ + UINT32 i; + UINT32 *rand_order = NULL; /* table used to determine a random transmission + * order. This randomization process is essential + * for LDPC-Staircase optimal performance */ + SOCKET so = + INVALID_SOCKET; /* UDP socket for server => client communications */ + char *pkt_with_fpi = NULL; /* buffer containing a fixed size packet plus a + header consisting only of the FPI */ + fec_oti_t + fec_oti; /* FEC Object Transmission Information as sent to the client */ + INT32 lost_after_index = -1; /* all the packets to send after this index are + considered as lost during transmission */ + SOCKADDR_IN dst_host; + UINT32 ret = -1; + + if (argc == 1) { + /* k value is ommited, so use default */ + k = DEFAULT_K; + } else { + k = atoi(argv[1]); + } + n = (UINT32)floor((double)k / (double)CODE_RATE); + /* Choose which codec is the most appropriate. If small enough, choose + * Reed-Solomon (with m=8), otherwise LDPC-Staircase. Then finish the openfec + * session initialization accordingly */ + if (n <= 255) { + /* fill in the code specific part of the of_..._parameters_t structure */ + of_rs_2_m_parameters_t *my_params; + + printf( + "\nInitialize a Reed-Solomon over GF(2^m) codec instance, (n, k)=(%u, " + "%u)...\n", + n, k); + codec_id = OF_CODEC_REED_SOLOMON_GF_2_M_STABLE; + if ((my_params = (of_rs_2_m_parameters_t *)calloc(1, sizeof(*my_params))) == + NULL) { + OF_PRINT_ERROR(("no memory for codec %d\n", codec_id)) + ret = -1; + goto end; + } + my_params->m = 8; + params = (of_parameters_t *)my_params; + } else { + /* fill in the code specific part of the of_..._parameters_t structure */ + of_ldpc_parameters_t *my_params; + + printf( + "\nInitialize an LDPC-Staircase codec instance, (n, k)=(%u, %u)...\n", + n, k); + codec_id = OF_CODEC_LDPC_STAIRCASE_STABLE; + if ((my_params = (of_ldpc_parameters_t *)calloc(1, sizeof(*my_params))) == + NULL) { + OF_PRINT_ERROR(("no memory for codec %d\n", codec_id)) + ret = -1; + goto end; + } + my_params->prng_seed = rand(); + my_params->N1 = 7; + params = (of_parameters_t *)my_params; + } + params->nb_source_symbols = + k; /* fill in the generic part of the of_parameters_t structure */ + params->nb_repair_symbols = n - k; + params->encoding_symbol_length = SYMBOL_SIZE; + + /* Open and initialize the openfec session now... */ + if ((ret = of_create_codec_instance(&ses, codec_id, OF_ENCODER, VERBOSITY)) != + OF_STATUS_OK) { + OF_PRINT_ERROR(("of_create_codec_instance() failed\n")) + ret = -1; + goto end; + } + if (of_set_fec_parameters(ses, params) != OF_STATUS_OK) { + OF_PRINT_ERROR( + ("of_set_fec_parameters() failed for codec_id %d\n", codec_id)) + ret = -1; + goto end; + } + + /* Allocate and initialize our source symbols... + * In case of a file transmission, the opposite takes place: the file is read + * and partitionned into a set of k source symbols. At the end, it's just + * equivalent since there is a set of k source symbols that need to be sent + * reliably thanks to an FEC encoding. */ + printf("\nFilling source symbols...\n"); + if ((enc_symbols_tab = (void **)calloc(n, sizeof(void *))) == NULL) { + OF_PRINT_ERROR(("no memory (calloc failed for enc_symbols_tab, n=%u)\n", n)) + ret = -1; + goto end; + } + /* In order to detect corruption, the first symbol is filled with 0x1111..., + * the second with 0x2222..., etc. NB: the 0x0 value is avoided since it is a + * neutral element in the target finite fields, i.e. it prevents the detection + * of symbol corruption */ + for (esi = 0; esi < k; esi++) { + if ((enc_symbols_tab[esi] = calloc(symb_sz_32, sizeof(UINT32))) == NULL) { + OF_PRINT_ERROR( + ("no memory (calloc failed for enc_symbols_tab[%d])\n", esi)) + ret = -1; + goto end; + } + memset(enc_symbols_tab[esi], (char)(esi + 1), SYMBOL_SIZE); + if (VERBOSITY > 1) { + printf("src[%03d]= ", esi); + dump_buffer_32(enc_symbols_tab[esi], 1); + } + } + + /* Now build the n-k repair symbols... */ + printf("\nBuilding repair symbols...\n"); + for (esi = k; esi < n; esi++) { + if ((enc_symbols_tab[esi] = (char *)calloc(symb_sz_32, sizeof(UINT32))) == + NULL) { + OF_PRINT_ERROR( + ("no memory (calloc failed for enc_symbols_tab[%d])\n", esi)) + ret = -1; + goto end; + } + if (of_build_repair_symbol(ses, enc_symbols_tab, esi) != OF_STATUS_OK) { + OF_PRINT_ERROR( + ("ERROR: of_build_repair_symbol() failed for esi=%u\n", esi)) + ret = -1; + goto end; + } + if (VERBOSITY > 1) { + printf("repair[%03d]= ", esi); + dump_buffer_32(enc_symbols_tab[esi], 4); + } + } + + /* Randomize the packet order, it's important for LDPC-Staircase codes for + * instance... */ + printf("\nRandomizing transmit order...\n"); + if ((rand_order = (UINT32 *)calloc(n, sizeof(UINT32))) == NULL) { + OF_PRINT_ERROR(("no memory (calloc failed for rand_order)\n")) + ret = -1; + goto end; + } + randomize_array(&rand_order, n); + + /* Finally initialize the UDP socket and throw our packets... */ + if ((so = init_socket(&dst_host)) == INVALID_SOCKET) { + OF_PRINT_ERROR(("Error initializing socket!\n")) + ret = -1; + goto end; + } + printf("First of all, send the FEC OTI for this object to %s/%d\n", DEST_IP, + DEST_PORT); + /* Initialize and send the FEC OTI to the client */ + /* convert back to host endianess */ + fec_oti.codec_id = htonl(codec_id); + fec_oti.k = htonl(k); + fec_oti.n = htonl(n); + if ((ret = sendto(so, (void *)&fec_oti, sizeof(fec_oti), 0, + (SOCKADDR *)&dst_host, sizeof(dst_host))) != + sizeof(fec_oti)) { + OF_PRINT_ERROR(("Error while sending the FEC OTI\n")) + ret = -1; + goto end; + } + + lost_after_index = n * (1 - LOSS_RATE); + if (lost_after_index < k) { + OF_PRINT_ERROR( + ("The loss rate %f is to high: only %u packets will be sent, whereas " + "k=%u\n", + LOSS_RATE, lost_after_index, k)) + ret = -1; + goto end; + } + printf( + "Sending %u source and repair packets to %s/%d. All packets sent at " + "index %u and higher are considered as lost\n", + n, DEST_IP, DEST_PORT, lost_after_index); + /* Allocate a buffer where we'll copy each symbol plus its simplistif FPI (in + * this example consisting only of the ESI). This needs to be fixed in real + * applications, with the actual FPI required for this code. Also doing a + * memcpy is rather suboptimal in terms of performance! */ + if ((pkt_with_fpi = (char *)malloc(4 + SYMBOL_SIZE)) == NULL) { + OF_PRINT_ERROR(("no memory (malloc failed for pkt_with_fpi)\n")) + ret = -1; + goto end; + } + for (i = 0; i < n; i++) { + if (i == lost_after_index) { + /* the remaining packets are considered as lost, exit loop */ + break; + } + /* Add a pkt header wich only countains the ESI, i.e. a 32bits sequence + * number, in network byte order in order to be portable regardless of the + * local and remote byte endian representation (the receiver will do the + * opposite with ntohl()...) */ + *(UINT32 *)pkt_with_fpi = htonl(rand_order[i]); + memcpy(4 + pkt_with_fpi, enc_symbols_tab[rand_order[i]], SYMBOL_SIZE); + printf("%05d => sending symbol %u (%s)\n", i + 1, rand_order[i], + (rand_order[i] < k) ? "src" : "repair"); + if ((ret = sendto(so, pkt_with_fpi, SYMBOL_SIZE + 4, 0, + (SOCKADDR *)&dst_host, sizeof(dst_host))) == + SOCKET_ERROR) { + OF_PRINT_ERROR(("sendto() failed!\n")) + ret = -1; + goto end; + } + /* Perform a short usleep() to slow down transmissions and avoid UDP socket + * saturation at the receiver. Note that the true solution consists in + * adding some rate control mechanism here, like a leaky or token bucket. */ + usleep(500); + } + printf("\nCompleted! %d packets sent successfully.\n", i); + ret = 1; + +end: + /* Cleanup everything... */ + if (so != INVALID_SOCKET) { + close(so); + } + if (ses) { + of_release_codec_instance(ses); + } + if (params) { + free(params); + } + if (rand_order) { + free(rand_order); + } + if (enc_symbols_tab) { + for (esi = 0; esi < n; esi++) { + if (enc_symbols_tab[esi]) { + free(enc_symbols_tab[esi]); + } + } + free(enc_symbols_tab); + } + if (pkt_with_fpi) { + free(pkt_with_fpi); + } + return ret; +} + +/* Randomize an array of integers */ +void randomize_array(UINT32 **array, UINT32 arrayLen) { + UINT32 backup = 0; + UINT32 randInd = 0; + UINT32 seed; /* random seed for the srand() function */ + UINT32 i; + + struct timeval tv; + if (gettimeofday(&tv, NULL) < 0) { + OF_PRINT_ERROR(("gettimeofday() failed")) + exit(-1); + } + seed = (int)tv.tv_usec; + srand(seed); + for (i = 0; i < arrayLen; i++) { + (*array)[i] = i; + } + for (i = 0; i < arrayLen; i++) { + backup = (*array)[i]; + randInd = rand() % arrayLen; + (*array)[i] = (*array)[randInd]; + (*array)[randInd] = backup; + } +} + +/* Initialize our UDP socket */ +static SOCKET init_socket(SOCKADDR_IN *dst_host) { + SOCKET s; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) { + printf("Error: call to socket() failed\n"); + return INVALID_SOCKET; + } + dst_host->sin_family = AF_INET; + dst_host->sin_port = htons((short)DEST_PORT); + dst_host->sin_addr.s_addr = inet_addr(DEST_IP); + return s; +} + +static void dump_buffer_32(void *buf, UINT32 len32) { + UINT32 *ptr; + UINT32 j = 0; + + printf("0x"); + for (ptr = (UINT32 *)buf; len32 > 0; len32--, ptr++) { + /* convert to big endian format to be sure of byte order */ + printf("%08X", htonl(*ptr)); + if (++j == 10) { + j = 0; + printf("\n"); + } + } + printf("\n"); +} diff --git a/thirdparty/openfec/CMakeLists.txt b/thirdparty/openfec/CMakeLists.txt new file mode 100644 index 0000000..e3d5a60 --- /dev/null +++ b/thirdparty/openfec/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 2.6) + +##project +project(openfec C) + +ENABLE_TESTING() + +if (PROFILING STREQUAL "ON") + +else(PROFILING STREQUAL "ON") + +endif(PROFILING STREQUAL "ON") + +if (DEBUG STREQUAL "ON") +# Debug mode +ADD_DEFINITIONS(-DOF_DEBUG) +set(CMAKE_BUILD_TYPE Debug) +message(STATUS "Debug mode ON" ) + +else(DEBUG STREQUAL "ON") +# Release mode +set(CMAKE_BUILD_TYPE Release) +set(CMAKE_C_FLAGS "-O4") +message(STATUS "Debug mode OFF") + +endif (DEBUG STREQUAL "ON") + +# set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}) +# set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}) + +# set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) +# include_directories(${PROJECT_SOURCE_DIR}/src/lib_common) +# set(CMAKE_INSTALL_LIBDIR ${PROJECT_SOURCE_DIR}/src/lib_common) +# set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) + +MARK_AS_ADVANCED( + LIBRARY_OUTPUT_PATH + EXECUTABLE_OUTPUT_PATH +) + +link_directories(${LIBRARY_OUTPUT_PATH}) + +add_subdirectory(src) \ No newline at end of file diff --git a/thirdparty/openfec/src/CMakeLists.txt b/thirdparty/openfec/src/CMakeLists.txt new file mode 100644 index 0000000..f410954 --- /dev/null +++ b/thirdparty/openfec/src/CMakeLists.txt @@ -0,0 +1,29 @@ +file (GLOB_RECURSE openfec_sources *) + +add_library(openfec STATIC ${openfec_sources}) + +# From: $cmake --help-property SOVERSION +# For shared libraries VERSION and SOVERSION can be used to specify +# the build version and api version respectively. +# +# Edit it as appropriate to be in line with the src/lib_common/of_openfec_api.c::more_about() version +# +set_target_properties(openfec PROPERTIES + VERSION 1.4.2 + SOVERSION 1) + +# Feel free to edit as appropriate the "target_link_libraries". +# +# Add the IL (DevIL) library if you want to have the possibility to +# produce H/G matrix images with LDPC codes. +# More precisely, we are relying on the DevIL library +# (http://openil.sourceforge.net/). +# Please install it on your machine before compiling the OpenFEC +# library if needed. +# Otherwise remove the IL library. + +target_link_libraries(openfec m) +#target_link_libraries(openfec m IL) + +#target_link_libraries(openfec pthread IL) +#target_link_libraries(openfec pthread) diff --git a/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_codec_profile.h b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_codec_profile.h new file mode 100644 index 0000000..dfda486 --- /dev/null +++ b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_codec_profile.h @@ -0,0 +1,59 @@ +/* $Id: of_codec_profile.h 72 2012-04-13 13:27:26Z detchart $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/****** GENERAL SETUP OPTIONS; EDIT AS APPROPRIATE ****************************/ + +#define OF_USE_LDPC_FROM_FILE_CODEC + +#define READ_MATRIX_FILE + +/** + * Default maximum number of source and encoding symbols for this codec. + * This value depends in particular on the kind of decoder used. To this + * limit, codec implementation details might add other limits (e.g. if + * the ESI values are stored in UINT16 instead of UINT32...). + * + * Hints: + * If ML decoding is enabled and used, then limit yourself to a value + * that is not too high, since decoding might finish with a Gaussian + * elimination on the simplified system. + * In situations where decoding is restricted to IT, the main limit is + * the available memory. It usually means you can set very large values. + */ +#ifdef ML_DECODING +#define OF_LDPC_FROM_FILE_MAX_NB_SOURCE_SYMBOLS_DEFAULT 40000 +#define OF_LDPC_FROM_FILE_MAX_NB_ENCODING_SYMBOLS_DEFAULT 40000 +#else +#define OF_LDPC_FROM_FILE_MAX_NB_SOURCE_SYMBOLS_DEFAULT 100000 +#define OF_LDPC_FROM_FILE_MAX_NB_ENCODING_SYMBOLS_DEFAULT 100000 +#endif diff --git a/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff.h b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff.h new file mode 100644 index 0000000..9400df5 --- /dev/null +++ b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff.h @@ -0,0 +1,152 @@ +/* $Id: of_ldpc_ff.h 182 2014-07-15 09:27:51Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + +#ifndef OF_LDPC_FF_H +#define OF_LDPC_FF_H + + +/** + * LDPC from file stable codec specific control block structure. + */ +typedef struct of_ldpc_ff_cb +{ + struct of_ldpc_staircase_cb cb1; + + /* + * entries specific to LDPC from file... + */ + + /** True if the right side of the parity check matrix is an identity with a + * lower triangle below this identity (and 0 above the identity). */ + bool H2_is_identity_with_lower_triangle; + +} of_ldpc_ff_cb_t; + + +/** + * This function create the codec instance for the LDPC from file codec. + * + * @fn of_status_t of_ldpc_ff_create_codec_instance (of_ldpc_ff_cb_t** of_cb) + * @brief create a LDPC from file codec instance + * @param of_cb (IN/OUT) address of the pointer to a LDPC from file codec control block. This pointer is updated + * by this function. + * In case of success, it points to a session structure allocated by the + * library. In case of failure it points to NULL. + * @return Error status. The ofcb pointer is updated according to the success return + * status. + */ +of_status_t of_ldpc_ff_create_codec_instance (of_ldpc_ff_cb_t** of_cb); + +/** + * + * @fn of_status_t of_ldpc_ff_set_fec_parameters (of_ldpc_ff_cb_t* cb, of_ldpc_ff_parameters_t* params) + * @brief set all the FEC codec parameters (e.g. k, n, or symbol size) + * @param cb (IN) Pointer to the control block. + * @param params (IN) pointer to a structure containing the FEC parameters associated to + * a specific FEC codec. + * @return Error status. + */ +of_status_t of_ldpc_ff_set_fec_parameters (of_ldpc_ff_cb_t* cb, + of_ldpc_ff_parameters_t* params); + +#ifdef OF_USE_ENCODER +/** + * @fn of_status_t of_ldpc_ff_build_repair_symbol (of_ldpc_ff_cb_t* ofcb, void* encoding_symbols_tab[], UINT32 esi_of_symbol_to_build) + * @brief build a repair symbol (encoder only) + * @param ofcb (IN) Pointer to the session. + * @param encoding_symbols_tab (IN/OUT) table of source and repair symbols. + * The entry for the repair symbol to build can either point + * to a buffer allocated by the application, or let to NULL + * meaning that of_build_repair_symbol will allocate memory. + * @param esi_of_symbol_to_build + * (IN) encoding symbol ID of the repair symbol to build in + * {k..n-1} + * @return Error status. + */ +of_status_t of_ldpc_ff_build_repair_symbol (of_ldpc_ff_cb_t* ofcb, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build); +#endif //OF_USE_ENCODER + +#ifdef OF_USE_DECODER +/** + * @fn of_status_t of_ldpc_ff_set_control_parameter (of_ldpc_ff_cb_t* ofcb,UINT32 type,void* value,UINT32 length) + * @brief set a specific FEC parameter + * @param ofcb (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID specific. + * @param value (IN) Pointer to the value of the parameter. The type of the object pointed + * is FEC codec ID specific. + * @return Error status. + */ +of_status_t of_ldpc_ff_set_control_parameter (of_ldpc_ff_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length); + +/** + * @fn of_status_t of_ldpc_ff_get_control_parameter (of_ldpc_ff_cb_t* ofcb,UINT32 type,void* value,UINT32 length) + * @brief get a specific FEC parameter + * @param ses (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID specific. + * @param value (IN/OUT) Pointer to the value of the parameter. The type of the object + * pointed is FEC codec ID specific. This function updates the value object + * accordingly. The application, who knows the FEC codec ID, is responsible + * to allocating the approriate object pointed by the value pointer. + * @return Error status. + */ +of_status_t of_ldpc_ff_get_control_parameter (of_ldpc_ff_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length); + +#endif //OF_USE_DECODER + +/** + * This function return the number of rows and cols of a matrix read into matrix_file. + * + * @fn of_status_t of_get_pck_matrix_dimensions_from_file(char * matrix_file,UINT32 * n_rows, UINT32 *n_cols) + * @brief return the number of rows and cols of a matrix + * @param matrix_file (IN) name of the file containing the matrix + * @param n_rows (OUT) number of rows in matrix + * @param n_cols (OUT) number of cols in matrix + * @return Error status. If it's OK, nb_row and nb_col contain the number of rows and cols of matrix. + */ +of_status_t of_get_pck_matrix_dimensions_from_file (char* matrix_file, + UINT32 * n_rows, + UINT32 * n_cols); + + +#endif //OF_LDPC_FF_H +#endif diff --git a/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff_api.c b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff_api.c new file mode 100644 index 0000000..2a2dac4 --- /dev/null +++ b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff_api.c @@ -0,0 +1,300 @@ +/* $Id: of_ldpc_ff_api.c 182 2014-07-15 09:27:51Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "of_ldpc_ff_includes.h" + +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + + +of_status_t of_ldpc_ff_create_codec_instance(of_ldpc_ff_cb_t** of_cb) +{ + OF_ENTER_FUNCTION + of_codec_type_t codec_type; /* temporary value */ + of_ldpc_ff_cb_t* ff_cb = (of_ldpc_ff_cb_t*) of_realloc(*of_cb, sizeof(of_ldpc_ff_cb_t)); + of_ldpc_staircase_cb_t* cb = (of_ldpc_staircase_cb_t*) ff_cb; + + *of_cb=ff_cb; + /* realloc does not initialize the additional buffer space, so do that manually, + * then re-initialize a few parameters */ + codec_type = cb->codec_type; + memset(cb, 0, sizeof(*cb)); + //*of_cb = cb; + + cb->codec_id = OF_CODEC_LDPC_FROM_FILE_ADVANCED; + cb->codec_type = codec_type; + cb->max_nb_source_symbols = OF_LDPC_FROM_FILE_MAX_NB_SOURCE_SYMBOLS_DEFAULT; /* init it immediately... */ + cb->max_nb_encoding_symbols = OF_LDPC_FROM_FILE_MAX_NB_ENCODING_SYMBOLS_DEFAULT; /* init it immediately... */ + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_ldpc_ff_set_fec_parameters (of_ldpc_ff_cb_t* cb, + of_ldpc_ff_parameters_t* params) +{ + of_mod2entry *e; + UINT32 row; + UINT32 seq; + UINT32 matrix_nb_par; + UINT32 matrix_nb_src; + UINT32 *p_matrix_nb_par; + UINT32 *p_matrix_nb_src; + char * m_matrix_file; + FILE *pFile; + + OF_ENTER_FUNCTION + p_matrix_nb_src = &matrix_nb_src; + p_matrix_nb_par = &matrix_nb_par; +#ifdef OF_DEBUG + cb->cb1.stats_xor = of_calloc(1, sizeof(of_symbol_stats_op_t)); +#endif + /* open the matrix file */ + m_matrix_file= params->pchk_file; + of_ldpc_staircase_cb_t* ofcb = (of_ldpc_staircase_cb_t*) cb; + pFile = fopen (m_matrix_file,"r"); + if (pFile == NULL) + { + OF_PRINT_ERROR(("of_ldpc_ff_set_fec_parameters : ERROR, cannot open matrix file %s",m_matrix_file)) + goto error; + } + ofcb->pchk_matrix = of_mod2sparse_read_human_readable(pFile, p_matrix_nb_src, p_matrix_nb_par); + fclose(pFile); + + if (ofcb->pchk_matrix == NULL) + { + OF_PRINT_ERROR(("of_ldpc_ff_set_fec_parameters : ERROR, parity check matrix can't be created with this parameters..")) + goto error; + } + + cb->H2_is_identity_with_lower_triangle = true; + + of_mod2sparse_matrix_stats(stdout, ofcb->pchk_matrix, *p_matrix_nb_src, *p_matrix_nb_par); + + /* set ofcb attribute specific to from file code*/ + if ((ofcb->nb_source_symbols = matrix_nb_src ) > ofcb->max_nb_source_symbols) { + OF_PRINT_ERROR(("of_ldpc_staircase_set_fec_parameters: ERROR, invalid nb_source_symbols parameter (got %d, maximum is %d)", + ofcb->nb_source_symbols, ofcb->max_nb_source_symbols)); + goto error; + } + ofcb->nb_repair_symbols =matrix_nb_par; + ofcb->nb_total_symbols = matrix_nb_src + matrix_nb_par; + if (ofcb->nb_total_symbols > ofcb->max_nb_encoding_symbols) { + OF_PRINT_ERROR(("of_ldpc_staircase_set_fec_parameters: ERROR, invalid number of encoding symbols (got %d, maximum is %d)", + ofcb->nb_total_symbols, ofcb->max_nb_encoding_symbols)); + goto error; + } + + params->nb_source_symbols = ofcb->nb_source_symbols; + params->nb_repair_symbols = ofcb->nb_repair_symbols; + + /*set ofcb attribute non-specific to from file code */ + ofcb->encoding_symbol_length = params->encoding_symbol_length; + + OF_TRACE_LVL (1, ("%s: k=%u, n-k=%u, n=%u, symbol_length=%u, PRNG seed=%u, N1=%u\n", __FUNCTION__, + ofcb->nb_source_symbols, ofcb->nb_repair_symbols, ofcb->nb_total_symbols, + ofcb->encoding_symbol_length, ofcb->prng_seed, ofcb->N1)) +#ifdef ML_DECODING + ofcb->pchk_matrix_simplified = NULL; +#endif + if ((ofcb->encoding_symbols_tab = (void**) of_calloc(ofcb->nb_total_symbols, sizeof(void*))) == NULL) { + goto no_mem; + } + +#ifdef OF_USE_DECODER + if (ofcb->codec_type & OF_DECODER) + { + ofcb->tab_nb_unknown_symbols = (UINT16*) of_calloc(ofcb->nb_repair_symbols, sizeof(UINT16)); + ofcb->tab_const_term_of_equ = (void**) of_calloc(ofcb->nb_repair_symbols, sizeof(void*)); + ofcb->tab_nb_equ_for_repair = (UINT16*) of_calloc(ofcb->nb_repair_symbols, sizeof(UINT16)); + ofcb->tab_nb_enc_symbols_per_equ = (UINT16*) of_calloc(ofcb->nb_repair_symbols, sizeof(UINT16)); + if (ofcb->tab_nb_unknown_symbols == NULL || ofcb->tab_const_term_of_equ == NULL || + ofcb->tab_nb_equ_for_repair == NULL || ofcb->tab_nb_enc_symbols_per_equ == NULL) { + goto no_mem; + } + // and update the various tables now + for (row = 0; row < ofcb->nb_repair_symbols; row++) + { + for (e = of_mod2sparse_first_in_row (ofcb->pchk_matrix, row); + !of_mod2sparse_at_end (e); + e = of_mod2sparse_next_in_row (e)) + { + ofcb->tab_nb_enc_symbols_per_equ[row]++; + ofcb->tab_nb_unknown_symbols[row]++; + } + } + for (seq = ofcb->nb_source_symbols; seq < (ofcb->nb_total_symbols); seq++) + { + for (e = of_mod2sparse_first_in_col (ofcb->pchk_matrix, of_get_symbol_col ((of_cb_t*)ofcb, seq)); + !of_mod2sparse_at_end (e); + e = of_mod2sparse_next_in_col (e)) + { + ofcb->tab_nb_equ_for_repair[seq - ofcb->nb_source_symbols]++; + } + } + } +#endif //OF_USE_DECODER + ofcb->nb_source_symbol_ready = 0; // Number of source symbols ready + ofcb->nb_repair_symbol_ready = 0; // Number of parity symbols ready + //ofcb->nb_non_dup_symbols_recvd = 0;// Number of non-duplicated symbols received +#ifdef ML_DECODING + ofcb->index_rows = NULL; // Indirection index to access initial m_chekValues array + ofcb->index_cols = NULL; // Indirection index to access initial symbol array + ofcb->remain_cols = 0; // Nb of non empty remaining cols in the future simplified matrix + ofcb->remain_rows = 0; // Nb of non empty remaining rows in the future simplified matrix + ofcb->pchk_matrix_simplified = NULL; // Simplified Parity Check Matrix in sparse mode format + ofcb->original_pchkMatrix = NULL; + ofcb->pchk_matrix_gauss = NULL; // Parity Check matrix in sparse mode format. This matrix + // is also used as a generator matrix in LDGM-* modes + ofcb->dec_step = 0; // Current step in the Gauss Elimination algorithm + ofcb->threshold_simplification = 0; // threshold (number of symbols) above which we + // run the Gauss Elimination algorithm +#endif + OF_EXIT_FUNCTION + return OF_STATUS_OK; +no_mem: + OF_PRINT_ERROR(("out of memory")); +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + + +of_status_t of_ldpc_ff_build_repair_symbol (of_ldpc_ff_cb_t* ofcb, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build) +{ + if (ofcb->H2_is_identity_with_lower_triangle) + { + /* encoding is exactly the same as that of ldpc staircase codes */ + return of_ldpc_staircase_build_repair_symbol((of_ldpc_staircase_cb_t*)ofcb, encoding_symbols_tab, esi_of_symbol_to_build); + } + else + { + /* encoding requires to work on the generator matrix */ + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; + } +} + + +of_status_t of_ldpc_ff_set_control_parameter (of_ldpc_ff_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length) +{ + OF_PRINT_ERROR(("of_ldpc_ff_set_control_parameter: ERROR, not implemented...\n")) + return OF_STATUS_ERROR; +} + + +of_status_t of_ldpc_ff_get_control_parameter (of_ldpc_ff_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length) +{ + of_ldpc_staircase_cb_t *ofcb_staircase; + + OF_ENTER_FUNCTION + ofcb_staircase = (of_ldpc_staircase_cb_t*)ofcb; + switch (type) { + case OF_CTRL_GET_MAX_K: + if (value == NULL || length != sizeof(UINT32)) { + OF_PRINT_ERROR(("%s: OF_CTRL_GET_MAX_K ERROR: null value or bad length (got %d, expected %ld)\n", + __FUNCTION__, length, sizeof(UINT32))) + goto error; + } + *(UINT32*)value = ofcb_staircase->max_nb_source_symbols; + OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_K (%d)\n", __FUNCTION__, *(UINT32*)value)) + break; + + case OF_CTRL_GET_MAX_N: + if (value == NULL || length != sizeof(UINT32)) { + OF_PRINT_ERROR(("%s: OF_CTRL_GET_MAX_N ERROR: null value or bad length (got %d, expected %ld)\n", + __FUNCTION__, length, sizeof(UINT32))) + goto error; + } + *(UINT32*)value = ofcb_staircase->max_nb_encoding_symbols; + OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_N (%d)\n", __FUNCTION__, *(UINT32*)value)) + break; + + default: + OF_PRINT_ERROR(("%s: unknown type (%d)\n", __FUNCTION__, type)) + goto error; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + + +of_status_t of_get_pck_matrix_dimensions_from_file(char * matrix_file,UINT32 * n_rows, UINT32 *n_cols){ + + FILE * f; + char * pch; + char line[1024]; + + f = fopen (matrix_file,"r"); + if (f == NULL) { + OF_PRINT_ERROR(("Cannot open file %s\n",matrix_file)) + goto error; + } + // get the number of row of the matrix + if (fgets (line, sizeof line, f) != NULL) + { + //size_t i = strspn ( line, " \t\n\v" ); + pch = strtok (line, " "); + *n_rows = atoi (pch); + //printf("nrows = %d\n",n_rows); + } + // get the number of columns of the matrix + if (fgets (line, sizeof line, f) != NULL) + { + //size_t i = strspn ( line, " \t\n\v" ); + pch = strtok (line, " "); + *n_cols = atoi (pch); + //printf("ncol = %d\n",n_cols); + } + fclose(f); + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; + +} + +#endif //OF_USE_LDPC_FROM_FILE_CODEC diff --git a/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff_api.h b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff_api.h new file mode 100644 index 0000000..18ae21e --- /dev/null +++ b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff_api.h @@ -0,0 +1,62 @@ +/* $Id: of_ldpc_ff_api.h 89 2012-05-23 15:15:36Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + +#ifndef OF_CODEC_STABLE_LDPC_FF_API +#define OF_CODEC_STABLE_LDPC_FF_API + +#include "../../lib_common/of_types.h" + + +/** + * @struct of_ldpc_ff_parameters_t + * @brief LDPC from file advanced codec specific FEC parameter structure. + * + * This structure contains the pieces of information required to initialize a codec instance, + * using the of_set_fec_parameters() function. + */ +typedef struct of_ldpc_ff_parameters +{ + UINT32 nb_source_symbols; /* must be 1st item */ + UINT32 nb_repair_symbols; /* must be 2nd item */ + UINT32 encoding_symbol_length; /* must be 3rd item */ + /* + * FEC codec id specific attributes follow... + */ + /** Input file containing the binary parity check matrix, of size n-k x n */ + char *pchk_file; +} of_ldpc_ff_parameters_t; + + +#endif /* OF_CODEC_STABLE_LDPC_FF_API */ +#endif diff --git a/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff_includes.h b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff_includes.h new file mode 100644 index 0000000..8ec34c6 --- /dev/null +++ b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_ff_includes.h @@ -0,0 +1,55 @@ +/* $Id: of_ldpc_ff_includes.h 186 2014-07-16 07:17:53Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef OF_LDPC_FF_INCLUDES_H +#define OF_LDPC_FF_INCLUDES_H + +#include +#include +#include +#include /* for timersub */ + +#include "../../lib_common/of_openfec_api.h" + +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + +#include "../../lib_common/linear_binary_codes_utils/of_linear_binary_code.h" + +#include "../../lib_stable/ldpc_staircase/of_ldpc_staircase_api.h" +#include "../../lib_stable/ldpc_staircase/of_ldpc_staircase.h" + +#include "of_ldpc_ff_api.h" +#include "of_ldpc_ff.h" + +#endif +#endif //OF_LDPC_FF_INCLUDES diff --git a/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_includes.h b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_includes.h new file mode 100644 index 0000000..649780f --- /dev/null +++ b/thirdparty/openfec/src/lib_advanced/ldpc_from_file/of_ldpc_includes.h @@ -0,0 +1,68 @@ +/* $Id: of_ldpc_includes.h 72 2012-04-13 13:27:26Z detchart $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Main authors: Mathieu Cunche (INRIA) + * Jonathan Detchart (INRIA) + * Julien Laboure (INRIA) + * Christoph Neumann (INRIA) + * Vincent Roca (INRIA) + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef OF_LDPC_INCLUDES +#define OF_LDPC_INCLUDES + +#include +//#include +#include +#include /* for timersub */ + +#include "../../lib_common/of_types.h" +#include "../../lib_common/of_mem.h" +#include "../../lib_common/of_debug.h" +#include "../../lib_common/of_openfec_api.h" +#include "../../lib_common/of_cb.h" + +#include "of_rand.h" +#include "of_tools.h" +#include "of_hamming_weight.h" +#include "of_ldpc_staircase.h" +#include "of_matrix_sparse.h" +#include "of_matrix_dense.h" +#include "of_matrix_convert.h" +#include "of_ldpc_staircase_api.h" +#include "of_symbol.h" +#include "of_create_pchk.h" +#include "of_ml_decoding.h" +#include "of_ml_tool.h" +#include "of_ml_tool_2.h" + +#endif //OF_LDPC_INCLUDES + diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_hamming_weight.c b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_hamming_weight.c new file mode 100644 index 0000000..b4923d0 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_hamming_weight.c @@ -0,0 +1,160 @@ +/* $Id: of_hamming_weight.c 186 2014-07-16 07:17:53Z roca $ */ +/* + * Source: Wikipedia http://en.wikipedia.org/wiki/Hamming_weight + * + * Creative Commons Attribution-ShareAlike 3.0 Unported License. + * + * You are free: + * + * to Share — to copy, distribute and transmit the work + * to Remix — to adapt the work + * + * Under the following conditions: + * + * Attribution — You must attribute the work in the manner specified by the author or licensor + * (but not in any way that suggests that they endorse you or your use of the work). + * Share Alike — If you alter, transform, or build upon this work, you may distribute the + * resulting work only under the same, similar or a compatible license. + * + * With the understanding that: + * + * Waiver — Any of the above conditions can be waived if you get permission from the copyright holder. + * Public Domain — Where the work or any of its elements is in the public domain under applicable law, + * that status is in no way affected by the license. + * Other Rights — In no way are any of the following rights affected by the license: + * Your fair dealing or fair use rights, or other applicable copyright exceptions and limitations; + * The author's moral rights; + * Rights other persons may have either in the work itself or in how the work is used, such as publicity + * or privacy rights. + * Notice — For any reuse or distribution, you must make clear to others the license terms of this work. + * + * The best way to do this is with a link to this web page: http://creativecommons.org/licenses/by-sa/3.0/ + */ + +#include "../of_linear_binary_code.h" + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + +static const UINT64 of_m1 = 0x5555555555555555LL; //binary: 0101... +static const UINT64 of_m2 = 0x3333333333333333LL; //binary: 00110011.. +static const UINT64 of_m4 = 0x0f0f0f0f0f0f0f0fLL; //binary: 4 zeros, 4 ones ... +static const UINT64 of_m8 = 0x00ff00ff00ff00ffLL; //binary: 8 zeros, 8 ones ... +static const UINT64 of_m16 = 0x0000ffff0000ffffLL; //binary: 16 zeros, 16 ones ... +static const UINT64 of_m32 = 0x00000000ffffffffLL; //binary: 32 zeros, 32 ones +static const UINT64 of_hff = 0xffffffffffffffffLL; //binary: all ones +static const UINT64 of_h01 = 0x0101010101010101LL; //the sum of 256 to the power of 0,1,2,3... + + +UINT8 of_hw8table[256] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8}; + + +//This uses fewer arithmetic operations than any other known +//implementation on machines with fast multiplication. +//It uses 12 arithmetic operations, one of which is a multiply. +INT32 of_popcount_3 (UINT64 x) +{ + x -= (x >> 1) & of_m1; //put count of each 2 bits into those 2 bits + x = (x & of_m2) + ( (x >> 2) & of_m2); //put count of each 4 bits into those 4 bits + x = (x + (x >> 4)) & of_m4; //put count of each 8 bits into those 8 bits + return (x * of_h01) >> 56; //returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ... +} + + +UINT32 of_hweight32 (UINT32 w) +{ + UINT32 res = w - ( (w >> 1) & 0x55555555); + res = (res & 0x33333333) + ( (res >> 2) & 0x33333333); + res = (res + (res >> 4)) & 0x0F0F0F0F; + res = res + (res >> 8); + return (res + (res >> 16)) & 0x000000FF; +} + + +UINT8 of_hweight8_table (UINT8 w) +{ + //unsigned char res; + //res=of_hw8table[w]; + + //printf("of_hw8table[%d]=%d\n",w,res); + //return res; + + return of_hw8table[w]; +} + + +UINT32 of_hweight32_table (UINT32 w) +{ + UINT32 res = 0; + UINT8 *w8 = (UINT8*) (&w); +// for (int j = 0; j<4; j++){ +// res+=hweight8_table(w8[j]); +// } +// res=hweight8_table(w8[0])+hweight8_table(w8[1])+hweight8_table(w8[2])+hweight8_table(w8[3]); + res = of_hw8table[w8[0]] + of_hw8table[w8[1]] + of_hw8table[w8[2]] + of_hw8table[w8[3]]; + return res; +} + + +UINT32 of_hweight32_naive (UINT32 w) +{ + INT32 j; + UINT32 res = 0; + UINT32 x = w; + for (j = 0; j < sizeof (UINT32); j++) + { + res += x & 1; + x = x >> 1; + } + return res; +} + + +/* compute the hamming weight of an array containg 32bits words*/ +UINT32 of_hweight_array (UINT32 *array, INT32 size) +{ + UINT32 weight = 0; + UINT32 i; + UINT32 array_size_32, array_size_32_rem; + UINT32 *v32; + + array_size_32 = size >> 5; + array_size_32_rem = size % 32; // Remaining bytes + if (array_size_32_rem > 0) + { + array_size_32++; + } + +#if defined (__LP64__) || (__WORDSIZE == 64) + UINT32 array_size64; // Size of array in 64bits unit + UINT32 array_size64rem; + array_size64 = array_size_32 >> 1; + array_size64rem = array_size_32 % 2; + + // 64-bit machines + /* First perform as many 64-bit XORs as needed... */ + UINT64 *v64 = (UINT64*) array; // to pointer to 64-bit integers + for (i = array_size64; i > 0; i--) + { + weight += of_popcount_3 (*v64); + v64++; + } + /* then perform a 32-bit XOR if needed... */ + if (array_size64rem > 0) + { + v32 = (UINT32*) v64; // to pointer to 32-bit integers + weight += of_hweight32_table (*v32); + v32++; + } +#else // 32-bit machines + v32 = (UINT32*) array; + for (i = array_size_32;i > 0;i--) + { + weight += of_hweight32_table (*v32); + v32++; + } +#endif + return weight; +} + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_hamming_weight.h b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_hamming_weight.h new file mode 100644 index 0000000..8a9bd00 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_hamming_weight.h @@ -0,0 +1,96 @@ +/* $Id: of_hamming_weight.h 186 2014-07-16 07:17:53Z roca $ */ +/* + * Source: Wikipedia http://en.wikipedia.org/wiki/Hamming_weight + * + * Creative Commons Attribution-ShareAlike 3.0 Unported License. + * + * You are free: + * + * to Share — to copy, distribute and transmit the work + * to Remix — to adapt the work + * + * Under the following conditions: + * + * Attribution — You must attribute the work in the manner specified by the author or licensor + * (but not in any way that suggests that they endorse you or your use of the work). + * Share Alike — If you alter, transform, or build upon this work, you may distribute the + * resulting work only under the same, similar or a compatible license. + * + * With the understanding that: + * + * Waiver — Any of the above conditions can be waived if you get permission from the copyright holder. + * Public Domain — Where the work or any of its elements is in the public domain under applicable law, + * that status is in no way affected by the license. + * Other Rights — In no way are any of the following rights affected by the license: + * Your fair dealing or fair use rights, or other applicable copyright exceptions and limitations; + * The author's moral rights; + * Rights other persons may have either in the work itself or in how the work is used, such as publicity + * or privacy rights. + * Notice — For any reuse or distribution, you must make clear to others the license terms of this work. + * + * The best way to do this is with a link to this web page: http://creativecommons.org/licenses/by-sa/3.0/ + */ + + +#ifndef HAMMING_WEIGHT_H +#define HAMMING_WEIGHT_H + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + +/** + * This uses fewer arithmetic operations than any other known + * implementation on machines with fast multiplication. + * It uses 12 arithmetic operations, one of which is a multiply. + * + * @fn INT32 of_popcount_3 (UINT64 x) + * @brief return the number of "1" in a 64 bits word. + * @param x (IN) 64bits word + * @return count of "1" of x + */ +INT32 of_popcount_3 (UINT64 x); + +/** + * return the hamming weight of a 32bits word + * + * @fn UINT32 of_hweight32 (UINT32 w) + * @brief return the hamming weight of a 32bits word + * @param w (IN) 32bits word + * @return hamming weight of w + */ +UINT32 of_hweight32 (UINT32 w); + +/** + * return the hamming weight of a 32bits word with a naive method + * + * @fn UINT32 of_hweight32_naive (UINT32 w) + * @brief return the hamming weight of a 32bits word + * @param w (IN) 32bits word + * @return hamming weight of w + */ +UINT32 of_hweight32_naive (UINT32 w); + +/** + * return the hamming weight of a 32bits word with a corresponding table method + * + * @fn UINT32 of_hweight32_table (UINT32 w) + * @brief return the hamming weight of a 32bits word + * @param w (IN) 32bits word + * @return hamming weight of w + */ +UINT32 of_hweight32_table (UINT32 w); + +/** + * return the hamming weight of an array word + * + * @fn UINT32 of_hweight_array (UINT32 *array, INT32 size) + * @brief return the hamming weight of a 32bits word + * @param array (IN) pointer to array + * @param size (IN) size of array + * @return hamming weight of array + */ +UINT32 of_hweight_array (UINT32 *array, INT32 size); + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS + +#endif diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_convert.c b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_convert.c new file mode 100644 index 0000000..e2b029b --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_convert.c @@ -0,0 +1,97 @@ +/* $Id: of_matrix_convert.c 186 2014-07-16 07:17:53Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "../of_linear_binary_code.h" + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + +/* CONVERT A MOD2 MATRIX FROM SPARSE TO DENSE FORM. */ + +void of_mod2sparse_to_dense (of_mod2sparse *m, /* Sparse matrix to convert */ + of_mod2dense *r) /* Place to store result */ +{ + OF_ENTER_FUNCTION + of_mod2entry *e; + UINT32 i; + + if (of_mod2sparse_rows (m) > of_mod2dense_rows (r) + || of_mod2sparse_cols (m) > of_mod2dense_cols (r)) + { + OF_PRINT_ERROR(("mod2sparse_to_dense: Dimension of result matrix is less than source\n")) + OF_EXIT_FUNCTION + return; + } + + of_mod2dense_clear (r); + + for (i = 0; i < of_mod2sparse_rows (m); i++) + { + e = of_mod2sparse_first_in_row (m, i); + while (!of_mod2sparse_at_end (e)) + { + of_mod2dense_set (r, i, of_mod2sparse_col (e), 1); + e = of_mod2sparse_next_in_row (e); + } + } +} + + +/* CONVERT A MOD2 MATRIX FROM DENSE TO SPARSE FORM. */ + +void of_mod2dense_to_sparse (of_mod2dense *m, /* Dense matrix to convert */ + of_mod2sparse *r) /* Place to store result */ +{ + UINT32 i, j; + + if (of_mod2dense_rows (m) > of_mod2sparse_rows (r) + || of_mod2dense_cols (m) > of_mod2sparse_cols (r)) + { + OF_PRINT_ERROR(("mod2dense_to_sparse: Dimension of result matrix is less than source\n")) + OF_EXIT_FUNCTION + return; + } + of_mod2sparse_clear (r); + for (i = 0; i < of_mod2dense_rows (m); i++) + { + for (j = 0; j < of_mod2dense_cols (m); j++) + { + if (of_mod2dense_get (m, i, j)) + { + of_mod2sparse_insert (r, i, j); + } + } + } +} + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_convert.h b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_convert.h new file mode 100644 index 0000000..49ffea6 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_convert.h @@ -0,0 +1,45 @@ +/* $Id: of_matrix_convert.h 182 2014-07-15 09:27:51Z roca $ */ + +/* Copyright (c) 1996 by Radford M. Neal + * + * Permission is granted for anyone to copy, use, modify, or distribute this + * program and accompanying programs and documents for any purpose, provided + * this copyright notice is retained and prominently displayed, along with + * a note saying that the original programs are available from Radford Neal's + * web page, and note is made of any changes made to the programs. The + * programs and documents are distributed without any warranty, express or + * implied. As the programs were written for research purposes only, they have + * not been tested to the degree that would be advisable in any important + * application. All use of these programs is entirely at the user's own risk. + */ + +#ifndef OF_MATRIX_CONVERT +#define OF_MATRIX_CONVERT + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + +/** + * @brief convert a sparse matrix to a dense matrix + * @param m (IN) sparse matrix + * @param r (IN) dense matrix + * @return void + */ +void of_mod2sparse_to_dense (of_mod2sparse *m, + of_mod2dense *r); + + +/** + * @brief convert a dense matrix to a sparse matrix + * @param m (IN) dense matrix + * @param r (IN) sparse matrix + * @return void + */ +void of_mod2dense_to_sparse (of_mod2dense *m, + of_mod2sparse *r); + + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS + +#endif /* OF_MATRIX_CONVERT */ + diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_dense.c b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_dense.c new file mode 100644 index 0000000..1642f45 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_dense.c @@ -0,0 +1,1750 @@ + +/* Copyright (c) 1996, 2000, 2001 by Radford M. Neal + * + * Permission is granted for anyone to copy, use, modify, or distribute this + * program and accompanying programs and documents for any purpose, provided + * this copyright notice is retained and prominently displayed, along with + * a note saying that the original programs are available from Radford Neal's + * web page, and note is made of any changes made to the programs. The + * programs and documents are distributed without any warranty, express or + * implied. As the programs were written for research purposes only, they have + * not been tested to the degree that would be advisable in any important + * application. All use of these programs is entirely at the user's own risk. + */ + +#include "../of_linear_binary_code.h" + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + +#define ROW_MAX_ENTRY 1000 +#define COL_MAX_ENTRY 1000 + +/* ALLOCATE SPACE FOR A DENSE MOD2 MATRIX. */ + +of_mod2dense *of_mod2dense_allocate (UINT32 n_rows, /* Number of rows in matrix */ + UINT32 n_cols) /* Number of columns in matrix */ +{ + of_mod2dense *m; + UINT32 j; + + OF_ENTER_FUNCTION + if (n_rows <= 0 || n_cols <= 0) + { + OF_PRINT_ERROR(("mod2dense_allocate: Invalid number of rows (%d) or columns (%d)\n", n_rows, n_cols)) + return NULL; + } + m = (of_mod2dense *) of_calloc(1, sizeof(*m)); + m->n_rows = n_rows; + m->n_cols = n_cols; +#ifdef COL_ORIENTED + m->n_words = (n_rows + of_mod2_wordsize - 1) >> of_mod2_wordsize_shift; + m->col = of_calloc (m->n_cols, sizeof(*m->col)); + m->bits = of_calloc (m->n_words * m->n_cols, sizeof(*m->bits)); + for (j = 0; j < m->n_cols; j++) + { + m->col[j] = m->bits + j * m->n_words; + } +#else + m->n_words = (n_cols + of_mod2_wordsize - 1) >> of_mod2_wordsize_shift; + m->row = (of_mod2word**) of_calloc (m->n_rows, sizeof(*m->row)); + m->bits = (of_mod2word*) of_calloc (m->n_words * m->n_rows, sizeof(*m->bits)); + for (j = 0; j < m->n_rows; j++) + { + m->row[j] = m->bits + j * m->n_words; + } +#endif + OF_EXIT_FUNCTION + return m; +} + + +/* FREE SPACE OCCUPIED BY A DENSE MOD2 MATRIX. */ + +void of_mod2dense_free (of_mod2dense *m) /* Matrix to free */ +{ + OF_ENTER_FUNCTION + of_free (m->bits); +#ifdef COL_ORIENTED + of_free (m->col); +#else + of_free (m->row); +#endif + of_free (m); + OF_EXIT_FUNCTION +} + + +/* CLEAR A DENSE MOD2 MATRIX. */ + +void of_mod2dense_clear (of_mod2dense *r) +{ + OF_ENTER_FUNCTION + UINT32 k, j; +#ifdef COL_ORIENTED + for (j = 0; j < of_mod2dense_cols (r); j++) + { + for (k = 0; k < r->n_words; k++) + { + r->col[j][k] = 0; + } + } +#else + + for (j = 0; j < of_mod2dense_rows (r); j++) + { + for (k = 0; k < r->n_words; k++) + { + r->row[j][k] = 0; + } + } +#endif + OF_EXIT_FUNCTION +} + + +/* COPY A DENSE MOD2 MATRIX. */ + +void of_mod2dense_copy (of_mod2dense *m, /* Matrix to copy */ + of_mod2dense *r) /* Place to store copy of matrix */ +{ + OF_ENTER_FUNCTION + UINT32 k, j; + + + if (of_mod2dense_rows (m) > of_mod2dense_rows (r) + || of_mod2dense_cols (m) > of_mod2dense_cols (r)) + { + OF_PRINT_ERROR(("mod2dense_copy: Destination matrix is too small\n")) + OF_EXIT_FUNCTION + return; + } +#ifdef COL_ORIENTED + for (j = 0; j < of_mod2dense_cols (m); j++) + { + for (k = 0; k < m->n_words; k++) + { + r->col[j][k] = m->col[j][k]; + } + for (; k < r->n_words; k++) + { + r->col[j][k] = 0; + } + } + + for (; j < of_mod2dense_cols (r); j++) + { + for (k = 0; k < r->n_words; k++) + { + r->col[j][k] = 0; + } + } +#else + for (j = 0; j < of_mod2dense_rows (m); j++) + { + for (k = 0; k < m->n_words; k++) + { + r->row[j][k] = m->row[j][k]; + } + for (; k < r->n_words; k++) + { + r->row[j][k] = 0; + } + } + + for (; j < of_mod2dense_rows (r); j++) + { + for (k = 0; k < r->n_words; k++) + { + r->row[j][k] = 0; + } + } +#endif + OF_EXIT_FUNCTION +} + + +/* COPY ROWS OF A DENSE MOD2 MATRIX. */ + +void of_mod2dense_copyrows (of_mod2dense *m, /* Matrix to copy */ + of_mod2dense *r, /* Place to store copy of matrix */ + UINT32 *rows) /* Indexes of rows to copy, from 0 */ +{ + OF_ENTER_FUNCTION + UINT32 i, j, k; + + if (of_mod2dense_cols (m) > of_mod2dense_cols (r)) + { + OF_PRINT_ERROR(("mod2dense_copyrows: Destination matrix has fewer columns than source\n")) + OF_EXIT_FUNCTION + return; + } + + of_mod2dense_clear (r); + + + for (i = 0; i < of_mod2dense_rows (r); i++) + { + if (rows[i] >= of_mod2dense_rows (m)) + { + OF_PRINT_ERROR(("mod2dense_copyrows: Row index out of range\n")) + OF_EXIT_FUNCTION + return; + } +#ifdef COL_ORIENTED + for (j = 0; j < of_mod2dense_cols (m); j++) + { + of_mod2dense_set (r, i, j, of_mod2dense_get (m, rows[i], j)); + } +#else + for (j = 0; j < of_mod2dense_cols (r); j++) + { + if (rows[j] >= of_mod2dense_rows (m)) + { + OF_PRINT_ERROR(("mod2dense_copycols: Column index out of range\n")) + OF_EXIT_FUNCTION + return; + } + for (k = 0; k < m->n_words; k++) + { + r->row[j][k] = m->row[rows[j]][k]; + } + for (; k < r->n_words; k++) + { + r->row[j][k] = 0; + } + } + +#endif + } + + OF_EXIT_FUNCTION +} + + +/* COPY COLUMNS OF A DENSE MOD2 MATRIX. */ + +void of_mod2dense_copycols (of_mod2dense *m, /* Matrix to copy */ + of_mod2dense *r, /* Place to store copy of matrix */ + UINT32 *cols) /* Indexes of columns to copy, from 0 */ +{ + UINT32 i, j; + + OF_ENTER_FUNCTION + if (of_mod2dense_rows (m) > of_mod2dense_rows (r)) + { + OF_PRINT_ERROR(("mod2dense_copycols: Destination matrix has fewer rows than source\n")) + OF_EXIT_FUNCTION + return; + } + + for (j = 0; j < of_mod2dense_cols (r); j++) + { +#ifdef COL_ORIENTED + if (cols[j] < 0 || cols[j] >= of_mod2dense_cols (m)) + { + OF_PRINT_ERROR(("mod2dense_copycols: Column index out of range\n")) + OF_EXIT_FUNCTION + return; + } + + for (k = 0; k < m->n_words; k++) + { + r->col[j][k] = m->col[cols[j]][k]; + } + for (; k < r->n_words; k++) + { + r->col[j][k] = 0; + } + +#else + for (i = 0; i < of_mod2dense_rows (m); i++) + { + of_mod2dense_set (r, i, j, of_mod2dense_get (m, i, cols[j])); + } +#endif + } + OF_EXIT_FUNCTION +} + + +/* PRINT A DENSE MOD2 MATRIX IN HUMAN-READABLE FORM. */ + +void of_mod2dense_print (FILE *f, + of_mod2dense *m) +{ + UINT32 i, j; + + OF_ENTER_FUNCTION + for (i = 0; i < of_mod2dense_rows (m); i++) + { + for (j = 0; j < of_mod2dense_cols (m); j++) + { + if( of_mod2dense_get (m, i, j) !=0) + { + fprintf (f, " %d", of_mod2dense_get (m, i, j)); + } + else + { + fprintf (f, " "/*, of_mod2dense_get (m, i, j)*/); + } + } + fprintf (f, "\n"); + } + OF_EXIT_FUNCTION +} + + +/* PRINT A DENSEMOD2 MATRIX IN HUMAN-READABLE FORM. */ +void of_mod2dense_print_bitmap (of_mod2dense *m, + char *fname) +{ +#ifdef IL_SUPPORT + UINT32 i, j; + UINT32 x,y; + ILuint lImage; + char cmd[100]; + + OF_ENTER_FUNCTION + ilInit(); + ilGenImages(1, &lImage); + ilBindImage(lImage); + //of_mod2dense_print_stats(stdout,m); + ilTexImage(of_mod2dense_cols (m),of_mod2dense_rows (m) , 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); + UINT32 val =1; + y=of_mod2dense_rows (m); + x=of_mod2dense_cols (m); + for (i = 0; i < of_mod2dense_rows (m); i++) + { + for (j = 0; j < of_mod2dense_cols (m); j++) + { + if (of_mod2dense_get (m, i, j)) + { + val = 0x00FF00; /* bit is set, use green */ + } + else + { + val = 0xFFFFFF; /* bit is not set, use white */ + } + x=j; + y=of_mod2dense_rows (m)-i-1; + ilSetPixels(x ,y, 0, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, &val); + } + } + if (fname == NULL) + { + fname = "dense.bmp"; + } + /* use open on MacOS machines, EOG (Eye of Gnome) in Linux machines, and something else if needed... */ + //snprintf(cmd, 99, "open %s", fname); + ilEnable(IL_FILE_OVERWRITE); + ilSaveImage(fname); + //system(cmd); + OF_EXIT_FUNCTION + return; +#endif +} + + +/* WRITE A DENSE MOD2 MATRIX TO A FILE IN MACHINE-READABLE FORM. + + Data is written using of_intio_write, so that it will be readable on a machine + with a different byte-ordering. At present, this assumes that the words + used to pack bits into are no longer than 32 bits. */ + +UINT32 of_mod2dense_write (FILE *f, of_mod2dense *m) +{ + OF_ENTER_FUNCTION + UINT32 j, k; + + of_intio_write (f, m->n_rows); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + + of_intio_write (f, m->n_cols); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } +#ifdef COL_ORIENTED + for (j = 0; j < of_mod2dense_cols (m); j++) + { + for (k = 0; k < m->n_words; k++) + { + of_intio_write (f, m->col[j][k]); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + } + } +#else + for (j = 0; j < of_mod2dense_rows (m); j++) + { + for (k = 0; k < m->n_words; k++) + { + of_intio_write (f, m->row[j][k]); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + } + } +#endif + OF_EXIT_FUNCTION + return 1; +} + + +/* READ A DENSE MOD2 MATRIX STORED IN MACHINE-READABLE FORM FROM A FILE. */ + +of_mod2dense *of_mod2dense_read (FILE *f) +{ + OF_ENTER_FUNCTION + UINT32 n_rows, n_cols; + of_mod2dense *m; + UINT32 j, k; + + n_rows = of_intio_read (f); + if (feof (f) || ferror (f) || n_rows <= 0) + { + OF_EXIT_FUNCTION + return 0; + } + + n_cols = of_intio_read (f); + if (feof (f) || ferror (f) || n_cols <= 0) + { + OF_EXIT_FUNCTION + return 0; + } + + m = of_mod2dense_allocate (n_rows, n_cols); +#ifdef COL_ORIENTED + for (j = 0; j < of_mod2dense_cols (m); j++) + { + for (k = 0; k < m->n_words; k++) + { + m->col[j][k] = of_intio_read (f); + if (feof (f) || ferror (f)) + { + of_mod2dense_free(m); + OF_EXIT_FUNCTION + return 0; + } + } + } +#else + for (j = 0; j < of_mod2dense_rows (m); j++) + { + for (k = 0; k < m->n_words; k++) + { + m->row[j][k] = of_intio_read (f); + if (feof (f) || ferror (f)) + { + of_mod2dense_free(m); + OF_EXIT_FUNCTION + return 0; + } + } + } +#endif + OF_EXIT_FUNCTION + return m; +} + + +/* GET AN ELEMENT FROM A DENSE MOD2 MATRIX. */ + +UINT32 of_mod2dense_get (of_mod2dense *m, /* Matrix to get element from */ + UINT32 row, /* Row of element (starting with zero) */ + UINT32 col) /* Column of element (starting with zero) */ +{ + //OF_ENTER_FUNCTION +#ifdef OF_DEBUG + if ( row >= of_mod2dense_rows (m) || col >= of_mod2dense_cols (m)) + { + OF_PRINT_ERROR(("mod2dense_get: row (%d) or column index (%d) out of bounds (resp. %d and %d)\n", row, col, + of_mod2dense_rows (m), of_mod2dense_cols (m))) + OF_EXIT_FUNCTION + return -1; + } +#endif +#ifdef COL_ORIENTED + return of_mod2_getbit (m->col[col][row>>of_mod2_wordsize_shift], + row&of_mod2_wordsize_mask); +#else + return of_mod2_getbit (m->row[row][col>>of_mod2_wordsize_shift], + col&of_mod2_wordsize_mask); +#endif + //OF_EXIT_FUNCTION +} + + +/* SET AN ELEMENT IN A DENSE MOD2 MATRIX. */ + +INT32 of_mod2dense_set (of_mod2dense *m, /* Matrix to modify element of */ + UINT32 row, /* Row of element (starting with zero) */ + UINT32 col, /* Column of element (starting with zero) */ + UINT32 value) /* New value of element (0 or 1) */ +{ + of_mod2word *w; + + //OF_ENTER_FUNCTION + if (row >= of_mod2dense_rows (m) || col >= of_mod2dense_cols (m)) + { + OF_PRINT_ERROR(("mod2dense_set: row (%d) or column index (%d) out of bounds (resp. %d and %d)\n", row, col, + of_mod2dense_rows (m), of_mod2dense_cols (m))) + OF_EXIT_FUNCTION + return -1; + } +#ifdef COL_ORIENTED + w = &m->col[col][row>>of_mod2_wordsize_shift]; + + *w = value ? of_mod2_setbit1 (*w, row & of_mod2_wordsize_mask) + : of_mod2_setbit0 (*w, row & of_mod2_wordsize_mask); +#else + w = &m->row[row][col>>of_mod2_wordsize_shift]; + + *w = value ? of_mod2_setbit1 (*w, col & of_mod2_wordsize_mask) + : of_mod2_setbit0 (*w, col & of_mod2_wordsize_mask); +#endif + //OF_EXIT_FUNCTION + return 0; +} + + +/* FLIP AN ELEMENT OF A DENSE MOD2 MATRIX. */ + +UINT32 of_mod2dense_flip (of_mod2dense *m, /* Matrix to flip element in */ + UINT32 row, /* Row of element (starting with zero) */ + UINT32 col) /* Column of element (starting with zero) */ +{ + of_mod2word *w; + UINT32 b; + + OF_ENTER_FUNCTION + if (row >= of_mod2dense_rows (m) || col >= of_mod2dense_cols (m)) + { + OF_PRINT_ERROR(("mod2dense_flip: row (%d) or column index (%d) out of bounds (resp. %d and %d)\n", row, col, + of_mod2dense_rows (m), of_mod2dense_cols (m))) + OF_EXIT_FUNCTION + return -1; + } +#ifdef COL_ORIENTED + b = 1 ^ of_mod2_getbit (m->col[col][row>>of_mod2_wordsize_shift], + row & of_mod2_wordsize_mask); + + w = &m->col[col][row>>of_mod2_wordsize_shift]; + + *w = b ? of_mod2_setbit1 (*w, row & of_mod2_wordsize_mask) + : of_mod2_setbit0 (*w, row & of_mod2_wordsize_mask); +#else + b = 1 ^ of_mod2_getbit (m->row[row][col>>of_mod2_wordsize_shift], + col & of_mod2_wordsize_mask); + + w = &m->row[row][col>>of_mod2_wordsize_shift]; + + *w = b ? of_mod2_setbit1 (*w, col & of_mod2_wordsize_mask) + : of_mod2_setbit0 (*w, col & of_mod2_wordsize_mask); + +#endif + OF_EXIT_FUNCTION + return b; +} + + +#if 0 /* { */ + +/* COMPUTE THE TRANSPOSE OF A DENSE MOD2 MATRIX. */ + +void of_mod2dense_transpose +(of_mod2dense *m, /* Matrix to compute transpose of (left unchanged) */ + of_mod2dense *r /* Result of transpose operation */ +) +{ + OF_ENTER_FUNCTION + of_mod2word w, v, *p; + UINT32 k1, j1, i2, j2; + + if (of_mod2dense_rows (m) != of_mod2dense_cols (r) + || of_mod2dense_cols (m) != of_mod2dense_rows (r)) + { + OF_PRINT_ERROR(("mod2dense_transpose: Matrices have incompatible dimensions\n")) + OF_EXIT_FUNCTION + return; + } + + if (r == m) + { + OF_PRINT_ERROR(("mod2dense_transpose: Result matrix is the same as the operand\n")) + OF_EXIT_FUNCTION + return; + } + + of_mod2dense_clear (r); +#ifdef COL_ORIENTED + for (j1 = 0; j1 < of_mod2dense_cols (m); j1++) + { + i2 = j1 >> of_mod2_wordsize_shift; + v = 1 << (j1 & of_mod2_wordsize_mask); + + p = m->col[j1]; + k1 = 0; + + for (j2 = 0; j2 < of_mod2dense_cols (r); j2++) + { + if (k1 == 0) + { + w = *p++; + k1 = of_mod2_wordsize; + } + if (w&1) + { + r->col[j2][i2] |= v; + } + w >>= 1; + k1 -= 1; + } + } +#else + for (j1 = 0; j1 < of_mod2dense_rows (m); j1++) + { + i2 = j1 >> of_mod2_wordsize_shift; + v = 1 << (j1 & of_mod2_wordsize_mask); + + p = m->row[j1]; + k1 = 0; + + for (j2 = 0; j2 < of_mod2dense_rows (r); j2++) + { + if (k1 == 0) + { + w = *p++; + k1 = of_mod2_wordsize; + } + if (w&1) + { + r->row[j2][i2] |= v; + } + w >>= 1; + k1 -= 1; + } + } +#endif + OF_EXIT_FUNCTION +} + + +/* ADD TWO DENSE MOD2 MATRICES. */ + +void of_mod2dense_add +(of_mod2dense *m1, /* Left operand of add */ + of_mod2dense *m2, /* Right operand of add */ + of_mod2dense *r /* Place to store result of add */ +) +{ + OF_ENTER_FUNCTION + UINT32 j, k; + + if (of_mod2dense_rows (m1) != of_mod2dense_rows (r) + || of_mod2dense_cols (m1) != of_mod2dense_cols (r) + || of_mod2dense_rows (m2) != of_mod2dense_rows (r) + || of_mod2dense_cols (m2) != of_mod2dense_cols (r)) + { + OF_PRINT_ERROR(("mod2dense_add: Matrices have different dimensions\n")) + OF_EXIT_FUNCTION + return; + } +#ifdef COL_ORIENTED + for (j = 0; j < of_mod2dense_cols (r); j++) + { + for (k = 0; k < r->n_words; k++) + { + r->col[j][k] = m1->col[j][k] ^ m2->col[j][k]; + } + } +#else + for (j = 0; j < of_mod2dense_rows (r); j++) + { + for (k = 0; k < r->n_words; k++) + { + r->row[j][k] = m1->row[j][k] ^ m2->row[j][k]; + } + } + +#endif + OF_EXIT_FUNCTION +} + + +/* MULTIPLY TWO DENSE MOD2 MATRICES. + + The algorithm used runs faster if the second matrix (right operand of the + multiply) is sparse, but it is also appropriate for dense matrices. This + procedure could be speeded up a bit by replacing the call of mod2dense_get + with in-line code that avoids division, but this doesn't seem worthwhile + at the moment. +*/ + +void of_mod2dense_multiply +(of_mod2dense *m1, /* Left operand of multiply */ + of_mod2dense *m2, /* Right operand of multiply */ + of_mod2dense *r /* Place to store result of multiply */ +) +{ + OF_ENTER_FUNCTION + UINT32 i, j, k; + + if (of_mod2dense_cols (m1) != of_mod2dense_rows (m2) + || of_mod2dense_rows (m1) != of_mod2dense_rows (r) + || of_mod2dense_cols (m2) != of_mod2dense_cols (r)) + { + OF_PRINT_ERROR(("mod2dense_multiply: Matrices have incompatible dimensions\n")) + OF_EXIT_FUNCTION + return; + } + + if (r == m1 || r == m2) + { + OF_PRINT_ERROR(("mod2dense_multiply: Result matrix is the same as one of the operands\n")) + OF_EXIT_FUNCTION + return; + } + + of_mod2dense_clear (r); +#ifdef COL_ORIENTED + for (j = 0; j < of_mod2dense_cols (r); j++) + { + for (i = 0; i < of_mod2dense_rows (m2); i++) + { + if (of_mod2dense_get (m2, i, j)) + { + for (k = 0; k < r->n_words; k++) + { + r->col[j][k] ^= m1->col[i][k]; + } + } + } + } +#else + for (j = 0; j < of_mod2dense_rows (r); j++) + { + for (i = 0; i < of_mod2dense_cols (m2); i++) + { + if (of_mod2dense_get (m2, j, i)) + { + for (k = 0; k < r->n_words; k++) + { + r->row[i][k] ^= m1->row[j][k]; + } + } + } + } +#endif + OF_EXIT_FUNCTION; +} + + +/* SEE WHETHER TWO DENSE MOD2 MATRICES ARE EQUAL. */ + +UINT32 of_mod2dense_equal +(of_mod2dense *m1, + of_mod2dense *m2 +) +{ + OF_ENTER_FUNCTION + UINT32 k, j, w; + of_mod2word m; + + if (of_mod2dense_rows (m1) != of_mod2dense_rows (m2) + || of_mod2dense_cols (m1) != of_mod2dense_cols (m2)) + { + OF_PRINT_ERROR(("mod2dense_equal: Matrices have different dimensions\n")) + OF_EXIT_FUNCTION + return -1; + } + + w = m1->n_words; + + /* Form a mask that has 1s in the lower bit positions corresponding to + bits that contain information in the last word of a matrix column. */ +#ifdef COL_ORIENTED + m = (1 << (of_mod2_wordsize - (w * of_mod2_wordsize - m1->n_rows))) - 1; + + for (j = 0; j < of_mod2dense_cols (m1); j++) + { + for (k = 0; k < w - 1; k++) + { + if (m1->col[j][k] != m2->col[j][k]) + { + OF_EXIT_FUNCTION + return 0; + } + } + + if ( (m1->col[j][k]&m) != (m2->col[j][k]&m)) + { + OF_EXIT_FUNCTION + return 0; + } + } + +#else + m = (1 << (of_mod2_wordsize - (w * of_mod2_wordsize - m1->n_cols))) - 1; + + for (j = 0; j < of_mod2dense_rows (m1); j++) + { + for (k = 0; k < w - 1; k++) + { + if (m1->row[j][k] != m2->row[j][k]) + { + OF_EXIT_FUNCTION + return 0; + } + } + + if ( (m1->row[j][k]&m) != (m2->row[j][k]&m)) + { + OF_EXIT_FUNCTION + return 0; + } + } +#endif + OF_EXIT_FUNCTION + return 1; +} + + +/* INVERT A DENSE MOD2 MATRIX. */ + +UINT32 of_mod2dense_invert +(of_mod2dense *m, /* The matrix to find the inverse of (destroyed) */ + of_mod2dense *r /* Place to store the inverse */ +) +{ + OF_ENTER_FUNCTION + of_mod2word *s, *t; + UINT32 i, j, k, n, w, k0, b0; + + if (of_mod2dense_rows (m) != of_mod2dense_cols (m)) + { + OF_PRINT_ERROR(("mod2dense_invert: Matrix to invert is not square\n")) + OF_EXIT_FUNCTION + return -1; + } + + if (r == m) + { + OF_PRINT_ERROR(("mod2dense_invert: Result matrix is the same as the operand\n")) + OF_EXIT_FUNCTION + return -1; + } +#ifdef COL_ORIENTED + n = of_mod2dense_rows (m); + + w = m->n_words; + + if (of_mod2dense_rows (r) != n || of_mod2dense_cols (r) != n) + { + OF_PRINT_ERROR(("mod2dense_invert: Matrix to receive inverse has wrong dimensions\n")) + OF_EXIT_FUNCTION + return -1; + } + + of_mod2dense_clear (r); + for (i = 0; i < n; i++) + { + of_mod2dense_set (r, i, i, 1); + } + + for (i = 0; i < n; i++) + { + k0 = i >> of_mod2_wordsize_shift; + b0 = i & of_mod2_wordsize_mask; + + for (j = i; j < n; j++) + { + if (of_mod2_getbit (m->col[j][k0], b0)) + break; + } + + if (j == n) + { + OF_EXIT_FUNCTION + return 0; + } + + if (j != i) + { + t = m->col[i]; + m->col[i] = m->col[j]; + m->col[j] = t; + + t = r->col[i]; + r->col[i] = r->col[j]; + r->col[j] = t; + } + + for (j = 0; j < n; j++) + { + if (j != i && of_mod2_getbit (m->col[j][k0], b0)) + { + s = m->col[j]; + t = m->col[i]; + for (k = k0; k < w; k++) + s[k] ^= t[k]; + s = r->col[j]; + t = r->col[i]; + for (k = 0; k < w; k++) + s[k] ^= t[k]; + } + } + } +#else + n = of_mod2dense_cols (m); + + w = m->n_words; + + if (of_mod2dense_cols (r) != n || of_mod2dense_rows (r) != n) + { + OF_PRINT_ERROR(("mod2dense_invert: Matrix to receive inverse has wrong dimensions\n")) + OF_EXIT_FUNCTION + return -1; + } + + of_mod2dense_clear (r); + for (i = 0; i < n; i++) + { + of_mod2dense_set (r, i, i, 1); + } + + + for (i = 0; i < n; i++) + { + k0 = i >> of_mod2_wordsize_shift; + b0 = i & of_mod2_wordsize_mask; + + for (j = i; j < n; j++) + { + if (of_mod2_getbit (m->row[j][k0], b0)) + break; + } + + if (j == n) + { + OF_EXIT_FUNCTION + return 0; + } + + if (j != i) + { + t = m->row[i]; + m->row[i] = m->row[j]; + m->row[j] = t; + + t = r->row[i]; + r->row[i] = r->row[j]; + r->row[j] = t; + } + + for (j = 0; j < n; j++) + { + if (j != i && of_mod2_getbit (m->row[j][k0], b0)) + { + s = m->row[j]; + t = m->row[i]; + for (k = k0; k < w; k++) + s[k] ^= t[k]; + s = r->row[j]; + t = r->row[i]; + for (k = 0; k < w; k++) + s[k] ^= t[k]; + } + } + } +#endif + OF_EXIT_FUNCTION + return 1; +} + + +/* TRIANGULARIZE A DENSE MOD2 MATRIX. */ + +UINT32 of_mod2dense_triangularize +(of_mod2dense *m, /* The matrix to find the inverse of (destroyed) */ + of_mod2dense *r /* Place to store the inverse */ +) +{ + OF_ENTER_FUNCTION + of_mod2word *s, *t; + UINT32 i, j, k, n, p, w, k0, b0; + + /* if (of_mod2dense_rows(m)!=of_mod2dense_cols(m)) */ + /* { fprintf(stderr,"of_mod2dense_triangularize: Matrix to invert is not square\n"); */ + /* exit(1); */ + /* } */ + + if (r == m) + { + OF_PRINT_ERROR(("mod2dense_triangularize: Result matrix is the same as the operand\n")) + OF_EXIT_FUNCTION + return -1; + } +#ifdef COL_ORIENTED + + n = of_mod2dense_rows (m); + p = of_mod2dense_cols (m); + w = m->n_words; + + if (of_mod2dense_rows (r) != n || of_mod2dense_cols (r) != p) + { + OF_PRINT_ERROR(("mod2dense_triangularize: Matrix to receive inverse has wrong dimensions\n")) + OF_EXIT_FUNCTION + return -1; + } + + // r is now the identity + of_mod2dense_clear (r); + for (i = 0; i < p; i++) + { + of_mod2dense_set (r, i, i, 1); + } + + + /* for each line*/ + for (i = 0; i < n; i++) + { + k0 = i >> of_mod2_wordsize_shift; // word index of the ith bit + b0 = i & of_mod2_wordsize_mask; // bit index of the ith bit in the k0-th word + + /* search for the first non-null element */ + for (j = i; j < p; j++) + { + if (of_mod2_getbit (m->col[j][k0], b0)) + break; + } + // now j is the index of the first non null element in the line i + if (j == p) + { + OF_EXIT_FUNCTION + return 0; + } + + if (j != i) + { + // swap column i an j the two matrices + t = m->col[i]; + m->col[i] = m->col[j]; + m->col[j] = t; + + t = r->col[i]; + r->col[i] = r->col[j]; + r->col[j] = t; + } + + + for (j = i; j < p; j++) + { + if (j != i && of_mod2_getbit (m->col[j][k0], b0)) + { + // for all the column were the ith element is non null + s = m->col[j]; + t = m->col[i]; + for (k = k0; k < w; k++) + s[k] ^= t[k]; // add column i with coluln j + s = r->col[j]; + t = r->col[i]; + for (k = 0; k < w; k++) + s[k] ^= t[k]; + } + } + } +#else + + n = of_mod2dense_cols (m); + p = of_mod2dense_rows (m); + w = m->n_words; + + if (of_mod2dense_cols (r) != n || of_mod2dense_rows (r) != p) + { + OF_PRINT_ERROR(("mod2dense_triangularize: Matrix to receive inverse has wrong dimensions\n")) + OF_EXIT_FUNCTION + return -1; + } + + // r is now the identity + of_mod2dense_clear (r); + for (i = 0; i < n; i++) + { + of_mod2dense_set (r, i, i, 1); + } + + + /* for each line*/ + for (i = 0; i < n; i++) + { + k0 = i >> of_mod2_wordsize_shift; // word index of the ith bit + b0 = i & of_mod2_wordsize_mask; // bit index of the ith bit in the k0-th word + + /* search for the first non-null element */ + for (j = i; j < p; j++) + { + if (of_mod2_getbit (m->row[j][k0], b0)) + break; + } + // now j is the index of the first non null element in the line i + if (j == p) + { + OF_EXIT_FUNCTION + return 0; + } + + if (j != i) + { + // swap column i an j the two matrices + t = m->row[i]; + m->row[i] = m->row[j]; + m->row[j] = t; + + t = r->row[i]; + r->row[i] = r->row[j]; + r->row[j] = t; + // TODO : swap the partial sum + + } + + for (j = 0; j < p; j++) + //for (j = i; jrow[j][k0], b0)) + { + // for all the column were the ith element is non null + s = m->row[j]; + t = m->row[i]; + for (k = k0; k < w; k++) + s[k] ^= t[k]; // add column i with coluln j + s = r->row[j]; + t = r->row[i]; + for (k = 0; k < w; k++) + s[k] ^= t[k]; + // TODO : add the m_checkValues of the line + } + } + } + +#endif + OF_EXIT_FUNCTION + return 1; +} + + +/* INVERT A DENSE MOD2 MATRIX WITH ROWS & COLUMNS SELECTED FROM BIGGER MATRIX.*/ + +UINT32 of_mod2dense_invert_selected +(of_mod2dense *m, /* Matrix from which to pick a submatrix to invert */ + of_mod2dense *r, /* Place to store the inverse */ + UINT32 *rows, /* Set to indexes of rows used and not used */ + UINT32 *cols /* Set to indexes of columns used and not used */ +) +{ + OF_ENTER_FUNCTION + of_mod2word *s, *t; + UINT32 R; + UINT32 i, j, k, n, w, k0, b0, n2, c; + + if (r == m) + { + OF_PRINT_ERROR(("mod2dense_invert_selected2: Result matrix is the same as the operand\n")) + OF_EXIT_FUNCTION + return -1; + } +#ifdef COL_ORIENTED + n = of_mod2dense_rows (m); + w = m->n_words; + + n2 = of_mod2dense_cols (m); + + if (of_mod2dense_rows (r) != n || of_mod2dense_cols (r) != n2) + { + OF_PRINT_ERROR(("mod2dense_invert_selected2: Matrix to receive inverse has wrong dimensions\n")) + OF_EXIT_FUNCTION + return -1; + } + + of_mod2dense_clear (r); + + for (i = 0; i < n; i++) + { + rows[i] = i; + } + + for (j = 0; j < n2; j++) + { + cols[j] = j; + } + + R = 0; + i = 0; + + for (;;) + { + while (i < n - R) + { + k0 = rows[i] >> of_mod2_wordsize_shift; + b0 = rows[i] & of_mod2_wordsize_mask; + + for (j = i; j < n2; j++) + { + if (of_mod2_getbit (m->col[cols[j]][k0], b0)) + break; + } + + if (j < n2) + break; + + R += 1; + c = rows[i]; + rows[i] = rows[n-R]; + rows[n-R] = c; + + } + + if (i == n - R) + break; + + c = cols[j]; + cols[j] = cols[i]; + cols[i] = c; + + of_mod2dense_set (r, rows[i], c, 1); + + for (j = 0; j < n2; j++) + { + if (j != c && of_mod2_getbit (m->col[j][k0], b0)) + { + s = m->col[j]; + t = m->col[c]; + for (k = 0; k < w; k++) + s[k] ^= t[k]; + s = r->col[j]; + t = r->col[c]; + for (k = 0; k < w; k++) + s[k] ^= t[k]; + } + } + + i += 1; + } + + for (j = n - R; j < n; j++) + { + s = r->col[cols[j]]; + for (k = 0; k < w; k++) + s[k] = 0; + } + +#else + n = of_mod2dense_cols (m); + w = m->n_words; + + n2 = of_mod2dense_rows (m); + +// if (of_mod2dense_rows(r)!=n || of_mod2dense_cols(r)!=n2) +// { fprintf(stderr, +// "mod2dense_invert_selected: Matrix to receive inverse has wrong dimensions\n"); +// exit(1); +// } + + of_mod2dense_clear (r); + + for (i = 0; i < n; i++) + { + rows[i] = i; + } + + for (j = 0; j < n2; j++) + { + cols[j] = j; + } + + R = 0; + i = 0; + + for (;;) + { + while (i < n - R) + { + k0 = cols[i] >> of_mod2_wordsize_shift; + b0 = cols[i] & of_mod2_wordsize_mask; + + for (j = i; j < n2; j++) + { + if (of_mod2_getbit (m->row[rows[j]][k0], b0)) + break; + } + + if (j < n2) + break; + + R += 1; + c = cols[i]; + cols[i] = cols[n-R]; + cols[n-R] = c; + + } + + if (i == n - R) + break; + + c = rows[j]; + rows[j] = rows[i]; + rows[i] = c; + + of_mod2dense_set (r, c, cols[i], 1); + + for (j = 0; j < n2; j++) + { + if (j != c && of_mod2_getbit (m->row[j][k0], b0)) + { + s = m->row[j]; + t = m->row[c]; + for (k = 0; k < w; k++) + s[k] ^= t[k]; + s = r->row[j]; + t = r->row[c]; + for (k = 0; k < w; k++) + s[k] ^= t[k]; + } + } + + i += 1; + } + + for (j = n - R; j < n; j++) + { + s = r->row[rows[j]]; + for (k = 0; k < w; k++) + s[k] = 0; + } +#endif + OF_EXIT_FUNCTION + return R; +} + + +/* FORCIBLY INVERT A DENSE MOD2 MATRIX. */ + +UINT32 of_mod2dense_forcibly_invert +(of_mod2dense *m, /* The matrix to find the inverse of (destroyed) */ + of_mod2dense *r, /* Place to store the inverse */ + UINT32 *a_row, /* Place to store row indexes of altered elements */ + UINT32 *a_col /* Place to store column indexes of altered elements */ +) +{ + OF_ENTER_FUNCTION + // of_mod2word *s, *t; + + UINT32 c = 0; +#ifdef COL_ORIENTED + if (of_mod2dense_rows (m) != of_mod2dense_cols (m)) + { + OF_PRINT_ERROR(("mod2dense_forcibly_invert: Matrix to invert is not square\n")) + OF_EXIT_FUNCTION + return -1; + } + + if (r == m) + { + OF_PRINT_ERROR(("mod2dense_forcibly_invert: Result matrix is the same as the operand\n")) + OF_EXIT_FUNCTION + return -1; + } + + n = of_mod2dense_rows (m); + w = m->n_words; + + if (of_mod2dense_rows (r) != n || of_mod2dense_cols (r) != n) + { + OF_PRINT_ERROR(("mod2dense_forcibly_invert: Matrix to receive inverse has wrong dimensions\n")) + OF_EXIT_FUNCTION + return -1; + } + + of_mod2dense_clear (r); + for (i = 0; i < n; i++) + { + of_mod2dense_set (r, i, i, 1); + } + + for (i = 0; i < n; i++) + { + a_row[i] = -1; + a_col[i] = i; + } + + for (i = 0; i < n; i++) + { + k0 = i >> of_mod2_wordsize_shift; + b0 = i & of_mod2_wordsize_mask; + + for (j = i; j < n; j++) + { + if (of_mod2_getbit (m->col[j][k0], b0)) + break; + } + + if (j == n) + { + j = i; + of_mod2dense_set (m, i, j, 1); + a_row[i] = i; + } + + if (j != i) + { + t = m->col[i]; + m->col[i] = m->col[j]; + m->col[j] = t; + + t = r->col[i]; + r->col[i] = r->col[j]; + r->col[j] = t; + + u = a_col[i]; + a_col[i] = a_col[j]; + a_col[j] = u; + } + + for (j = 0; j < n; j++) + { + if (j != i && of_mod2_getbit (m->col[j][k0], b0)) + { + s = m->col[j]; + t = m->col[i]; + for (k = k0; k < w; k++) + s[k] ^= t[k]; + s = r->col[j]; + t = r->col[i]; + for (k = 0; k < w; k++) + s[k] ^= t[k]; + } + } + } + + c = 0; + for (i = 0; i < n; i++) + { + if (a_row[i] != -1) + { + a_row[c] = a_row[i]; + a_col[c] = a_col[i]; + c += 1; + } + } +#endif + OF_EXIT_FUNCTION + return c; +} + +#endif /* #if 0 } */ + + +double of_mod2dense_density (of_mod2dense *m) +{ + + OF_ENTER_FUNCTION + UINT32 nb_one = 0; + UINT32 nb_entry = 0; + UINT32 i, j; + double density = 0; +#ifdef COL_ORIENTED + for (j = 0; j < of_mod2dense_cols (m); j++) + { + for (i = 0; i < of_mod2dense_rows (m); i++) + { + if (of_mod2dense_get (m, i, j)) + { + nb_one++; + } + } + } +#else + for (j = 0; j < of_mod2dense_rows (m); j++) + { + for (i = 0; i < of_mod2dense_cols (m); i++) + { + if (of_mod2dense_get (m, j, i)) + { + nb_one++; + } + } + } +#endif + nb_entry = of_mod2dense_rows (m) * of_mod2dense_cols (m); + density = (double) nb_one / nb_entry; + //printf("%s: nb_ones=%d tot_nb_entries=%d, density=%f\n", __FUNCTION__, nb_one, nb_entry, density); + OF_EXIT_FUNCTION + return density; +} + + +/* RETURNS TRUE IF THE SPECIFIED ROW IS EMPTY */ + +bool of_mod2dense_row_is_empty (of_mod2dense *m, + UINT32 row) +{ + UINT32 i; + UINT32 n_w; // number of of_mod2word in the row + of_mod2word *w; // pointer to the current word of the row + + OF_ENTER_FUNCTION +#ifdef OF_DEBUG + if (row >= of_mod2dense_rows (m)) + { + OF_EXIT_FUNCTION + exit(-1); + } +#endif + //n_w = of_mod2dense_cols (m) >> (of_mod2_wordsize_shift); + n_w = m->n_words; + for (i = 0, w = m->row[row]; i < n_w; i++, w++) + { + if (*w != 0) + { + return false; + } + } + return true; +} + + +UINT32 of_mod2dense_row_weight (of_mod2dense *m, UINT32 i) +{ + UINT32 weight = 0; + + OF_ENTER_FUNCTION + if (i >= of_mod2dense_rows (m)) + { + OF_EXIT_FUNCTION + return -1; + } + //of_mod2dense_print_memory_info(m); +#define SLOW_HAMMING_WEIGHT_CALCULATION +#ifdef SLOW_HAMMING_WEIGHT_CALCULATION + UINT32 j; + UINT32 nwords; /* number of of_mod2word in a row */ + //UINT32 weight1 = 0; + + nwords = of_mod2dense_cols (m) >> (of_mod2_wordsize_shift); // number of of_mod2word in a row + + for (j = 0; j < of_mod2dense_cols(m); j++) + { + if (of_mod2dense_get(m, i, j)) + { + weight++; + } + } + //printf("weight method2=%d (standard)\n",weight); +#else + weight = of_hweight_array ((UINT32 *) m->row[i], of_mod2dense_cols (m)); +#endif + + OF_EXIT_FUNCTION + return weight; +} + + +UINT32 of_mod2dense_row_weight_ignore_first (of_mod2dense *m, UINT32 i, UINT32 nb_ignore) +{ + UINT32 weight = 0; + //UINT32 nwords; + UINT32 start0; + + OF_ENTER_FUNCTION + if (i >= of_mod2dense_rows (m)) + { + OF_EXIT_FUNCTION + return -1; + } + + //nwords = of_mod2dense_cols (m) >> of_mod2_wordsize_shift; // number of of_mod2word in a row + start0 = nb_ignore >> (of_mod2_wordsize_shift - 1); + + UINT32 offset32 = nb_ignore >> of_mod2_wordsize_shift; // number of 32bits words that must be ignored + UINT32 rem = of_mod2dense_cols (m) - (offset32 << of_mod2_wordsize_shift); // number of remaining bits to consider + + weight = of_hweight_array ((UINT32 *) & m->row[i][offset32], rem); + OF_EXIT_FUNCTION + return weight; +} + + +UINT32 of_mod2dense_col_weight (of_mod2dense *m, UINT32 i) +{ + OF_ENTER_FUNCTION + UINT32 weight = 0; + if (i >= of_mod2dense_cols (m)) + { + OF_EXIT_FUNCTION + return -1; + } + UINT32 j; + for (j = 0; j < of_mod2dense_rows (m); j++) + { + if (of_mod2dense_get (m, j, i)) + { + weight++; + } + } + OF_EXIT_FUNCTION + return weight; + +} + + +void of_mod2dense_print_stats (FILE *f, of_mod2dense *m) +{ + OF_ENTER_FUNCTION + UINT32 i; + float density = 0; + float row_density = 0; + float col_density = 0; + + /* rows stats*/ + float aver_nb_entry_per_row = 0; + UINT32 max_entry_per_row = 0; + UINT32 min_entry_per_row = 9999999; + UINT32 nb_entry_row[ROW_MAX_ENTRY]; + UINT32 nb_entry_current_row = 0; + UINT32 ctr = 0; + + for (i = 0;i < ROW_MAX_ENTRY;i++) + { + nb_entry_row[i] = 0; + } + for (i = 0; i < of_mod2dense_rows (m); i++) + { + nb_entry_current_row = of_mod2dense_row_weight (m, i); + nb_entry_row[nb_entry_current_row]++; + if (nb_entry_current_row < min_entry_per_row) + { + min_entry_per_row = nb_entry_current_row; + } + if (nb_entry_current_row > max_entry_per_row) + { + max_entry_per_row = nb_entry_current_row; + } + ctr += nb_entry_current_row; + } + aver_nb_entry_per_row = ( (float) ctr) / of_mod2dense_rows (m); + row_density = aver_nb_entry_per_row / (of_mod2dense_cols (m)); + + /* cols stats*/ + float aver_nb_entry_per_col = 0; + UINT32 max_entry_per_col = 0; + UINT32 min_entry_per_col = 9999999; + UINT32 nb_entry_col[COL_MAX_ENTRY]; + UINT32 nb_entry_current_col = 0; + + ctr = 0; + for (i = 0;i < COL_MAX_ENTRY;i++) + { + nb_entry_col[i] = 0; + } + for (i = 0; i < of_mod2dense_cols (m); i++) + { + nb_entry_current_col = of_mod2dense_col_weight (m, i); + nb_entry_col[nb_entry_current_col]++; + if (nb_entry_current_col == 1) + { + //fprintf(f," Warning: col %d has degree 1! \n",i); + } + if (nb_entry_current_col == 0) + { + //fprintf(f," Warning: col %d is empty!! \n",i); + } + if (nb_entry_current_col < min_entry_per_col) + { + min_entry_per_col = nb_entry_current_col; + } + if (nb_entry_current_col > max_entry_per_col) + { + max_entry_per_col = nb_entry_current_col; + } + ctr += nb_entry_current_col; + } + aver_nb_entry_per_col = ( (float) ctr) / of_mod2dense_cols (m); + col_density = aver_nb_entry_per_col / (of_mod2dense_rows (m)); + density = col_density; + + /* print result */ + fprintf (f, " nb_col=%d nb_row=%d \n", of_mod2dense_cols (m), of_mod2dense_rows (m)); + fprintf (f, " row_density=%f \n", row_density); + + fprintf (f, " aver_nb_entry_per_row=%f \n", aver_nb_entry_per_row); + fprintf (f, " min_entry_per_row=%d \n", min_entry_per_row); + fprintf (f, " max_entry_per_row=%d \n", max_entry_per_row); + for (i = min_entry_per_row;i <= max_entry_per_row;i++) + { + fprintf (f, " nb_entry_row[%d]=%d \n", i, nb_entry_row[i]); + } + fprintf (f, "------------------ \n"); + fprintf (f, " col_density=%f \n", col_density); + fprintf (f, " aver_nb_entry_per_col=%f \n", aver_nb_entry_per_col); + fprintf (f, " min_entry_per_col=%d \n", min_entry_per_col); + fprintf (f, " max_entry_per_col=%d \n", max_entry_per_col); + for (i = min_entry_per_col;i <= max_entry_per_col;i++) + { + if (nb_entry_col[i] > 0) + { + fprintf (f, " nb_entry_col[%d]=%d \n", i, nb_entry_col[i]); + } + } + fprintf (f, "------------------ \n"); + fprintf (f, " matrix_density=%f \n", density); + OF_EXIT_FUNCTION +} + + +void of_mod2dense_print_memory_info (of_mod2dense *m) +{ + OF_ENTER_FUNCTION + printf ("m=%p\n", m); + printf ("m->n_rows=%d\n", m->n_rows); + printf ("m->n_cols=%d\n", m->n_cols); + printf ("m->n_words=%d\n", m->n_words); +#ifdef COL_ORIENTED + +#else + printf ("m->row=%p\n", m->row); + printf (" m->row size = %lu\n", m->n_rows*sizeof *m->row); +#endif + printf ("m->bits=%p\n", m->bits); + printf (" m->bits size = %lu\n", m->n_words*m->n_rows*sizeof *m->bits); + printf ("sizeof(mod2word)=%lu\n", sizeof (of_mod2word)); + OF_EXIT_FUNCTION +} + + +void of_mod2dense_xor_rows(of_mod2dense *m, UINT16 from, UINT16 to) +{ + UINT32 i; + of_mod2word *f; + of_mod2word *t; + + f = m->row[from]; + t = m->row[to]; + for (i = 0; i < m->n_words; i++) + { + t[i] ^= f[i]; + } +} + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_dense.h b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_dense.h new file mode 100644 index 0000000..1537692 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_dense.h @@ -0,0 +1,141 @@ +/* $Id: of_matrix_dense.h 197 2014-07-16 15:21:56Z roca $ */ + +/* Copyright (c) 1996, 2000, 2001 by Radford M. Neal + * + * Permission is granted for anyone to copy, use, modify, or distribute this + * program and accompanying programs and documents for any purpose, provided + * this copyright notice is retained and prominently displayed, along with + * a note saying that the original programs are available from Radford Neal's + * web page, and note is made of any changes made to the programs. The + * programs and documents are distributed without any warranty, express or + * implied. As the programs were written for research purposes only, they have + * not been tested to the degree that would be advisable in any important + * application. All use of these programs is entirely at the user's own risk. + */ + +/* + * This module implements operations on matrices of mod2 elements (bits, + * with addition and multiplication being done modulo 2). The matrices + * are stored with consecutive bits of a column packed into words, and + * the procedures are implemented where possible using bit operations + * on these words. This is an appropriate representation when the matrices + * are dense (ie, 0s and 1s are about equally frequent). + * + * All procedures in this module display an error message on standard + * error and terminate the program if passed an invalid argument (indicative + * of a programming error), or if memory cannot be allocated. Errors from + * invalid contents of a file result in an error code being returned to the + * caller, with no message being printed by this module. + */ + + +#ifndef MOD2DENSE_H /* { */ +#define MOD2DENSE_H + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + +/* PACKING OF BITS INTO WORDS. Bits are packed into 32-bit words, with + the low-order bit coming first. */ + +typedef UINT32 of_mod2word; /* Data type that holds packed bits */ + + +#define of_mod2_wordsize 32 /* Number of bits that fit in a of_mod2word. Can't + be increased without changing intio module */ + +#define of_mod2_wordsize_shift 5 /* Amount to shift by to divide by wordsize */ +#define of_mod2_wordsize_mask 0x1f /* What to and with to produce mod wordsize */ + +/* Extract the i'th bit of a of_mod2word. */ +#define of_mod2_getbit(w,i) (((w)>>(i))&1) + +/* Make a word like w, but with the i'th bit set to 1 (if it wasn't already). */ +#define of_mod2_setbit1(w,i) ((w)|(1<<(i))) + +/* Make a word like w, but with the i'th bit set to 0 (if it wasn't already). */ +#define of_mod2_setbit0(w,i) ((w)&(~(1<<(i)))) + + +/* STRUCTURE REPRESENTING A DENSE MATRIX. These structures are dynamically + allocated using mod2dense_allocate (or by other procedures that call + mod2dense_allocate). They should be freed with mod2dense_free when no + longer required. + + Direct access to this structure should be avoided except in low-level + routines. Use the macros and procedures defined below instead. */ + +typedef struct +{ + UINT32 n_rows; /* Number of rows in the matrix */ + UINT32 n_cols; /* Number of columns in the matrix */ + + UINT32 n_words; /* Number of words used to store a column of bits */ + +#ifdef COL_ORIENTED + of_mod2word **col; /* Pointer to array of pointers to columns */ +#else + of_mod2word **row; /* Pointer to array of pointers to row */ +#endif + of_mod2word *bits; /* Pointer to storage block for bits in this matrix + (pieces of this block are pointed to from col) */ +} of_mod2dense; + + +/* MACROS. */ + +#define of_mod2dense_rows(m) ((m)->n_rows) /* Get the number of rows or columns */ +#define of_mod2dense_cols(m) ((m)->n_cols) /* in a matrix */ + + +/* PROCEDURES. */ + +of_mod2dense *of_mod2dense_allocate (UINT32, UINT32); +void of_mod2dense_free (of_mod2dense *); + +void of_mod2dense_clear (of_mod2dense *); +void of_mod2dense_copy (of_mod2dense *, of_mod2dense *); +void of_mod2dense_copyrows (of_mod2dense*, of_mod2dense *, UINT32 *); +void of_mod2dense_copycols (of_mod2dense*, of_mod2dense *, UINT32 *); + +void of_mod2dense_print (FILE *, of_mod2dense *); +UINT32 of_mod2dense_write (FILE *, of_mod2dense *); +of_mod2dense *of_mod2dense_read (FILE *); + +UINT32 of_mod2dense_get (of_mod2dense *, UINT32, UINT32); +INT32 of_mod2dense_set (of_mod2dense *, UINT32, UINT32, UINT32); +UINT32 of_mod2dense_flip (of_mod2dense *, UINT32, UINT32); + +void of_mod2dense_transpose (of_mod2dense *, of_mod2dense *); +void of_mod2dense_add (of_mod2dense *, of_mod2dense *, of_mod2dense *); +void of_mod2dense_multiply (of_mod2dense *, of_mod2dense *, of_mod2dense *); + +UINT32 of_mod2dense_equal (of_mod2dense *, of_mod2dense *); + +UINT32 of_mod2dense_invert (of_mod2dense *, of_mod2dense *); +UINT32 of_mod2dense_forcibly_invert (of_mod2dense *, of_mod2dense *, UINT32 *, UINT32 *); +UINT32 of_mod2dense_invert_selected (of_mod2dense *, of_mod2dense *, UINT32 *, UINT32 *); + +UINT32 of_mod2dense_triangularize (of_mod2dense *, of_mod2dense *); + + +void of_mod2dense_print_bitmap (of_mod2dense *, char *); //MC added +void of_mod2dense_print_memory_info (of_mod2dense *); //MC added +double of_mod2dense_density (of_mod2dense *); // MC added + +bool of_mod2dense_row_is_empty (of_mod2dense *m, UINT32 row); // VR added +UINT32 of_mod2word_weight (of_mod2word); // MC added + +UINT32 of_mod2dense_row_weight (of_mod2dense *, UINT32); // MC added +UINT32 of_mod2dense_row_weight_ignore_first (of_mod2dense *m, UINT32 i, UINT32 nb_ignore);// MC added +UINT32 of_mod2dense_col_weight (of_mod2dense *, UINT32); // MC added + +void of_mod2dense_print_stats (FILE *, of_mod2dense *);// MC added + +//void of_mod2dense_add_row (of_mod2dense *, UINT32 , UINT32); // MC added +//void of_mod2dense_add_row_ignore_first (of_mod2dense *, UINT32 , UINT32, UINT32); // MC added + +void of_mod2dense_xor_rows(of_mod2dense *m, UINT16 from, UINT16 to); +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS + +#endif diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_sparse.c b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_sparse.c new file mode 100644 index 0000000..951b6df --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_sparse.c @@ -0,0 +1,3070 @@ +/* $Id: of_matrix_sparse.c 206 2014-12-10 04:47:09Z roca $ */ +/* + * The contents of this directory and its sub-directories are + * Copyright (c) 1995-2003 by Radford M. Neal + * + * Permission is granted for anyone to copy, use, modify, or distribute these + * programs and accompanying documents for any purpose, provided this copyright + * notice is retained and prominently displayed, along with a note saying + * that the original programs are available from Radford Neal's web page, and + * note is made of any changes made to these programs. These programs and + * documents are distributed without any warranty, express or implied. As the + * programs were written for research purposes only, they have not been tested + * to the degree that would be advisable in any important application. All use + * of these programs is entirely at the user's own risk. + */ + +#include "../of_linear_binary_code.h" + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + +#define ROW_MAX_ENTRY 50 +#define COL_MAX_ENTRY 1000 + +/** + * + */ +static void of_mod2sparse_delete_opt (of_mod2sparse *, of_mod2entry *, of_mod2entry **); + +/** + * + */ +static of_mod2entry * of_mod2sparse_insert_opt (of_mod2sparse *, + UINT32 , + UINT32, + of_mod2entry **__parsing); + + +/* ALLOCATE AN ENTRY WITHIN A MATRIX. This local procedure is used to + allocate a new entry, representing a non-zero element, within a given + matrix. Entries in this matrix that were previously allocated and + then freed are re-used. If there are no such entries, a new block + of entries is allocated. */ + +static of_mod2entry *of_alloc_entry (of_mod2sparse *m) +{ + //OF_ENTER_FUNCTION + of_mod2block *b; + of_mod2entry *e; + INT32 k; + + if (m->next_free == 0) + { + b = (of_mod2block*) of_calloc (1, sizeof * b); + + b->next = m->blocks; + m->blocks = b; + + for (k = 0; k < of_mod2sparse_block; k++) + { + b->entry[k].left = m->next_free; + m->next_free = &b->entry[k]; + } + } + e = m->next_free; + m->next_free = e->left; + //OF_EXIT_FUNCTION + return e; +} + + +/* ALLOCATE SPACE FOR A SPARSE MOD2 MATRIX. */ + +of_mod2sparse *of_mod2sparse_allocate (UINT32 n_rows, /* Number of rows in matrix */ + UINT32 n_cols) /* Number of columns in matrix */ +{ + //OF_ENTER_FUNCTION + of_mod2sparse *m; + of_mod2entry *e; + INT32 i, j; + + if (n_rows <= 0 || n_cols <= 0) + { + OF_PRINT_ERROR(("Invalid number of rows (%d) or columns (%d)\nBoth values must be > 0.\n", n_rows, n_cols)); + OF_EXIT_FUNCTION + return NULL; + } + + m = (of_mod2sparse*) of_calloc (1, sizeof * m); + + m->n_rows = n_rows; + m->n_cols = n_cols; + m->rows = (of_mod2entry*) of_calloc (n_rows, sizeof * m->rows); + m->cols = (of_mod2entry*) of_calloc (n_cols, sizeof * m->cols); + m->blocks = 0; + m->next_free = 0; + + for (i = 0; i < n_rows; i++) + { + e = &m->rows[i]; +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + e->left = e->right = e->up = e->down = e; +#else + e->left = e->right = e->down = e; +#endif + e->row = e->col = -1; + } + + for (j = 0; j < n_cols; j++) + { + e = &m->cols[j]; +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + e->left = e->right = e->up = e->down = e; +#else + e->left = e->right = e->down = e; +#endif + e->row = e->col = -1; + } + +#ifdef LDPC_QC + m->exp_factor = 1; /*default expansion factor */ +#endif + //OF_EXIT_FUNCTION + return m; +} + +/* FREE SPACE OCCUPIED BY A SPARSE MOD2 MATRIX. */ + +void of_mod2sparse_free (of_mod2sparse *m) /* Matrix to free */ +{ + //OF_ENTER_FUNCTION + of_mod2block *b; + + of_free (m->rows); + of_free (m->cols); + + while (m->blocks != 0) + { + b = m->blocks; + m->blocks = b->next; + of_free (b); + } + //OF_EXIT_FUNCTION +} + + +/* CLEAR A SPARSE MATRIX TO ALL ZEROS. */ + +void of_mod2sparse_clear (of_mod2sparse *r) +{ + of_mod2block *b; + of_mod2entry *e; + INT32 i, j; + + OF_ENTER_FUNCTION + for (i = 0; i < of_mod2sparse_rows (r); i++) + { + e = &r->rows[i]; +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + e->left = e->right = e->up = e->down = e; +#else + e->left = e->right = e->down = e; +#endif + } + + for (j = 0; j < of_mod2sparse_cols (r); j++) + { + e = &r->cols[j]; +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + e->left = e->right = e->up = e->down = e; +#else + e->left = e->right = e->down = e; +#endif + } + + while (r->blocks != 0) + { + b = r->blocks; + r->blocks = b->next; + free (b); + } + OF_EXIT_FUNCTION +} + + +/* COPY A SPARSE MATRIX. */ + +void of_mod2sparse_copy (of_mod2sparse *m, /* Matrix to copy */ + of_mod2sparse *r) /* Place to store copy of matrix */ +{ + OF_ENTER_FUNCTION + of_mod2entry *e, *f; + INT32 i; + + if (of_mod2sparse_rows (m) > of_mod2sparse_rows (r) + || of_mod2sparse_cols (m) > of_mod2sparse_cols (r)) + { + OF_PRINT_ERROR(("Destination matrix is too small")); + return; + } + + of_mod2sparse_clear (r); + + for (i = 0; i < of_mod2sparse_rows (m); i++) + { + e = of_mod2sparse_first_in_row (m, i); + + while (!of_mod2sparse_at_end (e)) + { + f = of_mod2sparse_insert (r, e->row, e->col); + e = of_mod2sparse_next_in_row (e); + } + } + OF_EXIT_FUNCTION +} + + +/* COPY ROWS OF A SPARSE MOD2 MATRIX. */ + +void of_mod2sparse_copyrows (of_mod2sparse *m, /* Matrix to copy */ + of_mod2sparse *r, /* Place to store copy of matrix */ + UINT32 *rows) /* Indexes of rows to copy, from 0 */ +{ + of_mod2entry *e; + INT32 i; + + OF_ENTER_FUNCTION + if (of_mod2sparse_cols (m) > of_mod2sparse_cols (r)) + { + OF_PRINT_ERROR(("Destination matrix has fewer columns than source")); + OF_EXIT_FUNCTION + return ; + } + + of_mod2sparse_clear (r); + + for (i = 0; i < of_mod2sparse_rows (r); i++) + { + if (rows[i] >= of_mod2sparse_rows (m)) + { + OF_PRINT_ERROR(("Row index out of range")); + OF_EXIT_FUNCTION + return ; + } + e = of_mod2sparse_first_in_row (m, rows[i]); + while (!of_mod2sparse_at_end (e)) + { + of_mod2sparse_insert (r, i, e->col); + e = of_mod2sparse_next_in_row (e); + } + } + OF_EXIT_FUNCTION +} + + +void of_mod2sparse_copyrows_opt (of_mod2sparse *m, /* Matrix to copy */ + of_mod2sparse *r, /* Place to store copy of matrix */ + UINT32 *rows, /* Indexes of rows to copy, from 0 */ + of_mod2entry **__parsing) +{ + of_mod2entry * __inserted; + bool __was_null = false; + of_mod2entry * __e; + INT32 i; + + OF_ENTER_FUNCTION + if (of_mod2sparse_cols (m) > of_mod2sparse_cols (r)) + { + OF_PRINT_ERROR(("Destination matrix has fewer columns than source")); + OF_EXIT_FUNCTION + return ; + } + + if (__parsing == NULL) + { + __was_null = true; + __parsing = (of_mod2entry **) of_calloc (of_mod2sparse_cols (m), sizeof (of_mod2entry *)); + } + + //of_mod2sparse_clear(r); + + for (i = 0 ; i < of_mod2sparse_rows (r) ; i++) + { + //if (rows[i] < 0 || rows[i] >= of_mod2sparse_rows (m)) + if (rows[i] >= of_mod2sparse_rows (m)) + { + OF_PRINT_LVL (1, ("mod2sparse_copyrows_opt: Row index out of range: rows[i] = %d\n", rows[i])) + OF_PRINT_ERROR(("Row index out of range")); + return ; + } + __e = of_mod2sparse_first_in_row (m, rows[i]); + while (!of_mod2sparse_at_end_row (__e)) + { + __inserted = of_mod2sparse_insert_opt (r, i, of_mod2sparse_col (__e), __parsing); + if (__was_null == true) + { + __parsing[of_mod2sparse_col (__e) ] = __inserted; + } + + __e = of_mod2sparse_next_in_row (__e); + } + } + + if (__was_null == true) + { + of_free (__parsing); + __parsing = NULL; + } + OF_EXIT_FUNCTION +} // of_mod2sparse_copyrows_opt(...) + + +/* COPY COLUMNS OF A SPARSE MOD2 MATRIX. */ + +void of_mod2sparse_copycols (of_mod2sparse *m, /* Matrix to copy */ + of_mod2sparse *r, /* Place to store copy of matrix */ + UINT32 *cols) /* Indexes of columns to copy, from 0 */ +{ + of_mod2entry *e; + INT32 j; + + OF_ENTER_FUNCTION + if (of_mod2sparse_rows (m) > of_mod2sparse_rows (r)) + { + OF_PRINT_ERROR(("Destination matrix has fewer rows than source")); + OF_EXIT_FUNCTION + return ; + } + + of_mod2sparse_clear (r); + + for (j = 0; j < of_mod2sparse_cols (r); j++) + { + //if (cols[j] < 0 || cols[j] >= of_mod2sparse_cols (m)) + if (cols[j] >= of_mod2sparse_cols (m)) + { + OF_PRINT_ERROR(("Column index out of range")); + OF_PRINT_LVL (1, (" mod2sparse_copycols: Column index out of range cols[j] = %d\n", cols[j])) + OF_EXIT_FUNCTION + return ; + } + e = of_mod2sparse_first_in_col (m, cols[j]); + while (!of_mod2sparse_at_end (e)) + { + of_mod2sparse_insert (r, e->row, j); + e = of_mod2sparse_next_in_col (e); + } + } + OF_EXIT_FUNCTION +} + + +void of_mod2sparse_copycols_opt (of_mod2sparse *m, /* Matrix to copy */ + of_mod2sparse *r, /* Place to store copy of matrix */ + UINT32 *cols) /* Indexes of columns to copy, from 0 */ +{ + of_mod2entry ** __parsing; + of_mod2entry * __inserted; + of_mod2entry * __e; + INT32 j; + + OF_ENTER_FUNCTION + if (of_mod2sparse_rows (m) > of_mod2sparse_rows (r)) + { + OF_PRINT_ERROR(("Destination matrix has fewer rows than source")); + OF_EXIT_FUNCTION + return ; + } + + //of_mod2sparse_clear(r); + __parsing = (of_mod2entry **) of_calloc (of_mod2sparse_cols (r), sizeof (of_mod2entry *)); + + for (j = 0 ; j < of_mod2sparse_cols (r) ; j++) + { + //if (cols[j] < 0 || cols[j] >= of_mod2sparse_cols (m)) + if (cols[j] >= of_mod2sparse_cols (m)) + { + OF_PRINT_ERROR(("Column index out of range")); + OF_PRINT_LVL (1, (" mod2sparse_copycols: Column index out of range cols[j] = %d\n", cols[j])) + OF_EXIT_FUNCTION + return ; + } + + __e = of_mod2sparse_first_in_col (m, cols[j]); + while (!of_mod2sparse_at_end_col (__e)) + { + __inserted = of_mod2sparse_insert_opt (r, of_mod2sparse_row (__e), j, __parsing); + __parsing[j] = __inserted; + __e = of_mod2sparse_next_in_col (__e); + } + } + + of_free (__parsing); + __parsing = NULL; + OF_EXIT_FUNCTION +} // of_mod2sparse_copycols_opt(...) + + + + +/* PRINT matrix statistics: average number of 1's per row/line etc ...*/ +void of_mod2sparse_matrix_stats (FILE *f, + of_mod2sparse *m, + UINT32 nb_src , + UINT32 nb_par) +{ + of_mod2entry *e; + INT32 i; + float density = 0; + float row_density = 0; + float col_density = 0; + + /* rows stats*/ + float aver_nb_entry_per_row = 0; + INT32 max_entry_per_row = 0; + INT32 min_entry_per_row = 9999999; + INT32 nb_entry_row[ROW_MAX_ENTRY]; + INT32 nb_entry_current_row = 0; + INT32 ctr = 0; + + /* cols stats*/ + float aver_nb_entry_per_col = 0; + INT32 max_entry_per_col = 0; + INT32 min_entry_per_col = 9999999; + INT32 nb_entry_col[COL_MAX_ENTRY]; + INT32 max_entry_per_data_col = 0; + INT32 min_entry_per_data_col = 9999999; + INT32 max_entry_per_parity_col = 0; + INT32 min_entry_per_parity_col = 9999999; + INT32 nb_entry_data_col[COL_MAX_ENTRY]; + INT32 nb_entry_parity_col[COL_MAX_ENTRY]; + INT32 nb_entry_current_col = 0; + + OF_ENTER_FUNCTION + /* rows stats*/ + memset(nb_entry_row, 0, sizeof(*nb_entry_row)); + + for (i = 0; i < of_mod2sparse_rows (m); i++) + { + e = of_mod2sparse_first_in_row (m, i); + while (!of_mod2sparse_at_end (e)) + { + nb_entry_current_row++; + e = of_mod2sparse_next_in_row (e); + } + + nb_entry_row[nb_entry_current_row]++; + + if (nb_entry_current_row < min_entry_per_row) + { + min_entry_per_row = nb_entry_current_row; + } + if (nb_entry_current_row > max_entry_per_row) + { + max_entry_per_row = nb_entry_current_row; + } + + ctr += nb_entry_current_row; + nb_entry_current_row = 0; + } + + aver_nb_entry_per_row = ( (float) ctr) / of_mod2sparse_rows (m); + row_density = aver_nb_entry_per_row / (of_mod2sparse_cols (m)); + + /* cols stats*/ + ctr = 0; + memset(nb_entry_col, 0, sizeof(*nb_entry_col)); + memset(nb_entry_data_col, 0, sizeof(*nb_entry_data_col)); + memset(nb_entry_parity_col, 0, sizeof(*nb_entry_parity_col)); + + for (i = 0; i < of_mod2sparse_cols (m); i++) + { + e = of_mod2sparse_first_in_col (m, i); + while (!of_mod2sparse_at_end (e)) + { + nb_entry_current_col++; + e = of_mod2sparse_next_in_col (e); + } + + nb_entry_col[nb_entry_current_col]++; + if (nb_entry_current_col == 1) + { + //fprintf(f," Warning: col %d has degree 1! \n",i); + } + if (nb_entry_current_col == 0) + { + //fprintf(f," Warning: col %d is empty!! \n",i); + } + if (i < nb_par) + { + // this is a parity column + + if (nb_entry_current_col < min_entry_per_parity_col) + { + min_entry_per_parity_col = nb_entry_current_col; + } + if (nb_entry_current_col > max_entry_per_parity_col) + { + max_entry_per_parity_col = nb_entry_current_col; + } + nb_entry_parity_col[nb_entry_current_col]++; + } + else + { + // this is a data column + if (nb_entry_current_col < min_entry_per_data_col) + { + min_entry_per_data_col = nb_entry_current_col; + } + if (nb_entry_current_col > max_entry_per_data_col) + { + max_entry_per_data_col = nb_entry_current_col; + } + nb_entry_data_col[nb_entry_current_col]++; + } + + if (nb_entry_current_col < min_entry_per_col) + { + min_entry_per_col = nb_entry_current_col; + } + if (nb_entry_current_col > max_entry_per_col) + { + max_entry_per_col = nb_entry_current_col; + } + + ctr += nb_entry_current_col; + nb_entry_current_col = 0; + } + + aver_nb_entry_per_col = ( (float) ctr) / of_mod2sparse_cols (m); + + col_density = aver_nb_entry_per_col / (of_mod2sparse_rows (m)); + + density = col_density; + + /* print result */ + + fprintf (f, " nb_col=%d nb_row=%d \n", of_mod2sparse_cols (m), of_mod2sparse_rows (m)); + fprintf (f, " row_density=%f \n", row_density); + + fprintf (f, " aver_nb_entry_per_row=%f \n", aver_nb_entry_per_row); + fprintf (f, " min_entry_per_row=%d \n", min_entry_per_row); + fprintf (f, " max_entry_per_row=%d \n", max_entry_per_row); + for (i = min_entry_per_row;i <= max_entry_per_row;i++) + { + fprintf (f, " nb_entry_row[%d]=%d \n", i, nb_entry_row[i]); + } + + fprintf (f, "------------------ \n"); + fprintf (f, " col_density=%f \n", col_density); + fprintf (f, " aver_nb_entry_per_col=%f \n", aver_nb_entry_per_col); + fprintf (f, " min_entry_per_col=%d \n", min_entry_per_col); + fprintf (f, " max_entry_per_col=%d \n", max_entry_per_col); + for (i = min_entry_per_col;i <= max_entry_per_col;i++) + { + if (nb_entry_col[i] > 0) + { + fprintf (f, " nb_entry_col[%d]=%d \n", i, nb_entry_col[i]); + } + } + fprintf (f, "------- \n"); + fprintf (f, " min_entry_per_data_col=%d \n", min_entry_per_data_col); + fprintf (f, " max_entry_per_data_col=%d \n", max_entry_per_data_col); + for (i = min_entry_per_data_col;i <= max_entry_per_data_col;i++) + { + if (nb_entry_data_col[i] > 0) + { + fprintf (f, " nb_entry_data_col[%d]=%d \n", i, nb_entry_data_col[i]); + } + } + fprintf (f, "------- \n"); + + fprintf (f, " min_entry_per_parity_col=%d \n", min_entry_per_parity_col); + fprintf (f, " max_entry_per_parity_col=%d \n", max_entry_per_parity_col); + for (i = min_entry_per_parity_col;i <= max_entry_per_parity_col;i++) + { + if (nb_entry_parity_col[i] > 0) + { + fprintf (f, " nb_entry_parity_col[%d]=%d \n", i, nb_entry_parity_col[i]); + } + } + fprintf (f, "------------------ \n"); + + fprintf (f, " matrix_density=%f \n", density); + OF_EXIT_FUNCTION +} + + +void of_mod2sparse_printf (FILE * fout, + of_mod2sparse * m) +{ + INT32 __row; + + OF_ENTER_FUNCTION + for (__row = 0 ; __row < of_mod2sparse_rows (m) ; __row++) + { + INT32 __col; + for (__col = 0 ; __col < of_mod2sparse_cols (m) ; __col++) + { + if (of_mod2sparse_find (m, __row, __col) != NULL) + fprintf (fout, "1"); + else + //fprintf (fout, "0"); + fprintf (fout, " "); + } + fprintf (fout, "\n"); + OF_EXIT_FUNCTION + } +} // of_mod2sparse_printf(...) + + +void of_mod2sparse_print_bitmap (of_mod2sparse * m) +{ + UINT32 i; + UINT32 x; + UINT32 y; + UINT32 row; + UINT32 col; + UINT32 val = 1; + of_mod2entry *e; +#ifdef IL_SUPPORT + ILuint lImage; + + ilInit(); + ilGenImages(1, &lImage); + ilBindImage(lImage); + //of_mod2dense_print_stats(stdout,m); + ilTexImage(of_mod2sparse_cols(m), of_mod2sparse_rows(m), 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); +#endif + + OF_ENTER_FUNCTION + y = of_mod2dense_rows (m); + x = of_mod2dense_cols (m); + for (row = 0; row < of_mod2sparse_rows(m); row++) + { + for (col = 0; col < of_mod2sparse_cols(m); col++) + { + val = 0; + x = col; + y = of_mod2sparse_rows(m) - row - 1; +#ifdef IL_SUPPORT + ilSetPixels(x, y, 0, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, &val); +#endif + } + } + for (i = 0; i < of_mod2sparse_rows (m); i++) + { + e = of_mod2sparse_first_in_row (m, i); + while (!of_mod2sparse_at_end_row (e)) + { + val = 0xFFFFFF; + row = of_mod2sparse_row(e); + col = of_mod2sparse_col(e); + x = col; + y = of_mod2sparse_rows(m) - row - 1; +#ifdef IL_SUPPORT + ilSetPixels(x ,y, 0, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, &val); +#endif + e = of_mod2sparse_next_in_row(e); + } + } + + //char buffer[100]; + +#ifdef IL_SUPPORT + ilEnable(IL_FILE_OVERWRITE); + ilSaveImage("sparse.bmp"); + // use EOG (Eye of Gnome) in Linux machines. Use something else if needed on other OS. + system("open sparse.bmp"); +#endif + + OF_EXIT_FUNCTION +} // of_mod2sparse_print_bitmap(...) + + +/* PRINT A SPARSE MOD2 MATRIX IN HUMAN-READABLE FORM. */ + +void of_mod2sparse_print +(FILE *f, + of_mod2sparse *m +) +{ + OF_ENTER_FUNCTION + INT32 rdigits, cdigits; + of_mod2entry *e; + INT32 i; + + rdigits = of_mod2sparse_rows (m) <= 10 ? 1 + : of_mod2sparse_rows (m) <= 100 ? 2 + : of_mod2sparse_rows (m) <= 1000 ? 3 + : of_mod2sparse_rows (m) <= 10000 ? 4 + : of_mod2sparse_rows (m) <= 100000 ? 5 + : 6; + + cdigits = of_mod2sparse_cols (m) <= 10 ? 1 + : of_mod2sparse_cols (m) <= 100 ? 2 + : of_mod2sparse_cols (m) <= 1000 ? 3 + : of_mod2sparse_cols (m) <= 10000 ? 4 + : of_mod2sparse_cols (m) <= 100000 ? 5 + : 6; + + for (i = 0; i < of_mod2sparse_rows (m); i++) + { + fprintf (f, "%*d:", rdigits, i); + + e = of_mod2sparse_first_in_row (m, i); + while (!of_mod2sparse_at_end (e)) + { + fprintf (f, " %*d", cdigits, of_mod2sparse_col (e)); + e = of_mod2sparse_next_in_row (e); + } + + fprintf (f, "\n"); + } + OF_EXIT_FUNCTION +} + + +#if 0 +/* WRITE A SPARSE MOD2 MATRIX TO A FILE IN MACHINE-READABLE FORM. */ + +INT32 mod2sparse_write +(FILE *f, + of_mod2sparse *m +) +{ + OF_ENTER_FUNCTION + of_mod2entry *e; + INT32 i; + + of_intio_write (f, m->n_rows); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + + of_intio_write (f, m->n_cols); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + + for (i = 0; i < of_mod2sparse_rows (m); i++) + { + e = of_mod2sparse_first_in_row (m, i); + + if (!of_mod2sparse_at_end (e)) + { + of_intio_write (f, - (i + 1)); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + + while (!of_mod2sparse_at_end (e)) + { + of_intio_write (f, of_mod2sparse_col (e) + 1); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + + e = of_mod2sparse_next_in_row (e); + } + } + } + + of_intio_write (f, 0); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + + OF_EXIT_FUNCTION + return 1; +} + + +/* READ A SPARSE MOD2 MATRIX STORED IN MACHINE-READABLE FORM FROM A FILE. */ + +of_mod2sparse *mod2sparse_read +(FILE *f +) +{ + OF_ENTER_FUNCTION + INT32 n_rows, n_cols; + of_mod2sparse *m; + INT32 v, row, col; + + n_rows = of_intio_read (f); + if (feof (f) || ferror (f) || n_rows <= 0) + { + OF_EXIT_FUNCTION + return 0; + } + + n_cols = of_intio_read (f); + if (feof (f) || ferror (f) || n_cols <= 0) + { + OF_EXIT_FUNCTION + return 0; + } + + m = of_mod2sparse_allocate (n_rows, n_cols); + + row = -1; + + for (;;) + { + v = of_intio_read (f); + if (feof (f) || ferror (f)) + break; + + if (v == 0) + { + OF_EXIT_FUNCTION + return m; + } + else + if (v < 0) + { + row = -v - 1; + if (row >= n_rows) + break; + } + else + { + col = v - 1; + if (col >= n_cols) + break; + if (row == -1) + break; + of_mod2sparse_insert (m, row, col); + } + } + + /* Error if we get here. */ + + of_mod2sparse_free (m); + OF_EXIT_FUNCTION + return 0; +} +#endif /* 0 */ + + +/* WRITE A SPARSE MOD2 MATRIX TO A FILE IN HUMAN-READABLE FORM. */ + +UINT32 of_mod2sparse_write_human_readable (FILE *f, + of_mod2sparse *m, + UINT32 nb_source, + UINT32 nb_parity) +{ + of_mod2entry *e; + INT32 i, col_idx, c; + char buffer [20]; + INT32 str_length; + + OF_ENTER_FUNCTION + memset (buffer, 0, 5); + + str_length = sprintf (buffer, " %d\n", m->n_rows); + fwrite (buffer, str_length, 1, f); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + + str_length = sprintf (buffer, " %d\n", m->n_cols); + fwrite (buffer, str_length, 1, f); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + + str_length = sprintf (buffer, " %d\n", nb_source); + fwrite (buffer, str_length, 1, f); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + + str_length = sprintf (buffer, " %d", nb_parity); + fwrite (buffer, str_length, 1, f); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + + for (i = 0; i < of_mod2sparse_rows (m); i++) + { + e = of_mod2sparse_first_in_row (m, i); + if (!of_mod2sparse_at_end (e)) + { + str_length = sprintf (buffer, "\n %5d", i); + fwrite (buffer, str_length, 1, f); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + // first the source symbols + while (!of_mod2sparse_at_end (e)) + { + c = of_mod2sparse_col (e); + if (c >= nb_parity) + { + col_idx = c - nb_parity; + str_length = sprintf (buffer, " %7d ", col_idx); + fwrite (buffer, str_length, 1, f); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + } + e = of_mod2sparse_next_in_row (e); + } + // then the parity symbols + e = of_mod2sparse_first_in_row (m, i); + while (!of_mod2sparse_at_end (e)) + { + c = of_mod2sparse_col (e); + if (c < nb_parity) + { + col_idx = nb_source + c; + str_length = sprintf (buffer, " %7d ", col_idx); + fwrite (buffer, str_length, 1, f); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + } + e = of_mod2sparse_next_in_row (e); + } + } + } + //of_intio_write(f,0); + if (ferror (f)) + { + OF_EXIT_FUNCTION + return 0; + } + OF_EXIT_FUNCTION + return 1; +} + + +/* READ A SPARSE MOD2 MATRIX STORED IN HUMAN-READABLE FORM FROM A FILE. */ +/* + * Format of the file: + * number_of_line + * number_of_column + * line_number element_column_number ... element_column_number + * . + * . + * . + * line_number element_column_number ... element_column_number + * + */ + +of_mod2sparse *of_mod2sparse_read_human_readable (FILE *f, + UINT32 *nb_source, + UINT32 *nb_parity) +{ + UINT32 n_rows = 0; + UINT32 n_cols = 0; + of_mod2sparse *m; + INT32 col; + INT32 curent_line; + INT32 tmp; + char *pch; + char line[1024]; + + OF_ENTER_FUNCTION + // get the number of row of the matrix + if (fgets (line, sizeof line, f) != NULL) + { + //size_t i = strspn ( line, " \t\n\v" ); + pch = strtok (line, " "); + n_rows = atoi (pch); + //printf("nrows = %d\n",n_rows); + } + // get the number of columns of the matrix + if (fgets (line, sizeof line, f) != NULL) + { + //size_t i = strspn ( line, " \t\n\v" ); + pch = strtok (line, " "); + n_cols = atoi (pch); + //printf("ncol = %d\n",n_cols); + } + // get the number of src symbols of the matrix + if (fgets (line, sizeof line, f) != NULL) + { + //size_t i = strspn ( line, " \t\n\v" ); + pch = strtok (line, " "); + *nb_source = atoi (pch); + //printf("nrows = %d\n",n_rows); + } + // get the number of parity symbols of the matrix + if (fgets (line, sizeof line, f) != NULL) + { + //size_t i = strspn ( line, " \t\n\v" ); + pch = strtok (line, " "); + *nb_parity = atoi (pch); + //printf("ncol = %d\n",n_cols); + } + OF_TRACE_LVL (1, ("nrows= %d ncol = %d nb_src= %d nb_par= %d \n", n_rows, n_cols, *nb_source, *nb_parity)) + if ( (*nb_parity + *nb_source < n_cols) || (*nb_parity < n_rows)) + { + + OF_PRINT_ERROR(("error read file invalid nb_parity nb_source ")); + OF_EXIT_FUNCTION + return NULL; + } + + // allocate the matrix + m = of_mod2sparse_allocate (n_rows, n_cols); + + curent_line = 0; + // process the file line by line + while (fgets (line, sizeof line, f) != NULL) + { + size_t i = strspn (line, " \t\n\v"); + + if (line[i] == '#') + continue; + //printf("line : %s \n",line); + + // get the first token: should be the line number + pch = strtok (line, " "); + //printf ("%s\n",pch); + // get the first token of the line: the line number + tmp = atoi (pch); + + if (tmp != curent_line) + { + fprintf (stderr, "Error reading file: reading line %d should be %d\n", tmp, curent_line); + OF_EXIT_FUNCTION + return NULL; + } + // get the following, the colunm numbers of the non-zero entries + // of the matrix line + pch = strtok (NULL, " "); + while (pch != NULL) + { + if (strcmp (pch, "\n") != 0) + { + //printf ("pcg = \"%s\"\n",pch); + // get the column number of the new element + tmp = atoi (pch); + //printf("inserting entry : (%d,%d)\n",curent_line ,tmp); + // insert the new element + if (tmp < *nb_source) + { + col = tmp + *nb_parity; + } + else + { + col = tmp - *nb_source; + } + of_mod2sparse_insert (m, curent_line, col); + //of_mod2entry e = m->cols[col]; + } + else + { + //printf("skipping pch : it is a EOL\n"); + } + pch = strtok (NULL, " "); + } + curent_line++; + } + + OF_EXIT_FUNCTION + return m; +} + + +/* LOOK FOR AN ENTRY WITH GIVEN ROW AND COLUMN. */ + +of_mod2entry *of_mod2sparse_find (of_mod2sparse *m, + UINT32 row, + UINT32 col) +{ + //OF_ENTER_FUNCTION + of_mod2entry *re, *ce; + + //if (row < 0 || row >= of_mod2sparse_rows (m) || col < 0 || col >= of_mod2sparse_cols (m)) + if (row >= of_mod2sparse_rows (m) || col >= of_mod2sparse_cols (m)) + { + fprintf (stderr, "mod2sparse_find: row or column index out of bounds\n"); + OF_EXIT_FUNCTION + return NULL; + } + + /* Check last entries in row. */ + + re = of_mod2sparse_last_in_row (m, row); + if (of_mod2sparse_at_end (re) || of_mod2sparse_col (re) < col) + { + //OF_EXIT_FUNCTION + return 0; + } + if (of_mod2sparse_col (re) == col) + { + //OF_EXIT_FUNCTION + return re; + } + +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + ce = of_mod2sparse_last_in_col (m, col); + if (of_mod2sparse_at_end (ce) || of_mod2sparse_row (ce) < row) + { + //OF_EXIT_FUNCTION + return 0; + } + if (of_mod2sparse_row (ce) == row) + { + //OF_EXIT_FUNCTION + return ce; + } +#endif + + /* Search row and column in parallel, from the front. */ + + re = of_mod2sparse_first_in_row (m, row); + ce = of_mod2sparse_first_in_col (m, col); + + for (;;) + { + if (of_mod2sparse_at_end (re) || of_mod2sparse_col (re) > col) + { + //OF_EXIT_FUNCTION + return 0; + } + if (of_mod2sparse_col (re) == col) + { + //OF_EXIT_FUNCTION + return re; + } + + if (of_mod2sparse_at_end (ce) || of_mod2sparse_row (ce) > row) + { + //OF_EXIT_FUNCTION + return 0; + } + if (of_mod2sparse_row (ce) == row) + { + //OF_EXIT_FUNCTION + return ce; + } + re = of_mod2sparse_next_in_row (re); + ce = of_mod2sparse_next_in_col (ce); + } + //OF_EXIT_FUNCTION +} + + +/* INSERT AN ENTRY WITH GIVEN ROW AND COLUMN. */ + +of_mod2entry *of_mod2sparse_insert (of_mod2sparse *m, + UINT32 row, + UINT32 col) +{ + //OF_ENTER_FUNCTION +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + of_mod2entry *re, *ce, *ne; +#else + of_mod2entry *re, *ce, *ne, *ce2; +#endif + + //if (row < 0 || row >= of_mod2sparse_rows (m) || col < 0 || col >= of_mod2sparse_cols (m)) + if (row >= of_mod2sparse_rows (m) || col >= of_mod2sparse_cols (m)) + { + fprintf (stderr, "mod2sparse_insert: row or column index out of bounds\n"); + OF_EXIT_FUNCTION + return NULL; + } + //printf("inserting %d %d \n",row,col); + /* Find old entry and return it, or allocate new entry and insert into row. */ + + re = of_mod2sparse_last_in_row (m, row); + + if (!of_mod2sparse_at_end (re) && of_mod2sparse_col (re) == col) + { + OF_EXIT_FUNCTION + return re; + } + + if (of_mod2sparse_at_end (re) || of_mod2sparse_col (re) < col) + { + re = re->right; + } + else + { + re = of_mod2sparse_first_in_row (m, row); + for (;;) + { + if (!of_mod2sparse_at_end (re) && of_mod2sparse_col (re) == col) + { + OF_EXIT_FUNCTION + return re; + } + if (of_mod2sparse_at_end (re) || of_mod2sparse_col (re) > col) + { + break; + } + re = of_mod2sparse_next_in_row (re); + } + } + + ne = of_alloc_entry (m); + + ne->row = row; + ne->col = col; + + ne->left = re->left; + ne->right = re; + ne->left->right = ne; + ne->right->left = ne; + + /* Insert new entry into column. */ + +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + /* If we find an existing entry here, + the matrix must be garbled, since we didn't find it in the row. */ + + ce = of_mod2sparse_last_in_col (m, col); + + if (!of_mod2sparse_at_end (ce) && of_mod2sparse_row (ce) == row) + { + fprintf (stderr, "mod2sparse_insert: Garbled matrix\n"); + OF_EXIT_FUNCTION + return NULL; + } + + if (of_mod2sparse_at_end (ce) || of_mod2sparse_row (ce) < row) + { + ce = ce->down; + } + else + { +#else + ce2 = & (m->cols[col]); +#endif + ce = of_mod2sparse_first_in_col (m, col); + + for (;;) + { + if (!of_mod2sparse_at_end (ce) && of_mod2sparse_row (ce) == row) + { + fprintf (stderr, "mod2sparse_insert: Garbled matrix\n"); + OF_EXIT_FUNCTION + return NULL; + } + + if (of_mod2sparse_at_end (ce) || of_mod2sparse_row (ce) > row) + { + break; + } +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + ce2 = ce; +#endif + ce = of_mod2sparse_next_in_col (ce); + } + +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + } + + ne->up = ce->up; + ne->down = ce; + ne->up->down = ne; + ne->down->up = ne; +#else + ne->down = ce; + ce2->down = ne; +#endif + + /* Return the new entry. */ + //OF_EXIT_FUNCTION + return ne; +} + + +static of_mod2entry * of_mod2sparse_insert_opt (of_mod2sparse *m, + UINT32 row, + UINT32 col, + of_mod2entry **__parsing) +{ + of_mod2entry * __right_entry, * __col_entry, * __new_entry; +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + of_mod2entry * __col_entry_; +#endif + + OF_ENTER_FUNCTION + //if (row < 0 || row >= of_mod2sparse_rows (m) || col < 0 || col >= of_mod2sparse_cols (m)) + if (row >= of_mod2sparse_rows (m) || col >= of_mod2sparse_cols (m)) + { + fprintf (stderr, "mod2sparse_insert: row or column index out of bounds\n"); + OF_EXIT_FUNCTION + return NULL; + } + + /* Find old entry and return it, or allocate new entry and insert into row. */ + + __right_entry = of_mod2sparse_last_in_row (m, row); + + if (!of_mod2sparse_at_end (__right_entry) && of_mod2sparse_col (__right_entry) == col) + { + OF_EXIT_FUNCTION + return __right_entry; + } + + if (of_mod2sparse_at_end (__right_entry) || of_mod2sparse_col (__right_entry) < col) + { + __right_entry = __right_entry->right; + } + else + { + __right_entry = of_mod2sparse_first_in_row (m, row); + + for (;;) + { + if (!of_mod2sparse_at_end (__right_entry) && of_mod2sparse_col (__right_entry) == col) + { + OF_EXIT_FUNCTION + return __right_entry; + } + + if (of_mod2sparse_at_end (__right_entry) || of_mod2sparse_col (__right_entry) > col) + { + break; + } + + __right_entry = of_mod2sparse_next_in_row (__right_entry); + } + } + + __new_entry = of_alloc_entry (m); + + __new_entry->row = row; + __new_entry->col = col; + + __new_entry->left = __right_entry->left; + __new_entry->right = __right_entry; + __new_entry->left->right = __new_entry; + __new_entry->right->left = __new_entry; + + /* Insert new entry into column. */ + if (__parsing != NULL) + { + if (__parsing[of_mod2sparse_col (__new_entry) ] != NULL) + { + __col_entry = __parsing[of_mod2sparse_col (__new_entry) ]; + } + else + { + __col_entry = of_mod2sparse_first_in_col (m, of_mod2sparse_col (__new_entry)); + } + } + else + { + __col_entry = of_mod2sparse_first_in_col (m, of_mod2sparse_col (__new_entry)); + } // if (__parsing != NULL) ... + +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __col_entry; +#endif // #ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + while (!of_mod2sparse_at_end_col (__col_entry) && of_mod2sparse_row (__col_entry) < row) + { +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __col_entry; +#endif // #ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry = of_mod2sparse_next_in_col (__col_entry); + } // while (!of_mod2sparse_at_end_col(__col_entry) && of_mod2sparse_row(__col_entry) <= row) ... + + __new_entry->down = __col_entry; +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __new_entry->up = __col_entry->up; + __new_entry->up->down = __new_entry; + __new_entry->down->up = __new_entry; +#else // #ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_->down = __new_entry; +#endif // #ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE ... #else ... + + OF_EXIT_FUNCTION + /* Return the new entry. */ + return __new_entry; +} + + +/* DELETE AN ENTRY FROM A SPARSE MATRIX. */ +void of_mod2sparse_delete (of_mod2sparse *m, + of_mod2entry *e) +{ + OF_ENTER_FUNCTION +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + of_mod2entry *ce; +#endif + + if (e == 0) + { + fprintf (stderr, "mod2sparse_delete: Trying to delete a null entry\n"); + OF_EXIT_FUNCTION + return; + } + if ((of_mod2sparse_row (e) < 0) || (of_mod2sparse_col (e) < 0)) + { + fprintf (stderr, "mod2sparse_delete: Trying to delete a header entry (row=%d, col=%d)\n", e->row, e->col); + OF_EXIT_FUNCTION + return ; + } +#ifdef OF_DEBUG + /* Sanity: check that the entry is in the list before trying to remove it. + * Define this check only if in doubt since this is very computing intensive! */ + of_mod2entry *tmp_e; + for (tmp_e = of_mod2sparse_first_in_col(m, of_mod2sparse_col(e)); tmp_e != e; tmp_e = tmp_e->down) + { + if (of_mod2sparse_at_end_col(tmp_e)) + { + fprintf (stderr, "mod2sparse_delete: error, entry %d/%d not found in column\n", + e->row, e->col); + ASSERT(0); + OF_EXIT_FUNCTION + return; + } + } +#endif +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + e->up->down = e->down; + e->down->up = e->up; +#else + ce = & (m->cols[of_mod2sparse_col(e)]); + for (; ce->down != e; ce = ce->down); /* find the entry before the one to delete */ + ce->down = e->down; +#endif + + e->left->right = e->right; + e->right->left = e->left; + + e->left = m->next_free; + m->next_free = e; + OF_EXIT_FUNCTION +} + + +void of_mod2sparse_delete_opt (of_mod2sparse * m, + of_mod2entry * e, + of_mod2entry ** __parsing) +{ + OF_ENTER_FUNCTION +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + of_mod2entry * ce; +#endif + + if (e == NULL) + { + fprintf (stderr, "mod2sparse_delete: Trying to delete a null entry\n"); + OF_EXIT_FUNCTION + return ; + } + if ((of_mod2sparse_row (e) < 0) || (of_mod2sparse_col (e) < 0)) + { + fprintf (stderr, "mod2sparse_delete: Trying to delete a header entry (row=%d, col=%d)\n", e->row, e->col); + OF_EXIT_FUNCTION + return ; + } +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + e->up->down = e->down; + e->down->up = e->up; +#else + if (__parsing != NULL) + { + ce = __parsing[of_mod2sparse_col (e) ]; + } + else + { + ce = & (m->cols[of_mod2sparse_col (e) ]); + } + while (!of_mod2sparse_at_end_col (ce)) + { + ce = of_mod2sparse_next_in_col (ce); + } + ce->down = e->down; +#endif + + e->left->right = e->right; + e->right->left = e->left; + + e->left = m->next_free; + m->next_free = e; + OF_EXIT_FUNCTION +} + + +#if 0 + +/* TEST WHETHER TWO SPARSE MATRICES ARE EQUAL. */ + +INT32 mod2sparse_equal +(of_mod2sparse *m1, + of_mod2sparse *m2 +) +{ + OF_ENTER_FUNCTION + of_mod2entry *e1, *e2; + INT32 i; + + if (of_mod2sparse_rows (m1) != of_mod2sparse_rows (m2) + || of_mod2sparse_cols (m1) != of_mod2sparse_cols (m2)) + { + fprintf (stderr, "mod2sparse_equal: Matrices have different dimensions\n"); + OF_EXIT_FUNCTION + return 0; + } + + for (i = 0; i < of_mod2sparse_rows (m1); i++) + { + e1 = of_mod2sparse_first_in_row (m1, i); + e2 = of_mod2sparse_first_in_row (m2, i); + + while (!of_mod2sparse_at_end (e1) && !of_mod2sparse_at_end (e2)) + { + if (of_mod2sparse_col (e1) != of_mod2sparse_col (e2)) + { + OF_EXIT_FUNCTION + return 0; + } + + e1 = of_mod2sparse_next_in_row (e1); + e2 = of_mod2sparse_next_in_row (e2); + } + + if (!of_mod2sparse_at_end (e1) || !of_mod2sparse_at_end (e2)) + { + OF_EXIT_FUNCTION + return 0; + } + } + + OF_EXIT_FUNCTION + return 1; +} + + +/* COMPUTE THE TRANSPOSE OF A SPARSE MOD2 MATRIX. */ + +void mod2sparse_transpose +(of_mod2sparse *m, /* Matrix to compute transpose of (left unchanged) */ + of_mod2sparse *r /* Result of transpose operation */ +) +{ + OF_ENTER_FUNCTION + of_mod2entry *e; + INT32 i; + + if (of_mod2sparse_rows (m) != of_mod2sparse_cols (r) + || of_mod2sparse_cols (m) != of_mod2sparse_rows (r)) + { + fprintf (stderr, + "mod2sparse_transpose: Matrices have incompatible dimensions\n"); + OF_EXIT_FUNCTION + return NULL; + } + + if (r == m) + { + fprintf (stderr, + "mod2sparse_transpose: Result matrix is the same as the operand\n"); + OF_EXIT_FUNCTION + return NULL; + } + + of_mod2sparse_clear (r); + + for (i = 0; i < of_mod2sparse_rows (m); i++) + { + e = of_mod2sparse_first_in_row (m, i); + + while (!of_mod2sparse_at_end (e)) + { + of_mod2sparse_insert (r, of_mod2sparse_col (e), i); + e = of_mod2sparse_next_in_row (e); + } + } + OF_EXIT_FUNCTION +} + + +/* ADD TWO SPARSE MOD2 MATRICES. */ + +void mod2sparse_add +(of_mod2sparse *m1, /* Left operand of add */ + of_mod2sparse *m2, /* Right operand of add */ + of_mod2sparse *r /* Place to store result of add */ +) +{ + OF_ENTER_FUNCTION + of_mod2entry *e1, *e2; + INT32 i; + + if (of_mod2sparse_rows (m1) != of_mod2sparse_rows (r) + || of_mod2sparse_cols (m1) != of_mod2sparse_cols (r) + || of_mod2sparse_rows (m2) != of_mod2sparse_rows (r) + || of_mod2sparse_cols (m2) != of_mod2sparse_cols (r)) + { + fprintf (stderr, "mod2sparse_add: Matrices have different dimensions\n"); + OF_EXIT_FUNCTION + return NULL; + } + + if (r == m1 || r == m2) + { + fprintf (stderr, + "mod2sparse_add: Result matrix is the same as one of the operands\n"); + OF_EXIT_FUNCTION + return NULL; + } + + of_mod2sparse_clear (r); + + for (i = 0; i < of_mod2sparse_rows (r); i++) + { + e1 = of_mod2sparse_first_in_row (m1, i); + e2 = of_mod2sparse_first_in_row (m2, i); + + while (!of_mod2sparse_at_end (e1) && !of_mod2sparse_at_end (e2)) + { + if (of_mod2sparse_col (e1) == of_mod2sparse_col (e2)) + { + e1 = of_mod2sparse_next_in_row (e1); + e2 = of_mod2sparse_next_in_row (e2); + } + + else + if (of_mod2sparse_col (e1) < of_mod2sparse_col (e2)) + { + of_mod2sparse_insert (r, i, of_mod2sparse_col (e1)); + e1 = of_mod2sparse_next_in_row (e1); + } + + else + { + of_mod2sparse_insert (r, i, of_mod2sparse_col (e2)); + e2 = of_mod2sparse_next_in_row (e2); + } + } + + while (!of_mod2sparse_at_end (e1)) + { + of_mod2sparse_insert (r, i, of_mod2sparse_col (e1)); + e1 = of_mod2sparse_next_in_row (e1); + } + + while (!of_mod2sparse_at_end (e2)) + { + of_mod2sparse_insert (r, i, of_mod2sparse_col (e2)); + e2 = of_mod2sparse_next_in_row (e2); + } + } + OF_EXIT_FUNCTION +} + + +/* MULTIPLY TWO SPARSE MOD2 MATRICES. */ + +void mod2sparse_multiply +(of_mod2sparse *m1, /* Left operand of multiply */ + of_mod2sparse *m2, /* Right operand of multiply */ + of_mod2sparse *r /* Place to store result of multiply */ +) +{ + OF_ENTER_FUNCTION + of_mod2entry *e1, *e2; + INT32 i, j, b; + + if (of_mod2sparse_cols (m1) != of_mod2sparse_rows (m2) + || of_mod2sparse_rows (m1) != of_mod2sparse_rows (r) + || of_mod2sparse_cols (m2) != of_mod2sparse_cols (r)) + { + fprintf (stderr, + "mod2sparse_multiply: Matrices have incompatible dimensions\n"); + OF_EXIT_FUNCTION + return NULL; + } + + if (r == m1 || r == m2) + { + fprintf (stderr, + "mod2sparse_multiply: Result matrix is the same as one of the operands\n"); + OF_EXIT_FUNCTION + return NULL; + } + + of_mod2sparse_clear (r); + + for (i = 0; i < of_mod2sparse_rows (m1); i++) + { + if (of_mod2sparse_at_end (of_mod2sparse_first_in_row (m1, i))) + { + continue; + } + + for (j = 0; j < of_mod2sparse_cols (m2); j++) + { + b = 0; + + e1 = of_mod2sparse_first_in_row (m1, i); + e2 = of_mod2sparse_first_in_col (m2, j); + + while (!of_mod2sparse_at_end (e1) && !of_mod2sparse_at_end (e2)) + { + if (of_mod2sparse_col (e1) == of_mod2sparse_row (e2)) + { + b ^= 1; + e1 = of_mod2sparse_next_in_row (e1); + e2 = of_mod2sparse_next_in_col (e2); + } + + else + if (of_mod2sparse_col (e1) < of_mod2sparse_row (e2)) + { + e1 = of_mod2sparse_next_in_row (e1); + } + + else + { + e2 = of_mod2sparse_next_in_col (e2); + } + } + + if (b) + { + of_mod2sparse_insert (r, i, j); + } + } + } + OF_EXIT_FUNCTION +} + + +/* MULTIPLY VECTOR BY SPARSE MATRIX. */ + +void mod2sparse_mulvec +(of_mod2sparse *m, /* The sparse matrix, with M rows and N columns */ + UINT8 *u, /* The input vector, N long */ + UINT8 *v /* Place to store the result, M long */ +) +{ + OF_ENTER_FUNCTION + of_mod2entry *e; + INT32 M, N; + INT32 i, j; + + M = of_mod2sparse_rows (m); + N = of_mod2sparse_cols (m); + + for (i = 0; i < M; i++) + v[i] = 0; + + for (j = 0; j < N; j++) + { + if (u[j]) + { + for (e = of_mod2sparse_first_in_col (m, j); + !of_mod2sparse_at_end (e); + e = of_mod2sparse_next_in_col (e)) + { + v[of_mod2sparse_row (e) ] ^= 1; + } + } + } + OF_EXIT_FUNCTION +} + + +/* COUNT ENTRIES IN A ROW. */ + +UINT32 mod2sparse_count_row +(of_mod2sparse *m, + UINT32 row +) +{ + OF_ENTER_FUNCTION + of_mod2entry *e; + INT32 count; + + if (row < 0 || row >= of_mod2sparse_rows (m)) + { + fprintf (stderr, "mod2sparse_count_row: row index out of bounds\n"); + OF_EXIT_FUNCTION + return NULL; + } + + count = 0; + + for (e = of_mod2sparse_first_in_row (m, row); + !of_mod2sparse_at_end (e); + e = of_mod2sparse_next_in_row (e)) + { + count += 1; + } + + OF_EXIT_FUNCTION + return count; +} + + +/* COUNT ENTRIES IN A COLUMN. */ + +UINT32 mod2sparse_count_col +(of_mod2sparse *m, + UINT32 col +) +{ + OF_ENTER_FUNCTION + of_mod2entry *e; + INT32 count; + + if (col < 0 || col >= of_mod2sparse_cols (m)) + { + fprintf (stderr, "mod2sparse_count_col: column index out of bounds\n"); + OF_EXIT_FUNCTION + return NULL; + } + + count = 0; + + for (e = of_mod2sparse_first_in_col (m, col); + !of_mod2sparse_at_end (e); + e = of_mod2sparse_next_in_col (e)) + { + count += 1; + } + + OF_EXIT_FUNCTION + return count; +} + + +/* ADD TO A ROW. */ + +void mod2sparse_add_row +(of_mod2sparse *m1, /* Matrix containing row to add to */ + UINT32 row1, /* Index in this matrix of row to add to */ + of_mod2sparse *m2, /* Matrix containing row to add from */ + UINT32 row2 /* Index in this matrix of row to add from */ +) +{ + OF_ENTER_FUNCTION + of_mod2entry *f1, *f2, *ft; + + if (of_mod2sparse_cols (m1) < of_mod2sparse_cols (m2)) + { + fprintf (stderr, + "mod2sparse_add_row: row added to is shorter than row added from\n"); + OF_EXIT_FUNCTION + return NULL; + } + + if (row1 < 0 || row1 >= of_mod2sparse_rows (m1) + || row2 < 0 || row2 >= of_mod2sparse_rows (m2)) + { + fprintf (stderr, "mod2sparse_add_row: row index out of range\n"); + OF_EXIT_FUNCTION + return NULL; + } + + f1 = of_mod2sparse_first_in_row (m1, row1); + f2 = of_mod2sparse_first_in_row (m2, row2); + + while (!of_mod2sparse_at_end (f1) && !of_mod2sparse_at_end (f2)) + { + if (of_mod2sparse_col (f1) > of_mod2sparse_col (f2)) + { + of_mod2sparse_insert (m1, row1, of_mod2sparse_col (f2)); + f2 = of_mod2sparse_next_in_row (f2); + } + else + { + ft = of_mod2sparse_next_in_row (f1); + if (of_mod2sparse_col (f1) == of_mod2sparse_col (f2)) + { + of_mod2sparse_delete (m1, f1); + f2 = of_mod2sparse_next_in_row (f2); + } + f1 = ft; + } + } + + while (!of_mod2sparse_at_end (f2)) + { + of_mod2sparse_insert (m1, row1, of_mod2sparse_col (f2)); + f2 = of_mod2sparse_next_in_row (f2); + } + + OF_EXIT_FUNCTION +} + + +/* ADD TO A COLUMN. */ + +void mod2sparse_add_col +(of_mod2sparse *m1, /* Matrix containing column to add to */ + UINT32 col1, /* Index in this matrix of column to add to */ + of_mod2sparse *m2, /* Matrix containing column to add from */ + UINT32 col2 /* Index in this matrix of column to add from */ +) +{ + OF_ENTER_FUNCTION + of_mod2entry *f1, *f2, *ft; + + if (of_mod2sparse_rows (m1) < of_mod2sparse_rows (m2)) + { + fprintf (stderr, + "mod2sparse_add_col: Column added to is shorter than column added from\n"); + OF_EXIT_FUNCTION + return NULL; + } + + if (col1 < 0 || col1 >= of_mod2sparse_cols (m1) + || col2 < 0 || col2 >= of_mod2sparse_cols (m2)) + { + fprintf (stderr, "mod2sparse_add_col: Column index out of range\n"); + OF_EXIT_FUNCTION + return NULL; + } + + f1 = of_mod2sparse_first_in_col (m1, col1); + f2 = of_mod2sparse_first_in_col (m2, col2); + + while (!of_mod2sparse_at_end (f1) && !of_mod2sparse_at_end (f2)) + { + if (of_mod2sparse_row (f1) > of_mod2sparse_row (f2)) + { + of_mod2sparse_insert (m1, of_mod2sparse_row (f2), col1); + f2 = of_mod2sparse_next_in_col (f2); + } + else + { + ft = of_mod2sparse_next_in_col (f1); + if (of_mod2sparse_row (f1) == of_mod2sparse_row (f2)) + { + of_mod2sparse_delete (m1, f1); + f2 = of_mod2sparse_next_in_col (f2); + } + f1 = ft; + } + } + + while (!of_mod2sparse_at_end (f2)) + { + of_mod2sparse_insert (m1, of_mod2sparse_row (f2), col1); + f2 = of_mod2sparse_next_in_col (f2); + } + + OF_EXIT_FUNCTION +} + + +/* FIND AN LU DECOMPOSITION OF A SPARSE MATRIX. */ + +UINT32 mod2sparse_decomp +(of_mod2sparse *A, /* Input matrix, M by N */ + UINT32 K, /* Size of sub-matrix to find LU decomposition of */ + of_mod2sparse *L, /* Matrix in which L is stored, M by K */ + of_mod2sparse *U, /* Matrix in which U is stored, K by N */ + UINT32 *rows, /* Array where row indexes are stored, M long */ + UINT32 *cols, /* Array where column indexes are stored, N long */ + mod2sparse_strategy strategy, /* Strategy to follow in picking rows/columns */ + UINT32 abandon_number, /* Number of columns to abandon at some point */ + UINT32 abandon_when /* When to abandon these columns */ +) +{ + OF_ENTER_FUNCTION + UINT32 *rinv = NULL, *cinv = NULL, *acnt = NULL, *rcnt = NULL; + of_mod2sparse *B = NULL; + UINT32 M, N; + + of_mod2entry *e = NULL, *f = NULL, *fn = NULL, *e2 = NULL; + INT32 i = 0, j = 0, k = 0, cc = 0, cc2 = 0, cc3 = 0, cr2 = 0, pr = 0; + INT32 found, nnf; + + M = of_mod2sparse_rows (A); + N = of_mod2sparse_cols (A); + + if (of_mod2sparse_cols (L) != K || of_mod2sparse_rows (L) != M + || of_mod2sparse_cols (U) != N || of_mod2sparse_rows (U) != K) + { + fprintf (stderr, + "mod2sparse_decomp: Matrices have incompatible dimensions\n"); + OF_EXIT_FUNCTION + return NULL; + } + + if (abandon_number > N - K) + { + fprintf (stderr, "Trying to abandon more columns than allowed\n"); + OF_EXIT_FUNCTION + return NULL; + } + + rinv = (UINT32*) of_calloc (M, sizeof * rinv); + cinv = (UINT32*) of_calloc (N, sizeof * cinv); + + if (abandon_number > 0) + { + acnt = (UINT32*) of_calloc (M + 1, sizeof * acnt); + } + + if (strategy == Mod2sparse_minprod) + { + rcnt = (UINT32*) of_calloc (M, sizeof * rcnt); + } + + of_mod2sparse_clear (L); + of_mod2sparse_clear (U); + + /* Copy A to B. B will be modified, then discarded. */ + + B = of_mod2sparse_allocate (M, N); + of_mod2sparse_copy (A, B); + + /* Count 1s in rows of B, if using minprod strategy. */ + + if (strategy == Mod2sparse_minprod) + { + for (i = 0; i < M; i++) + { + rcnt[i] = mod2sparse_count_row (B, i); + } + } + + /* Set up initial row and column choices. */ + + for (i = 0; i < M; i++) + rows[i] = rinv[i] = i; + for (j = 0; j < N; j++) + cols[j] = cinv[j] = j; + + /* Find L and U one column at a time. */ + + nnf = 0; + + for (i = 0; i < K; i++) + { + /* Choose the next row and column of B. */ + + switch (strategy) + { + case Mod2sparse_first: + { + found = 0; + + for (k = i; k < N; k++) + { + e = of_mod2sparse_first_in_col (B, cols[k]); + while (!of_mod2sparse_at_end (e)) + { + if (rinv[of_mod2sparse_row (e) ] >= i) + { + found = 1; + goto out_first; + } + e = of_mod2sparse_next_in_col (e); + } + } + +out_first: + break; + } + + case Mod2sparse_mincol: + { + found = 0; + + for (j = i; j < N; j++) + { + cc2 = mod2sparse_count_col (B, cols[j]); + if (!found || cc2 < cc) + { + e2 = of_mod2sparse_first_in_col (B, cols[j]); + while (!of_mod2sparse_at_end (e2)) + { + if (rinv[of_mod2sparse_row (e2) ] >= i) + { + found = 1; + cc = cc2; + e = e2; + k = j; + break; + } + e2 = of_mod2sparse_next_in_col (e2); + } + } + } + + break; + } + + case Mod2sparse_minprod: + { + found = 0; + + for (j = i; j < N; j++) + { + cc2 = mod2sparse_count_col (B, cols[j]); + e2 = of_mod2sparse_first_in_col (B, cols[j]); + while (!of_mod2sparse_at_end (e2)) + { + if (rinv[of_mod2sparse_row (e2) ] >= i) + { + cr2 = rcnt[of_mod2sparse_row (e2) ]; + if (!found || cc2 == 1 || (cc2 - 1) * (cr2 - 1) < pr) + { + found = 1; + pr = cc2 == 1 ? 0 : (cc2 - 1) * (cr2 - 1); + e = e2; + k = j; + } + } + e2 = of_mod2sparse_next_in_col (e2); + } + } + + break; + } + + default: + { + fprintf (stderr, "mod2sparse_decomp: Unknown stategy\n"); + OF_EXIT_FUNCTION + return NULL; + } + } + + if (!found) + { + nnf += 1; + } + + /* Update 'rows' and 'cols'. Looks at 'k' and 'e' found above. */ + + if (found) + { + if (cinv[of_mod2sparse_col (e) ] != k) + abort(); + + cols[k] = cols[i]; + cols[i] = of_mod2sparse_col (e); + + cinv[cols[k]] = k; + cinv[cols[i]] = i; + + k = rinv[of_mod2sparse_row (e) ]; + + if (k < i) + abort(); + + rows[k] = rows[i]; + rows[i] = of_mod2sparse_row (e); + + rinv[rows[k]] = k; + rinv[rows[i]] = i; + } + + /* Update L, U, and B. */ + + f = of_mod2sparse_first_in_col (B, cols[i]); + + while (!of_mod2sparse_at_end (f)) + { + fn = of_mod2sparse_next_in_col (f); + k = of_mod2sparse_row (f); + + if (rinv[k] > i) + { + mod2sparse_add_row (B, k, B, of_mod2sparse_row (e)); + if (strategy == Mod2sparse_minprod) + { + rcnt[k] = mod2sparse_count_row (B, k); + } + of_mod2sparse_insert (L, k, i); + } + else + if (rinv[k] < i) + { + of_mod2sparse_insert (U, rinv[k], cols[i]); + } + else + { + of_mod2sparse_insert (L, k, i); + of_mod2sparse_insert (U, i, cols[i]); + } + + f = fn; + } + + /* Get rid of all entries in the current column of B, just to save space. */ + + for (;;) + { + f = of_mod2sparse_first_in_col (B, cols[i]); + if (of_mod2sparse_at_end (f)) + break; + of_mod2sparse_delete (B, f); + } + + /* Abandon columns of B with lots of entries if it's time for that. */ + + if (abandon_number > 0 && i == abandon_when) + { + for (k = 0; k < M + 1; k++) + { + acnt[k] = 0; + } + for (j = 0; j < N; j++) + { + k = mod2sparse_count_col (B, j); + acnt[k] += 1; + } + + cc = abandon_number; + k = M; + while (acnt[k] < cc) + { + cc -= acnt[k]; + k -= 1; + if (k < 0) + abort(); + } + + cc2 = 0; + for (j = 0; j < N; j++) + { + cc3 = mod2sparse_count_col (B, j); + if (cc3 > k || cc3 == k && cc > 0) + { + if (cc3 == k) + cc -= 1; + for (;;) + { + f = of_mod2sparse_first_in_col (B, j); + if (of_mod2sparse_at_end (f)) + break; + of_mod2sparse_delete (B, f); + } + cc2 += 1; + } + } + + if (cc2 != abandon_number) + abort(); + + if (strategy == Mod2sparse_minprod) + { + for (j = 0; j < M; j++) + { + rcnt[j] = mod2sparse_count_row (B, j); + } + } + } + } + + /* Get rid of all entries in the rows of L past row K, after reordering. */ + + for (i = K; i < M; i++) + { + for (;;) + { + f = of_mod2sparse_first_in_row (L, rows[i]); + if (of_mod2sparse_at_end (f)) + break; + of_mod2sparse_delete (L, f); + } + } + + of_mod2sparse_free (B); + free (rinv); + free (cinv); + if (strategy == Mod2sparse_minprod) + free (rcnt); + if (abandon_number > 0) + free (acnt); + + OF_EXIT_FUNCTION + return nnf; +} + + +/* SOLVE A LOWER-TRIANGULAR SYSTEM BY FORWARD SUBSTITUTION. */ + +UINT32 mod2sparse_forward_sub +(of_mod2sparse *L, /* Matrix that is lower triangular after reordering */ + UINT32 *rows, /* Array of indexes (from 0) of rows for new order */ + UINT8 *x, /* Vector on right of equation, also reordered */ + UINT8 *y /* Place to store solution */ +) +{ + OF_ENTER_FUNCTION + INT32 K, i, j, ii, b, d; + of_mod2entry *e; + + K = of_mod2sparse_cols (L); + + /* Make sure that L is lower-triangular, after row re-ordering. */ + + for (i = 0; i < K; i++) + { + ii = rows ? rows[i] : i; + e = of_mod2sparse_last_in_row (L, ii); + if (!of_mod2sparse_at_end (e) && of_mod2sparse_col (e) > i) + { + fprintf (stderr, + "mod2sparse_forward_sub: Matrix is not lower-triangular\n"); + OF_EXIT_FUNCTION + return NULL; + } + } + + /* Solve system by forward substitution. */ + + for (i = 0; i < K; i++) + { + ii = rows ? rows[i] : i; + + /* Look at bits in this row, forming inner product with partial + solution, and seeing if the diagonal is 1. */ + + d = 0; + b = 0; + + for (e = of_mod2sparse_first_in_row (L, ii); + !of_mod2sparse_at_end (e); + e = of_mod2sparse_next_in_row (e)) + { + j = of_mod2sparse_col (e); + + if (j == i) + { + d = 1; + } + else + { + b ^= y[j]; + } + } + + /* Check for no solution if the diagonal isn't 1. */ + + if (!d && b != x[ii]) + { + OF_EXIT_FUNCTION + return 0; + } + + /* Set bit of solution, zero if arbitrary. */ + + y[i] = b ^ x[ii]; + } + + OF_EXIT_FUNCTION + return 1; +} + + +/* SOLVE AN UPPER-TRIANGULAR SYSTEM BY BACKWARD SUBSTITUTION. */ + +UINT32 mod2sparse_backward_sub +(of_mod2sparse *U, /* Matrix that is upper triangular after reordering */ + UINT32 *cols, /* Array of indexes (from 0) of columns for new order */ + UINT8 *y, /* Vector on right of equation */ + UINT8 *z /* Place to store solution, also reordered */ +) +{ + OF_ENTER_FUNCTION + INT32 K, i, j, ii, b, d; + of_mod2entry *e; + + K = of_mod2sparse_rows (U); + + /* Make sure that U is upper-triangular, after column re-ordering. */ + + for (i = 0; i < K; i++) + { + ii = cols ? cols[i] : i; + e = of_mod2sparse_last_in_col (U, ii); + if (!of_mod2sparse_at_end (e) && of_mod2sparse_row (e) > i) + { + fprintf (stderr, + "mod2sparse_backward_sub: Matrix is not upper-triangular\n"); + OF_EXIT_FUNCTION + return NULL; + } + } + + /* Solve system by backward substitution. */ + + for (i = K - 1; i >= 0; i--) + { + ii = cols ? cols[i] : i; + + /* Look at bits in this row, forming inner product with partial + solution, and seeing if the diagonal is 1. */ + + d = 0; + b = 0; + + for (e = of_mod2sparse_first_in_row (U, i); + !of_mod2sparse_at_end (e); + e = of_mod2sparse_next_in_row (e)) + { + j = of_mod2sparse_col (e); + + if (j == ii) + { + d = 1; + } + else + { + b ^= z[j]; + } + } + + /* Check for no solution if the diagonal isn't 1. */ + + if (!d && b != y[i]) + { + return 0; + } + + /* Set bit of solution, zero if arbitrary. */ + + z[ii] = b ^ y[i]; + } + + OF_EXIT_FUNCTION + return 1; +} +#endif // #if 0 + + +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE +of_mod2entry * of_mod2sparse_last_in_col (of_mod2sparse *m, + UINT32 i) +{ + of_mod2entry *e; + + OF_ENTER_FUNCTION + e = of_mod2sparse_first_in_col (m, i); + while (!of_mod2sparse_at_end (e->down)) + { + e = e->down; + } + OF_EXIT_FUNCTION + return e; +} +#endif + + +#if defined(ML_DECODING) /* { */ + +// +// Return the weight of the line row0 +// +UINT32 of_mod2sparse_swap_rows (of_mod2sparse * m, // Matrix in which we swap two rows + UINT32 row0, // swap row e0 and row e1 + UINT32 row1, + of_mod2sparse *__swap, + of_mod2entry ** __links, + of_mod2entry **__parsing) +{ + UINT32 row_weight; + UINT32 __col; + + OF_ENTER_FUNCTION + row_weight = 0; + // If the current row is not the one we want to swap with + if (row0 != row1) + { + //of_mod2sparse * __swap; + UINT32 __cpy[2]; + of_mod2entry * e0; + of_mod2entry * e1; + of_mod2entry * __e, * __prev; + of_mod2entry * __delMe; + of_mod2entry * __col_entry, * __new_entry; +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + of_mod2entry * __col_entry_; +#endif + bool __swap_was_null = false; + + // Copy e0 in a __swap matrix + if (__swap == NULL) + { + __swap_was_null = true; + __swap = of_mod2sparse_allocate (1, of_mod2sparse_cols (m)); + } + + __cpy[0] = row0; + __cpy[1] = row1; + of_mod2sparse_copyrows_opt (m, __swap, __cpy, __parsing); + + // Delete original e0 + e0 = of_mod2sparse_first_in_row (m, row0); + while (!of_mod2sparse_at_end_row (e0)) + { + __e = e0; + e0 = of_mod2sparse_next_in_row (e0); + if (__links != NULL) + { + of_mod2sparse_delete_opt (m, __e, __links); + } + else + { + of_mod2sparse_delete (m, __e); + } + } // while (!of_mod2sparse_at_end(e0)) + + + // Copy e1 to e0 + row_weight = 0; + e1 = of_mod2sparse_first_in_row (m, row1); + while (!of_mod2sparse_at_end_row (e1)) + { + __prev = of_mod2sparse_last_in_row (m, row0); + + /* Create a new element */ + __new_entry = of_alloc_entry (m); + + __new_entry->row = row0; + __new_entry->col = of_mod2sparse_col (e1); + __col = of_mod2sparse_col (__new_entry); + + // Insert new element in the approrpiate line + __new_entry->left = __prev; + __new_entry->right = of_mod2sparse_next_in_row (__prev); + __new_entry->left->right = __new_entry; + __new_entry->right->left = __new_entry; + + /* Insert new entry into column. */ + if (__links == NULL) + { + __col_entry = of_mod2sparse_first_in_col (m, __col); +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __col_entry; +#endif + while (!of_mod2sparse_at_end_col (__col_entry) && of_mod2sparse_row (__col_entry) < row0) + { +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __col_entry; +#endif + __col_entry = of_mod2sparse_next_in_col (__col_entry); + } + } // if (__links == NULL) ... + else + { + if (__links[__col] == NULL) + { + // It is the first time I insert a cell in this col + __col_entry = of_mod2sparse_first_in_col (m, __col); +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __col_entry; +#endif + } // if (__links[of_mod2sparse_col(__new_entry)] == NULL) ... + else + { + // Cells have already been inserted in the col, the correct position is then in __links[col] +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __links[__col]; +#endif + __col_entry = of_mod2sparse_next_in_col (__links[__col]); + } // if (__links[of_mod2sparse_col(__new_entry)] == NULL) ... else ... + } // if (__links == NULL) ... else ... + + __new_entry->down = __col_entry; +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __new_entry->up = __col_entry->up; + __new_entry->up->down = __new_entry; + __new_entry->down->up = __new_entry; +#else + __col_entry_->down = __new_entry; +#endif + + if (__links != NULL) + { + __links[__col] = __new_entry; + } + + __delMe = e1; + e1 = of_mod2sparse_next_in_row (e1); + if (__links != NULL) + { + of_mod2sparse_delete_opt (m, __delMe, __links); + } + else + { + of_mod2sparse_delete (m, __delMe); + } + + ++row_weight; + } // while (!of_mod2sparse_at_end(e0)) + + // Copy e0 to e1 from the __swap matrix + __e = of_mod2sparse_first_in_row (__swap, 0); + while (!of_mod2sparse_at_end_row (__e)) + { + __prev = of_mod2sparse_last_in_row (m, row1); + + /* Insert into row. */ + __new_entry = of_alloc_entry (m); + + __new_entry->row = row1; + __new_entry->col = of_mod2sparse_col (__e); + __col = of_mod2sparse_col (__new_entry); + + + __new_entry->left = __prev; + __new_entry->right = of_mod2sparse_next_in_row (__prev); + __new_entry->left->right = __new_entry; + __new_entry->right->left = __new_entry; + + /* Insert new entry into column. */ + if (__links != NULL) + { + if (__links[__col] != NULL) + { + __col_entry = __links[__col]; + } + else + { + __col_entry = of_mod2sparse_first_in_col (m, __col); + } + } + else + { + __col_entry = of_mod2sparse_first_in_col (m, __col); + } + +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __col_entry; +#endif + while (!of_mod2sparse_at_end_col (__col_entry) && of_mod2sparse_row (__col_entry) < row1) + { +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __col_entry; +#endif + __col_entry = of_mod2sparse_next_in_col (__col_entry); + } + + __new_entry->down = __col_entry; +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __new_entry->up = __col_entry->up; + __new_entry->up->down = __new_entry; + __new_entry->down->up = __new_entry; +#else + __col_entry_->down = __new_entry; +#endif + + __delMe = __e; + __e = of_mod2sparse_next_in_row (__e); + of_mod2sparse_delete (__swap, __delMe); + } // while (!of_mod2sparse_at_end(__e)) + + + if (__swap_was_null == true) + { + of_mod2sparse_free (__swap); + of_free (__swap); + } + + if (__parsing != NULL && __links != NULL) + { + memcpy ( + & (__parsing[row0]), + & (__links[row0]), + (of_mod2sparse_cols (m) - row0) * sizeof (of_mod2entry *) + ); + } + } // if (row1 != row0) ... + else + { + if (__links != NULL) + { + of_mod2entry * __e; + + __e = of_mod2sparse_first_in_row (m, row0); + //__col = of_mod2sparse_col (__e); + while (!of_mod2sparse_at_end_row (__e)) + { + row_weight++; + __links[of_mod2sparse_col (__e) ] = __e; + + __e = of_mod2sparse_next_in_row (__e); + } + } + if (__parsing != NULL && __links != NULL) + { + memcpy ( + & (__parsing[row0]), + & (__links[row0]), + (of_mod2sparse_cols (m) - row0) * sizeof (of_mod2entry *) + ); + } + } + OF_EXIT_FUNCTION + return row_weight; +} + + +// +// Return the weight of the destination line +// +UINT32 of_mod2sparse_xor_rows (of_mod2sparse *m, // Matrix in which we swap two rows + UINT32 row0, // xor row e0 and row e1, and set the result in row1 + UINT32 row1, + of_mod2entry **__links, + of_mod2entry **__parsing) +{ + UINT32 __col; + of_mod2entry * __e0; + of_mod2entry * __e1; + of_mod2entry * __prev; + of_mod2entry * __col_entry, * __new_entry; +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + of_mod2entry * __col_entry_; +#endif + INT32 row_weight; + + OF_ENTER_FUNCTION + row_weight = 0; + // Verify if row0 is empty. In this case row1 stays the same. + if (of_mod2sparse_empty_row (m, row0)) + { + of_mod2entry * __e; + + if (__parsing != NULL) + { + __e = of_mod2sparse_first_in_row (m, row1); + + while (!of_mod2sparse_at_end_row (__e)) + { + row_weight++; + __parsing[of_mod2sparse_col (__e) ] = __e; + __e = of_mod2sparse_next_in_row (__e); + } + OF_EXIT_FUNCTION + return row_weight; + } + OF_EXIT_FUNCTION + return of_mod2sparse_weight_row (m, row1); + } + + // Verify if the two rows are equal. In that case, it is equivalent to reseting the line. + if (row0 == row1) + { + of_mod2entry * __delMe; + + __e0 = of_mod2sparse_first_in_row (m, row0); + while (!of_mod2sparse_at_end_row (__e0)) + { + __delMe = __e0; + __e0 = of_mod2sparse_next_in_row (__e0); + if (__parsing != NULL) + { + of_mod2sparse_delete_opt (m, __delMe, __parsing); + } + else + { + of_mod2sparse_delete (m, __delMe); + } + } + OF_EXIT_FUNCTION + return 0; + } + + __e0 = of_mod2sparse_first_in_row (m, row0); + __e1 = of_mod2sparse_first_in_row (m, row1); + + row_weight = 0; + + while (!of_mod2sparse_at_end_row (__e0) && !of_mod2sparse_at_end_row (__e1)) + { + if (of_mod2sparse_col (__e0) < of_mod2sparse_col (__e1)) + { + row_weight++; + + /* Insert into row. */ + __new_entry = of_alloc_entry (m); + + __new_entry->row = row1; + __new_entry->col = of_mod2sparse_col (__e0); + __col = of_mod2sparse_col (__new_entry); + + __new_entry->left = of_mod2sparse_prev_in_row (__e1); + __new_entry->right = __e1; + __new_entry->left->right = __new_entry; + __new_entry->right->left = __new_entry; + + /* Insert new entry into column. */ + if (__parsing != NULL) + { + if (__parsing[__col] != NULL) + { + __col_entry = __parsing[__col]; + } + else + { + __col_entry = of_mod2sparse_first_in_col (m, __col); + } + } + else + { + __col_entry = of_mod2sparse_first_in_col (m, __col); + } // if (__parsing != NULL) ... + +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __col_entry; +#endif + while (!of_mod2sparse_at_end_col (__col_entry) && of_mod2sparse_row (__col_entry) < row1) + { +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __col_entry; +#endif + __col_entry = of_mod2sparse_next_in_col (__col_entry); + } + __new_entry->down = __col_entry; +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __new_entry->up = __col_entry->up; + __new_entry->up->down = __new_entry; + __new_entry->down->up = __new_entry; +#else + __col_entry_->down = __new_entry; +#endif + + if (__parsing != NULL) + { + __parsing[of_mod2sparse_col (__new_entry) ] = __new_entry; + } + __e0 = of_mod2sparse_next_in_row (__e0); + } + else + { + if (of_mod2sparse_col (__e0) == of_mod2sparse_col (__e1)) + { + if (__parsing != NULL) + { + if (__links != NULL) + { + __parsing[of_mod2sparse_col (__e1) ] = __links[of_mod2sparse_col (__e1) ]; + } + else + { + of_mod2entry * __e; + + __e = __parsing[of_mod2sparse_col (__e1) ]; + __prev = __e; + while (!of_mod2sparse_at_end_col (__e) && of_mod2sparse_row (__e) < row1) + { + __prev = __e; + __e = of_mod2sparse_next_in_col (__e); + } + + __parsing[of_mod2sparse_col (__e1) ] = __prev; + } + } + if (__parsing != NULL) + { + of_mod2sparse_delete_opt (m, __e1, __parsing); + } + else + { + of_mod2sparse_delete (m, __e1); + } + __e0 = of_mod2sparse_next_in_row (__e0); + __e1 = of_mod2sparse_next_in_row (__e1); + } + else + { + row_weight++; + if (__parsing != NULL) + { + __parsing[of_mod2sparse_col (__e1) ] = __e1; + } + + __e1 = of_mod2sparse_next_in_row (__e1); + } + } + } + + while (!of_mod2sparse_at_end_row (__e0)) + { + row_weight++; + + __prev = of_mod2sparse_last_in_row (m, row1); + + /* Insert into row. */ + __new_entry = of_alloc_entry (m); + + __new_entry->row = row1; + __new_entry->col = of_mod2sparse_col (__e0); + __col = of_mod2sparse_col (__new_entry); + + __new_entry->left = __prev; + __new_entry->right = of_mod2sparse_next_in_row (__prev); + __new_entry->left->right = __new_entry; + __new_entry->right->left = __new_entry; + + /* Insert new entry into column. */ + if (__parsing != NULL) + { + if (__parsing[of_mod2sparse_col (__new_entry) ] != NULL) + { + __col_entry = __parsing[__col]; + } + else + { + __col_entry = of_mod2sparse_first_in_col (m, __col); + } + } + else + { + __col_entry = of_mod2sparse_first_in_col (m, __col); + } + +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __col_entry; +#endif + while (!of_mod2sparse_at_end_col (__col_entry) && of_mod2sparse_row (__col_entry) < row1) + { +#ifdef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __col_entry_ = __col_entry; +#endif + __col_entry = of_mod2sparse_next_in_col (__col_entry); + } + + __new_entry->down = __col_entry; +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + __new_entry->up = __col_entry->up; + __new_entry->up->down = __new_entry; + __new_entry->down->up = __new_entry; +#else + __col_entry_->down = __new_entry; +#endif + + if (__parsing != NULL) + { + __parsing[of_mod2sparse_col (__new_entry) ] = __new_entry; + } + + __e0 = of_mod2sparse_next_in_row (__e0); + } + + OF_EXIT_FUNCTION + return row_weight; +} + + +bool of_mod2sparse_empty_row (of_mod2sparse * m, UINT32 row) +{ + OF_ENTER_FUNCTION + if (of_mod2sparse_at_end_row (of_mod2sparse_first_in_row (m, row))) + { + OF_EXIT_FUNCTION + return true; + } + + OF_EXIT_FUNCTION + return false; +} + + +bool of_mod2sparse_empty_col (of_mod2sparse * m, UINT32 col) +{ + OF_ENTER_FUNCTION + if (m != NULL) + { + if (of_mod2sparse_at_end_col (of_mod2sparse_first_in_col (m, col))) + { + OF_EXIT_FUNCTION + return true; + } + OF_EXIT_FUNCTION + return false; + } + else + { + fprintf (stderr, "mod2sparse_empty_col: Matrix m does not exist."); + OF_EXIT_FUNCTION + return false; + } +} + + +UINT32 of_mod2sparse_weight_row (of_mod2sparse * m, UINT32 row) +{ + OF_ENTER_FUNCTION + of_mod2entry * __e; + INT32 row_weight; + + row_weight = 0; + + __e = of_mod2sparse_first_in_row (m, row); + while (!of_mod2sparse_at_end (__e)) + { + ++row_weight; + __e = of_mod2sparse_next_in_row (__e); + } + OF_EXIT_FUNCTION + return row_weight; +} + + +#if 0 +UINT32 mod2sparse_weight_col (of_mod2sparse * m, UINT32 col) +{ + OF_ENTER_FUNCTION + of_mod2entry * __e; + INT32 col_weight; + + col_weight = 0; + __e = of_mod2sparse_first_in_col (m, col); + while (!of_mod2sparse_at_end (__e)) + { + ++col_weight; + __e = of_mod2sparse_next_in_col (__e); + } + OF_EXIT_FUNCTION + return col_weight; +} +#endif // #if 0 + + +void of_mod2sparse_copy_filled_matrix (of_mod2sparse *m, + of_mod2sparse *r, + UINT32 *index_rows, + UINT32 *index_cols) +{ + of_mod2entry *e; + UINT32 i; + + for (i = 0; i < of_mod2sparse_rows(m); i++) + { + e = of_mod2sparse_first_in_row(m, i); + while (!of_mod2sparse_at_end_row(e)) + { + if (!of_mod2sparse_empty_col(m, e->col) && !of_mod2sparse_empty_row(m, e->row)) + { + //printf("insert : %hd,%hd from %hd,%hd\n",index_rows[e->row], index_cols[e->col],e->row, e->col); + of_mod2sparse_insert(r, index_rows[e->row], index_cols[e->col]); + } + e = of_mod2sparse_next_in_row(e); + } + } +} + + +#endif // } ML_DECODING + + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_sparse.h b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_sparse.h new file mode 100644 index 0000000..89a8ac3 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_matrix_sparse.h @@ -0,0 +1,380 @@ +/* $Id: of_matrix_sparse.h 197 2014-07-16 15:21:56Z roca $ */ +/* + * The contents of this directory and its sub-directories are + * Copyright (c) 1995-2003 by Radford M. Neal + * + * Permission is granted for anyone to copy, use, modify, or distribute these + * programs and accompanying documents for any purpose, provided this copyright + * notice is retained and prominently displayed, along with a note saying + * that the original programs are available from Radford Neal's web page, and + * note is made of any changes made to these programs. These programs and + * documents are distributed without any warranty, express or implied. As the + * programs were written for research purposes only, they have not been tested + * to the degree that would be advisable in any important application. All use + * of these programs is entirely at the user's own risk. + */ + +/* + * This module implements operations on sparse matrices of mod2 elements + * (bits, with addition and multiplication being done modulo 2). + * + * All procedures in this module display an error message on standard + * error and terminate the program if passed an invalid argument (indicative + * of a programming error), or if memory cannot be allocated. Errors from + * invalid contents of a file result in an error code being returned to the + * caller, with no message being printed by this module. + */ + +/* + * DATA STRUCTURES USED TO STORE A SPARSE MATRIX. Non-zero entries (ie, 1s) + * are represented by nodes that are doubly-linked both by row and by column, + * with the headers for these lists being kept in arrays. Nodes are allocated + * in blocks to reduce time and space overhead. Freed nodes are kept for + * reuse in the same matrix, rather than being freed for other uses, except + * that they are all freed when the matrix is cleared to all zeros by the + * of_mod2sparse_clear procedure, or copied into by of_mod2sparse_copy. + * + * Direct access to these structures should be avoided except in low-level + * routines. Use the macros and procedures defined below instead. + */ + +#ifndef OF_LDPC_MATRIX_SPARSE__ +#define OF_LDPC_MATRIX_SPARSE__ + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + +//#define SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE + +/** + * Structure representing a non-zero entry, or the header for a row or column. + */ +typedef struct of_mod2entry +{ + /** + * Row and column indexes of this entry, starting at 0, and + * with -1 for a row or column header + */ +#ifdef SPARSE_MATRIX_OPT_SMALL_INDEXES /* memory optimization, see ldpc_profile.h */ + currently not used... otherwise remove this line... + INT16 row; + INT16 col; +#else + INT32 row; + INT32 col; +#endif + /** + * Pointers to entries adjacent in row and column, or to headers. + * Free entries are linked by 'left'. + */ + struct of_mod2entry *left, + *right, + *down; +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE /* memory optimization */ + struct of_mod2entry *up; +#endif +} of_mod2entry; + +#define of_mod2sparse_block 1024 /* Number of entries to block together for memory allocation */ + + +/* + * Block of entries allocated all at once. + */ +typedef struct of_mod2block +{ + /** Next block that has been allocated. */ + struct of_mod2block *next; + + /** Entries in this block. */ + of_mod2entry entry[of_mod2sparse_block]; +} of_mod2block; + + +/** + * Representation of a sparse matrix. + */ +typedef struct of_mod2sparse +{ + INT32 n_rows; /* Number of rows in the matrix */ + INT32 n_cols; /* Number of columns in the matrix */ + + of_mod2entry *rows; /* Pointer to array of row headers */ + of_mod2entry *cols; /* Pointer to array of column headers */ + + of_mod2block *blocks; /* Blocks that have been allocated */ + of_mod2entry *next_free; /* Next free entry */ + +#ifdef LDPC_QC + INT32 exp_factor; /* expansion factor of the matrix, it is also the size of the circulant matrix */ +#endif +} of_mod2sparse; + + +/* MACROS TO GET AT ELEMENTS OF A SPARSE MATRIX. The 'first', 'last', 'next', + and 'prev' macros traverse the elements in a row or column. Moving past + the first/last element gets one to a header element, which can be identified + using the 'at_end' macro. Macros also exist for finding out the row + and column of an entry, and for finding out the dimensions of a matrix. */ + +#define of_mod2sparse_first_in_row(m,i) ((m)->rows[i].right) /* Find the first */ +#define of_mod2sparse_first_in_col(m,j) ((m)->cols[j].down) /* or last entry in */ +#define of_mod2sparse_last_in_row(m,i) ((m)->rows[i].left) /* a row or column */ +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE +#define of_mod2sparse_last_in_col(m,j) ((m)->cols[j].up) +#else +of_mod2entry * of_mod2sparse_last_in_col (of_mod2sparse * m, UINT32 i); /* a bit more complex if we don't have the "up" pointer */ +#endif + +#define of_mod2sparse_next_in_row(e) ((e)->right) /* Move from one entry to */ +#define of_mod2sparse_next_in_col(e) ((e)->down) /* another in any of the three */ +#define of_mod2sparse_prev_in_row(e) ((e)->left) /* possible directions */ +#ifndef SPARSE_MATRIX_OPT_FOR_LDPC_STAIRCASE +#define of_mod2sparse_prev_in_col(e) ((e)->up) +#endif + +#define of_mod2sparse_at_end_col(e) ((e)->col < 0) /* See if we've reached the end of column */ +#define of_mod2sparse_at_end_row(e) ((e)->row < 0) /* See if we've reached the end of row */ +#define of_mod2sparse_at_end(e) ((e)->row < 0) /* See if we've reached the end of row */ + + +#define of_mod2sparse_row(e) ((e)->row) /* Find out the row or column index */ +#define of_mod2sparse_col(e) ((e)->col) /* of an entry (indexes start at 0) */ + +#define of_mod2sparse_rows(m) ((m)->n_rows) /* Get the number of rows or columns*/ +#define of_mod2sparse_cols(m) ((m)->n_cols) /* in a matrix */ + + +#if 0 +/* POSSIBLE LU DECOMPOSITION STRATEGIES. For use with mod2sparse_decomp. */ + +typedef enum mod2sparse_strategy_enum +{ Mod2sparse_first, + Mod2sparse_mincol, + Mod2sparse_minprod +} mod2sparse_strategy; +#endif // #if 0 + + +/* PROCEDURES TO MANIPULATE SPARSE MATRICES. */ +of_mod2sparse *of_mod2sparse_allocate (UINT32, UINT32); + +void of_mod2sparse_free (of_mod2sparse *); + +void of_mod2sparse_clear (of_mod2sparse *); + +//#if 0 +void of_mod2sparse_copy (of_mod2sparse *, of_mod2sparse *); +//#endif // #if 0 + +#if defined(ML_DECODING) + +void of_mod2sparse_copyrows (of_mod2sparse *, of_mod2sparse *, UINT32 *); +void of_mod2sparse_copycols (of_mod2sparse *, of_mod2sparse *, UINT32 *); + +/** + * Copy a list of rows from one matrix to another. + * + * @param m (IN) Matrix to print out (only 0 and 1) + * @param r (OUT) Resulting matrix + * @param rows (IN) List of rows to copy + * @param __parsing (IN) Optimization for the insertion of new elements, + * avoid parsing again all the element in a cal before + * finding the good position + */ +void of_mod2sparse_copyrows_opt (of_mod2sparse * m, + of_mod2sparse * r, + UINT32 * rows, + of_mod2entry ** __parsing); + + +/** + * Copy a list of columns from one matrix to another. + * + * @param m (IN) Matrix to print out (only 0 and 1) + * @param r (OUT) Resulting matrix + * @param cols (IN) List of cols to copy + */ +void of_mod2sparse_copycols_opt (of_mod2sparse * m, + of_mod2sparse * r, + UINT32 * cols); + +#endif // #if defined(ML_DECODING) + + +/** + * Print out a matrix in a file, print only 0 and 1 + * + * @param fout (IN) The stream to write in + * @param m (IN) Matrix to print out (only 0 and 1) + */ +void of_mod2sparse_printf (FILE * fout, of_mod2sparse * m); + + +void of_mod2sparse_print (FILE *, of_mod2sparse *); +void of_mod2sparse_print_bitmap (of_mod2sparse *m); + + +#if 0 +UINT32 mod2sparse_write (FILE *, of_mod2sparse *); +of_mod2sparse *mod2sparse_read (FILE *); +#endif // #if 0 + +UINT32 of_mod2sparse_write_human_readable (FILE *, + of_mod2sparse *, + UINT32 nb_source, + UINT32 nb_parity); + +of_mod2sparse *of_mod2sparse_read_human_readable (FILE *f, + UINT32 *nb_source, + UINT32 *nb_parity); + +/* PRINT matrix statistics: average number of 1's per row/line etc ...*/ + +void of_mod2sparse_matrix_stats (FILE *, + of_mod2sparse *, + UINT32 nb_src, + UINT32 nb_par); + + +of_mod2entry *of_mod2sparse_find (of_mod2sparse *, + UINT32, + UINT32); + +of_mod2entry *of_mod2sparse_insert (of_mod2sparse *, + UINT32, + UINT32); + +void of_mod2sparse_delete (of_mod2sparse *, + of_mod2entry *); + + +#if defined(ML_DECODING) + +/** + * Swap row0 and row1 of the matrix m, using an additional matrix (either allocated or not). + * The two additional parameters optimize the parsing of the matrix. + * + * @param m (IN/OUT) The matrix which hold the two lines + * @param row0 (IN) First line to be swapped + * @param row1 (IN) Second line to be swapped + * @param __swapMatrix (IN) Additional matrix used to store + * one of the line to be swapped. + * if NULL, the additionnal matrix is created and + * freed by the function + * @param __links (IN/OUT) Used to minimised the parsing of the matrix on insertion of + * one element in the row row0. The gauss pivoting method parses + * the matrix from up to bottom, __links keeps the last element + * before row0 in the matrix (optimization for gauss pivoting) + * @param __parsing (IN/OUT) Optimization for Gauss pivoting in the XOR steps. Gauss pivoting + * parses from up to bottom to XOR lines and then eliminates simplifies + * the matrix. At the end of swapping, __parsing is initialyzed. + * + * @return The hamming weight of the new row0 line + */ +UINT32 of_mod2sparse_swap_rows (of_mod2sparse * m, + UINT32 row0, + UINT32 row1, + of_mod2sparse * __swapMatrix, + of_mod2entry ** __links, + of_mod2entry ** __parsing); + +/** + * XOR two lines of the matrix m: row1 = row0 + row1. + * + * @param m (IN/OUT) The matrix which hold the two lines + * @param row0 (IN) First line to be XORed + * @param row1 (IN) Second line to be XORed + * @param __links (IN/OUT) Used to minimised the parsing of the matrix on insertion of + * one element in the row row0. The gauss pivoting method parses + * the matrix from up to bottom, __links keeps the last element + * before row0 in the matrix (optimization for gauss pivoting) + * @param __parsing (IN/OUT) Optimization for Gauss pivoting in the XOR steps. Gauss pivoting + * parses from up to bottom to XOR lines and then eliminates simplifies + * the matrix. At the end of swapping, __parsing is initialyzed. + * + * @return The hamming weight of the new row1 line + */ +UINT32 of_mod2sparse_xor_rows (of_mod2sparse * m, + UINT32 row0, UINT32 row1, + of_mod2entry ** __links, + of_mod2entry ** __parsing); + +/** + * Determine if a row is empty + * + * @param m (IN/OUT) The matrix which hold the row + * @param row (IN) The row to check + * + * @return TRUE if the row is empty, else FALSE + */ +bool of_mod2sparse_empty_row (of_mod2sparse * m, UINT32 row); + + +/** + * Determine if a col is empty + * + * @param m (IN/OUT) The matrix which hold the col + * @param col (IN) The col to check + * + * @return TRUE if the row is empty, else FALSE + */ +bool of_mod2sparse_empty_col (of_mod2sparse * m, UINT32 col); + + +/** + * Count the number of 1 in a row + * + * @param m (IN/OUT) The matrix which the row + * @param row (IN) The row to check + * + * @return The weight of the row + */ +UINT32 of_mod2sparse_weight_row (of_mod2sparse * m, UINT32 row); + + +#if 0 +/** + * Count the number of 1 in a col + * + * @param m (IN/OUT) The matrix which the row + * @param col (IN) The col to check + * + * @return The weight of the col + */ +UINT32 mod2sparse_weight_col (of_mod2sparse * m, UINT32 col); +#endif + +#endif // defined(ML_DECODING) + +#if 0 +void mod2sparse_transpose (of_mod2sparse *, of_mod2sparse *); +void mod2sparse_add (of_mod2sparse *, of_mod2sparse *, of_mod2sparse *); +void mod2sparse_multiply (of_mod2sparse *, of_mod2sparse *, of_mod2sparse *); +void mod2sparse_mulvec (of_mod2sparse *, UINT8 *, UINT8 *); + +UINT32 mod2sparse_equal (of_mod2sparse *, of_mod2sparse *); + +UINT32 mod2sparse_count_row (of_mod2sparse *, UINT32); +UINT32 mod2sparse_count_col (of_mod2sparse *, UINT32); + +void mod2sparse_add_row (of_mod2sparse *, UINT32, of_mod2sparse *, UINT32); +void mod2sparse_add_col (of_mod2sparse *, UINT32, of_mod2sparse *, UINT32); + +UINT32 mod2sparse_decomp (of_mod2sparse *, UINT32, of_mod2sparse *, of_mod2sparse *, + UINT32 *, UINT32 *, mod2sparse_strategy,UINT32, UINT32); + +UINT32 mod2sparse_forward_sub (of_mod2sparse *, UINT32 *, UINT8 *, UINT8 *); +UINT32 mod2sparse_backward_sub (of_mod2sparse *, UINT32 *, UINT8 *, UINT8 *); +#endif + +/* copy only filled rows and cols from m to r */ +void of_mod2sparse_copy_filled_matrix (of_mod2sparse *m, + of_mod2sparse *r, + UINT32 *index_rows, + UINT32 *index_cols); + +#endif /* #ifndef OF_LDPC_MATRIX_SPARSE__ */ + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS + diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_tools.c b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_tools.c new file mode 100755 index 0000000..61551b0 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_tools.c @@ -0,0 +1,146 @@ +/* $Id: of_tools.c 182 2014-07-15 09:27:51Z roca $ */ +/* + * The contents of this directory and its sub-directories are + * Copyright (c) 1995-2003 by Radford M. Neal + * + * Permission is granted for anyone to copy, use, modify, or distribute these + * programs and accompanying documents for any purpose, provided this copyright + * notice is retained and prominently displayed, along with a note saying + * that the original programs are available from Radford Neal's web page, and + * note is made of any changes made to these programs. These programs and + * documents are distributed without any warranty, express or implied. As the + * programs were written for research purposes only, they have not been tested + * to the degree that would be advisable in any important application. All use + * of these programs is entirely at the user's own risk. + */ + + +/* This module implements operations on sparse matrices of mod2 elements + (bits, with addition and multiplication being done modulo 2). + + All procedures in this module display an error message on standard + error and terminate the program if passed an invalid argument (indicative + of a programming error), or if memory cannot be allocated. Errors from + invalid contents of a file result in an error code being returned to the + caller, with no message being printed by this module. +*/ + + +/* DATA STRUCTURES USED TO STORE A SPARSE MATRIX. Non-zero entries (ie, 1s) + are represented by nodes that are doubly-linked both by row and by column, + with the headers for these lists being kept in arrays. Nodes are allocated + in blocks to reduce time and space overhead. Freed nodes are kept for + reuse in the same matrix, rather than being freed for other uses, except + that they are all freed when the matrix is cleared to all zeros by the + of_mod2sparse_clear procedure, or copied into by of_mod2sparse_copy. + + Direct access to these structures should be avoided except in low-level + routines. Use the macros and procedures defined below instead. */ + +#include "../of_linear_binary_code.h" + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + +/* ALLOCATE SPACE AND CHECK FOR ERROR. Calls 'calloc' to allocate space, + and then displays an error message and exits if the space couldn't be + found. */ + +void *of_chk_alloc (UINT32 n, /* Number of elements */ + UINT32 size) /* Size of each element */ +{ + void *p; + + OF_ENTER_FUNCTION + p = of_calloc (n, size); + if (p == NULL) + { + fprintf (stderr, "Ran out of memory (while trying to allocate %d bytes)\n", n*size); + OF_EXIT_FUNCTION + return NULL; + } + OF_EXIT_FUNCTION + return p; +} + + +#if 1 +/* READ AN INTEGER ONE BYTE AT A TIME. Four bytes are read, ordered from + low to high order. These are considered to represent a signed integer, + in two's complement form. The value returned is this integer, converted + to whatever a C "int" is. The conversion should work as long as an "int" + is at least four bytes, even if it's not in two's complement representation + (except for the largest two's complement negative integer). + + If an error or eof is encountered, zero is returned. The caller can + check for these events using feof and ferror. + + The file read from should have been opened as "binary". +*/ + +INT32 of_intio_read (FILE *f) /* File to read from */ +{ + UINT8 b[4]; + INT32 top; + INT32 i; + + OF_ENTER_FUNCTION + for (i = 0; i < 4; i++) + { + if (fread (&b[i], 1, 1, f) != 1) + { + OF_EXIT_FUNCTION + return 0; + } + } + top = b[3] > 127 ? (INT32) b[3] - 256 : b[3]; + OF_EXIT_FUNCTION + return (top << 24) + (b[2] << 16) + (b[1] << 8) + b[0]; +} + + +/* WRITE AN INTEGER ONE BYTE AT A TIME. Four bytes are written, ordered from + low to high order. These are considered to represent a signed integer, + in two's complement form. This should work as long as the integer passed + can be represented in four bytes, even if a C "int" is longer than this. + + The file written to should have been opened as "binary". +*/ + +void of_intio_write (FILE *f, /* File to write to */ + INT32 v) /* Value to write to file */ +{ + UINT8 b; + INT32 i; + + OF_ENTER_FUNCTION + for (i = 0; i < 3; i++) + { + b = v & 0xff; + fwrite (&b, 1, 1, f); + v >>= 8; + } + b = v > 0 ? v : v + 256; + fwrite (&b, 1, 1, f); + OF_EXIT_FUNCTION +} +#endif + + +void of_print_composition (char* symbol, UINT32 size) +{ + UINT32 i; + + OF_ENTER_FUNCTION + for (i = 0;i < size;i++) + { + if (symbol[i] != 0) + { + printf ("%d ", i); + } + } + printf ("\n"); + OF_EXIT_FUNCTION +} + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_tools.h b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_tools.h new file mode 100755 index 0000000..471862a --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/binary_matrix/of_tools.h @@ -0,0 +1,72 @@ +/* $Id: of_tools.h 186 2014-07-16 07:17:53Z roca $ */ +/* + * The contents of this directory and its sub-directories are + * Copyright (c) 1995-2003 by Radford M. Neal + * + * Permission is granted for anyone to copy, use, modify, or distribute these + * programs and accompanying documents for any purpose, provided this copyright + * notice is retained and prominently displayed, along with a note saying + * that the original programs are available from Radford Neal's web page, and + * note is made of any changes made to these programs. These programs and + * documents are distributed without any warranty, express or implied. As the + * programs were written for research purposes only, they have not been tested + * to the degree that would be advisable in any important application. All use + * of these programs is entirely at the user's own risk. + */ + + +/* This module implements operations on sparse matrices of mod2 elements + (bits, with addition and multiplication being done modulo 2). + + All procedures in this module display an error message on standard + error and terminate the program if passed an invalid argument (indicative + of a programming error), or if memory cannot be allocated. Errors from + invalid contents of a file result in an error code being returned to the + caller, with no message being printed by this module. +*/ + + +/* DATA STRUCTURES USED TO STORE A SPARSE MATRIX. Non-zero entries (ie, 1s) + are represented by nodes that are doubly-linked both by row and by column, + with the headers for these lists being kept in arrays. Nodes are allocated + in blocks to reduce time and space overhead. Freed nodes are kept for + reuse in the same matrix, rather than being freed for other uses, except + that they are all freed when the matrix is cleared to all zeros by the + of_mod2sparse_clear procedure, or copied into by of_mod2sparse_copy. + + Direct access to these structures should be avoided except in low-level + routines. Use the macros and procedures defined below instead. */ + +#ifndef TOOLS_H__ +#define TOOLS_H__ + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + + +/** + * Call calloc and exits with an error if it fails + */ +void * of_chk_alloc (UINT32 n, + UINT32 size); + +/** + */ +void of_print_composition (char* symbol, + UINT32 size); + +/** + * Read an integer + */ +INT32 of_intio_read (FILE *); + +/** + * Write an integer + */ +void of_intio_write (FILE *, INT32); + + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS + +#endif + diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/it_decoding/of_it_decoding.c b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/it_decoding/of_it_decoding.c new file mode 100644 index 0000000..d99c742 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/it_decoding/of_it_decoding.c @@ -0,0 +1,348 @@ +/* $Id: of_it_decoding.c 217 2014-12-13 13:55:01Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "../of_linear_binary_code.h" + +#ifdef OF_USE_DECODER +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + + +of_status_t of_linear_binary_code_decode_with_new_symbol (of_linear_binary_code_cb_t* ofcb, + void* new_symbol, + UINT32 new_symbol_esi) +{ + of_mod2entry *e = NULL; // entry ("1") in parity check matrix + of_mod2entry *mod_entry_to_delete; // temp: entry to delete in row/column + void *const_term; // temp: pointer to constant term, containing the sum of + // all the known symbols of this equation + UINT32 row; // temp: current row value + UINT32 *table_of_check_deg_1 = NULL; // table of check nodes of degree + // one after the processing of new_symbol + INT32 table_of_check_deg_1_nb = 0; // number of entries in table + UINT32 size_of_table_of_check_deg_1 = 0; // size of the memory block + UINT32 decoded_symbol_esi; // sequence number of decoded symbol + + OF_ENTER_FUNCTION + ASSERT(ofcb); + ASSERT(new_symbol); + ASSERT(new_symbol_esi < ofcb->nb_total_symbols); + + /* + * Step 0: check if this is a fresh symbol, otherwise return + */ + if (ofcb->encoding_symbols_tab[new_symbol_esi] != NULL) + { + OF_TRACE_LVL (1, ("%s: %s symbol (esi=%d) already received or rebuilt, ignored.\n", __FUNCTION__, + (of_is_source_symbol ((of_cb_t*)ofcb, new_symbol_esi)) ? "source" : "parity", new_symbol_esi)) +#ifdef OF_DEBUG + if (of_is_source_symbol ((of_cb_t*)ofcb, new_symbol_esi)) + ofcb->stats_symbols->nb_source_symbols_ignored++; + else + ofcb->stats_symbols->nb_repair_symbols_ignored++; +#endif + OF_EXIT_FUNCTION + return OF_STATUS_OK; + } + + //of_mod2sparse_print_bitmap(ofcb->pchk_matrix); + + /* + * Step 1: Store the symbol in a permanent array. + */ + if (of_is_source_symbol ((of_cb_t*)ofcb, new_symbol_esi)) + { + ofcb->nb_source_symbol_ready++; +#ifdef OF_DEBUG + ofcb->stats_symbols->nb_source_symbols_received++; +#endif + ofcb->encoding_symbols_tab[new_symbol_esi] = new_symbol; + if (of_is_decoding_complete ((of_session_t*)ofcb)) + { + OF_TRACE_LVL (1, ("%s: decoding finished\n", __FUNCTION__)) + OF_EXIT_FUNCTION + return OF_STATUS_OK; + } + } + else + { + ofcb->nb_repair_symbol_ready++; +#ifdef OF_DEBUG + ofcb->stats_symbols->nb_repair_symbols_received++; +#endif + // in ML decoding, we need to store all parity symbols, whereas with pure IT + // decoding this is not necessary. + if ((ofcb->encoding_symbols_tab[new_symbol_esi] = (void *) + of_malloc (ofcb->encoding_symbol_length)) == NULL) + { + goto no_mem; + } + // copy the content... + memcpy (ofcb->encoding_symbols_tab[new_symbol_esi], new_symbol, ofcb->encoding_symbol_length); + } + OF_TRACE_LVL (1, ("%s: new %s symbol (esi=%d), total of %d/%d source/repair symbols ready\n", + __FUNCTION__, (of_is_source_symbol ((of_cb_t*)ofcb, new_symbol_esi)) ? "source" : "parity", + new_symbol_esi, ofcb->nb_source_symbol_ready, ofcb->nb_repair_symbol_ready)) + + /* + * Step 2: Inject the symbol value in each equation it is involved + */ + // (if partial sum already exists or if partial sum should be created) + for (e = of_mod2sparse_first_in_col (ofcb->pchk_matrix, of_get_symbol_col ((of_cb_t*)ofcb, new_symbol_esi)); !of_mod2sparse_at_end_col (e); ) + { + // for a given row, ie for a given equation where this symbol + // is implicated, do the following: + row = e->row; + ofcb->tab_nb_unknown_symbols[row]--; // symbol is known + const_term = ofcb->tab_const_term_of_equ[row]; // associated partial sum buffer (if any) + if ((const_term == NULL) && ((ofcb->tab_nb_unknown_symbols[row] == 1))) + { + // we need to allocate a partial sum (i.e. check node) + // and add the symbol to it, because it is the + // last missing symbol of this equation. + const_term = (void*) of_calloc (1, ofcb->encoding_symbol_length); + if ((ofcb->tab_const_term_of_equ[row] = const_term) == NULL) + { + goto no_mem; + } + } + if (const_term != NULL) + { + mod_entry_to_delete = e; + of_mod2entry *tmp_e; // current symbol in this equation + UINT32 tmp_esi; // corresponding esi + void *tmp_symbol; // corresponding symbol pointer + + // there's a partial sum for this row... + if (ofcb->tab_nb_enc_symbols_per_equ[row] > 1) + { + //ofcb->tmp_tab_symbols[ofcb->nb_tmp_symbols++] = new_symbol; + // we can add the symbol content to this constant term + of_add_to_symbol (const_term, new_symbol, ofcb->encoding_symbol_length +#ifdef OF_DEBUG + , &(ofcb->stats_xor->nb_xor_for_IT) +#endif + ); + } + // else this is useless, since new_symbol is the last + // symbol of this equation, and its value is necessarilly + // equal to the constant term. Their sum must be 0 (we don't check it). + // Remove the symbol from the equation since this entry is now useless. + e = of_mod2sparse_next_in_col (e); + of_mod2sparse_delete (ofcb->pchk_matrix, mod_entry_to_delete); + ofcb->tab_nb_enc_symbols_per_equ[row]--; + if (of_is_repair_symbol ((of_cb_t*)ofcb, new_symbol_esi)) + { + ofcb->tab_nb_equ_for_repair[new_symbol_esi - ofcb->nb_source_symbols]--; + } + // Inject all permanently stored symbols + // (source and repair) into this partial sum. + // Requires to scan the equation (i.e. row). + for (tmp_e = of_mod2sparse_first_in_row (ofcb->pchk_matrix, row); !of_mod2sparse_at_end_row (tmp_e); ) + { + tmp_esi = of_get_symbol_esi ((of_cb_t*)ofcb, tmp_e->col); + tmp_symbol = ofcb->encoding_symbols_tab[tmp_esi]; + if (tmp_symbol != NULL) + { + // add the symbol content now + of_add_to_symbol (const_term, tmp_symbol, ofcb->encoding_symbol_length +#ifdef OF_DEBUG + , &(ofcb->stats_xor->nb_xor_for_IT) +#endif + ); + // delete the entry + mod_entry_to_delete = tmp_e; + tmp_e = of_mod2sparse_next_in_row (tmp_e); + of_mod2sparse_delete (ofcb->pchk_matrix, mod_entry_to_delete); + ofcb->tab_nb_enc_symbols_per_equ[row]--; + if (of_is_repair_symbol ((of_cb_t*)ofcb, tmp_esi)) + { + ofcb->tab_nb_equ_for_repair[tmp_esi - ofcb->nb_source_symbols]--; +#ifndef ML_DECODING + // we can delete parity symbol altogether if in IT decoding only, + // if ML decoding is needed, then keep the repair symbol + if (ofcb->tab_nb_equ_for_repair[tmp_esi - ofcb->nb_source_symbols] == 0) + { + of_free (tmp_symbol); + ofcb->encoding_symbols_tab[tmp_esi] = NULL; + } +#endif + } + } + else + { + // this symbol is not yet known, switch to next one in equation + tmp_e = of_mod2sparse_next_in_row (tmp_e); + } + } + } + else + { + // here m_checkValues[row] is NULL, ie. the partial + // sum has not been allocated + e = of_mod2sparse_next_in_col (e); + } + if (ofcb->tab_nb_enc_symbols_per_equ[row] == 1) + { + // register this entry for step 3 since the symbol + // associated to this equation can now be decoded... + if (table_of_check_deg_1 == NULL) + { + // allocate memory for the table first + size_of_table_of_check_deg_1 = 4; + if ((table_of_check_deg_1 = (UINT32*) of_calloc (size_of_table_of_check_deg_1, sizeof (UINT32*))) == NULL) + { + goto no_mem; + } + } + else if (table_of_check_deg_1_nb == size_of_table_of_check_deg_1) + { + // not enough size in table, add some more + size_of_table_of_check_deg_1 += 4; + if ((table_of_check_deg_1 = (UINT32*) of_realloc (table_of_check_deg_1, size_of_table_of_check_deg_1 * sizeof (UINT32*))) == NULL) + { + goto no_mem; + } + } + table_of_check_deg_1[table_of_check_deg_1_nb++] = row; + } + } + + /* + * Step 3: Check if a new symbol has been decoded and take appropriate measures ... + */ + for (table_of_check_deg_1_nb--; table_of_check_deg_1_nb >= 0; table_of_check_deg_1_nb--) + { + if (of_is_decoding_complete ((of_session_t*)ofcb)) + { + /* decoding has just finished, no need to do anything else. + * Stop this decoding loop and return immediately. */ + break; + } + // get the index (ie row) of the partial sum concerned + row = table_of_check_deg_1[table_of_check_deg_1_nb]; + if (ofcb->tab_nb_enc_symbols_per_equ[row] == 1) + { + // A new decoded symbol is available... + // NB: because of the recursion below, we need to + // check that all equations mentioned in the + // table_of_check_deg_1 list are __still__ of degree 1. + e = of_mod2sparse_first_in_row (ofcb->pchk_matrix, row); + ASSERT (!of_mod2sparse_at_end_row (e) && of_mod2sparse_at_end_row (e->right)) + decoded_symbol_esi = of_get_symbol_esi ((of_cb_t*)ofcb, e->col); + // remove the entry from the matrix + const_term = ofcb->tab_const_term_of_equ[row]; // remember it + ofcb->tab_const_term_of_equ[row] = NULL; + ofcb->tab_nb_enc_symbols_per_equ[row]--; + if (of_is_repair_symbol ((of_cb_t*)ofcb, decoded_symbol_esi)) + { + ofcb->tab_nb_equ_for_repair[decoded_symbol_esi - ofcb->nb_source_symbols]--; + } + of_mod2sparse_delete (ofcb->pchk_matrix, e); + OF_TRACE_LVL (1, ("%s: REBUILT %s symbol %d\n", __FUNCTION__, + (of_is_repair_symbol ((of_cb_t*)ofcb, decoded_symbol_esi)) ? "Parity" : "Source", + decoded_symbol_esi)); + if (of_is_source_symbol ((of_cb_t*)ofcb, decoded_symbol_esi)) + { + // source symbol. + void *decoded_symbol_dst; // temp variable used to store symbol +#ifdef OF_DEBUG + ofcb->stats_symbols->nb_source_symbols_built_with_it++; + ofcb->stats_symbols->nb_source_symbols_received--; +#endif + // First copy it into a permanent buffer. + if (ofcb->decoded_source_symbol_callback != NULL) + { + // Call the associated callback (that allocates a buffer) and then + // copy the symbol content in it. + if ((decoded_symbol_dst = ofcb->decoded_source_symbol_callback( + ofcb->context_4_callback, + ofcb->encoding_symbol_length, + decoded_symbol_esi)) != NULL) + { + // if the application has allocated a buffer, copy the symbol into it. + memcpy (decoded_symbol_dst, const_term, ofcb->encoding_symbol_length); + // we don't need the const_term buffer any more, so free it. + of_free (const_term); + } + else + { + // else reuse the const_term buffer in order to save extra malloc/memcpy. + decoded_symbol_dst = const_term; + } + } + else + { + // else reuse the const_term buffer in order to save extra malloc/memcpy. + decoded_symbol_dst = const_term; + } + // And finally call this function recursively + of_linear_binary_code_decode_with_new_symbol (ofcb, decoded_symbol_dst, decoded_symbol_esi); + } + else + { +#ifdef OF_DEBUG + ofcb->stats_symbols->nb_repair_symbols_built_with_it++; + ofcb->stats_symbols->nb_repair_symbols_received--; +#endif + // Parity symbol. + if (ofcb->decoded_repair_symbol_callback != NULL) + { + ofcb->decoded_repair_symbol_callback (ofcb->context_4_callback, + ofcb->encoding_symbol_length, + decoded_symbol_esi); + } + // Call this function recursively first... + of_linear_binary_code_decode_with_new_symbol (ofcb, const_term, decoded_symbol_esi); + // ...then free the partial sum which is no longer needed. + of_free (const_term); + } + } + } + if (table_of_check_deg_1 != NULL) + { + of_free (table_of_check_deg_1); + } + //OF_TRACE_LVL(1,("max:%u,cur:%u\n",ofcb->stats->maximum_mem,ofcb->stats->current_mem)) + + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +no_mem: + OF_PRINT_ERROR(("out of memory\n")); + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS + +#endif //OF_USE_DECODER diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/it_decoding/of_it_decoding.h b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/it_decoding/of_it_decoding.h new file mode 100644 index 0000000..0cd074b --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/it_decoding/of_it_decoding.h @@ -0,0 +1,58 @@ +/* $Id: of_it_decoding.h 186 2014-07-16 07:17:53Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef IT_DECODING_H +#define IT_DECODING_H + + +#ifdef OF_USE_DECODER +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + + +/** + * @fn of_status_t of_linear_binary_code_decode_with_new_symbol (of_linear_binary_code_cb_t* ofcb, void* const new_symbol_buf, UINT32 new_symbol_esi) + * @brief (try to) decode with a newly received symbol + * @param ofcb (IN) Pointer to the linear binary code control block. + * @param new_symbol (IN) Pointer to the encoding symbol now available (i.e. a new + * symbol received by the application, or a decoded symbol in case + * of a recursive call). + * @param new_symbol_esi (IN) Encoding symbol ID of the newly symbol available, in {0..n-1}. + * @return Error status (NB: this function does not return OF_STATUS_FAILURE). + */ +of_status_t of_linear_binary_code_decode_with_new_symbol(of_linear_binary_code_cb_t* ofcb,void* new_symbol,UINT32 new_symbol_esi); + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS + +#endif //OF_USE_DECODER + +#endif //IT_DECODING_H diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/._.DS_Store b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/._.DS_Store new file mode 100644 index 0000000..09fa6bd Binary files /dev/null and b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/._.DS_Store differ diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_decoding.c b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_decoding.c new file mode 100644 index 0000000..df1c7a0 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_decoding.c @@ -0,0 +1,624 @@ +/* $Id: of_ml_decoding.c 218 2014-12-13 14:15:11Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "../of_linear_binary_code.h" + + +#ifdef OF_USE_DECODER +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS +#ifdef ML_DECODING + + +/****** Static Functions ****************************************************/ + + +/** + * This function prepars the linear system (H) to be further simplified. + * + * @brief creates a copy of H matrix and update all ML deconding variables + * @param ofcb (IN/OUT) Linear-Binary-Code control-block. + * @return OF_STATUS_OK if it's OK + */ +static of_status_t +of_linear_binary_code_prepar_linear_system (of_linear_binary_code_cb_t *ofcb); + +/** + * This function simplifies the linear system (H): delete rows and cols when feasible. + * This step is needed as IT decoding performs in a lazzy way, avoiding to sum the available symbols + * (received or decoded) to the constant term of the equations they are involved in unless it is the + * last symbol of this equation. Here we need to do that explicitely in order to simplify the system + * as much as possible. + * + * @brief symplifies the linear system + * @param ofcb (IN/OUT) Linear-Binary-Code control-block. + * @param new_symbol (IN/OUT) pointer to new symbol to process + * @param new_symbol_esi (IN) Encoding Symbol Index + * @return OF_STATUS_OK if it's OK + */ +static of_status_t +of_linear_binary_code_simplify_linear_system_with_a_symbol (of_linear_binary_code_cb_t *ofcb, + const void *new_symbol, + UINT32 new_symbol_esi); + +/** + * This function creates the simplified linear system, considering only the non empty columns. + * This funtion creates the new ofcb->pchk_matrix_simplified matrix. + * + * @brief creates the simplified linear system + * @param ofcb (IN/OUT) Linear-Binary-Code control-block. + * @return OF_STATUS_OK if it's OK + */ +static of_status_t +of_linear_binary_code_create_simplified_linear_system (of_linear_binary_code_cb_t *ofcb); + + +/******************************************************************************/ + + +of_status_t +of_linear_binary_code_finish_decoding_with_ml (of_linear_binary_code_cb_t *ofcb) +{ + INT32 i; + UINT32 *permutation_array = NULL; + of_mod2dense *dense_pchk_matrix_simplified = NULL; + INT32 *column_idx = NULL; + void **const_term = NULL; + void **variable_member = NULL; + UINT32 nb_computed_repair_in_ml; +#ifdef DEBUG + struct timeval gdtv0; /* start */ + struct timeval gdtv1; /* end */ + struct timeval gdtv_delta; /* difference tv1 - tv0 */ +#endif + + OF_ENTER_FUNCTION + OF_TRACE_LVL (1, ("ML decoding on parity check matrix\n")) + /* + * Step 0: Matrix simplification, where we remove known symbols from the system, adding their value + * to corresponding constant terms. + * + * This step is needed as IT decoding performs in a lazzy way, avoiding to sum the available symbols + * (received or decoded) to the constant term of the equations they are involved in unless it is the + * last symbol of this equation. Here we need to do that explicitely in order to simplify the system + * as much as possible. + */ + ofcb->remain_rows = ofcb->nb_repair_symbols; + ofcb->remain_cols = ofcb->nb_source_symbols + ofcb->nb_repair_symbols; + if (of_linear_binary_code_prepar_linear_system (ofcb) != OF_STATUS_OK) + { + if (ofcb->remain_cols == 0) + { + // in fact decoding is already finished! + OF_TRACE_LVL (1, ("Create simplified linear system says it's finished!\n")) + OF_EXIT_FUNCTION + return OF_STATUS_FAILURE; + } + // but here it failed! + OF_TRACE_LVL (1, ("Create simplified linear system failed, ofcb->remain_cols=%d\n", ofcb->remain_cols)) + OF_EXIT_FUNCTION + return OF_STATUS_FAILURE; + } + /* + * Inject all known source symbols + */ + for (i = 0 ; i < ofcb->nb_source_symbols ; i++) + { + if (ofcb->encoding_symbols_tab[i] != NULL) + { + if (of_linear_binary_code_simplify_linear_system_with_a_symbol (ofcb, ofcb->encoding_symbols_tab[i], i) != OF_STATUS_OK) + { + OF_TRACE_LVL(0,("Simplifying the matrix with source symbols failed\n")) + OF_EXIT_FUNCTION + return OF_STATUS_FAILURE; + } + } + } + /* + * Inject all known repair symbols + */ + /* Randomize the repair symbols order before injecting them (it makes the decoding process more efficient). */ + permutation_array = (UINT32 *) of_malloc (ofcb->nb_repair_symbols * sizeof(UINT32)); + for (i = 0 ; i < ofcb->nb_repair_symbols ; i++) + { + permutation_array[i] = i; + } + for (i = 0 ; i < ofcb->nb_repair_symbols ; i++) + { + INT32 backup; + INT32 rand_val; + + backup = permutation_array[i]; + rand_val = rand() % ofcb->nb_repair_symbols; + permutation_array[i] = permutation_array[rand_val]; + permutation_array[rand_val] = backup; + } + /* Inject parity symbols following the random order given by permutation_array */ + for (i = 0 ; i < ofcb->nb_repair_symbols ; i++) + { + if (ofcb->encoding_symbols_tab[ofcb->nb_source_symbols+permutation_array[i]] != NULL) + { + if (of_linear_binary_code_simplify_linear_system_with_a_symbol (ofcb, ofcb->encoding_symbols_tab[ofcb->nb_source_symbols+permutation_array[i]], + of_get_symbol_esi ((of_cb_t*)ofcb, permutation_array[i])) != OF_STATUS_OK) + { + OF_TRACE_LVL(0,("Simplifying the matrix with parity symbols failed\n")) + goto failure; + } + } + } + of_free (permutation_array); + permutation_array = NULL; + OF_TRACE_LVL (1, ("%s: ofcb->remain_rows=%d, ofcb->remain_cols=%d\n", __FUNCTION__, ofcb->remain_rows, ofcb->remain_cols)) + if (of_linear_binary_code_create_simplified_linear_system (ofcb) != OF_STATUS_OK) + { + OF_TRACE_LVL(0, ("Create Simplified Linear System failed\n")) + goto failure; + } +#ifdef IL_SUPPORT + of_mod2sparse_print_bitmap(ofcb->pchk_matrix_simplified); +#endif + /* + * It's now time to create the simplified matrix, in dense format. + */ + dense_pchk_matrix_simplified = of_mod2dense_allocate (ofcb->pchk_matrix_simplified->n_rows, ofcb->pchk_matrix_simplified->n_cols); + of_mod2sparse_to_dense (ofcb->pchk_matrix_simplified, dense_pchk_matrix_simplified); + /* and immediately free the now useless sparse version to save memory... */ + of_mod2sparse_free (ofcb->pchk_matrix_simplified); + of_free (ofcb->pchk_matrix_simplified); + ofcb->pchk_matrix_simplified = NULL; + +#ifdef DEBUG + gettimeofday (&gdtv0, NULL); + OF_TRACE_LVL (1, ("gauss_decoding_start=%ld.%ld\n", gdtv0.tv_sec, gdtv0.tv_usec)) +#endif + if ((column_idx = (INT32 *) of_malloc (of_mod2dense_cols (dense_pchk_matrix_simplified) * sizeof (INT32))) == NULL) + { + goto no_mem; + } + for (i = 0; i < of_mod2dense_cols (dense_pchk_matrix_simplified); i++) + { + column_idx[i] = i; + } + if ((const_term = (void **) of_malloc (of_mod2dense_rows (dense_pchk_matrix_simplified) * sizeof (void*))) == NULL) + { + goto no_mem; + } + for (i = 0; i < of_mod2dense_rows (dense_pchk_matrix_simplified); i++) + { + const_term[i] = ofcb->tab_const_term_of_equ[ofcb->index_rows[i]]; + ofcb->tab_const_term_of_equ[ofcb->index_rows[i]] = NULL; + } + if ((variable_member = (void **) of_calloc (of_mod2dense_cols (dense_pchk_matrix_simplified), sizeof (void*))) == NULL) + { + goto no_mem; + } + /* + * And finally launch Gaussian Elimination. + */ + if (of_linear_binary_code_solve_dense_system (ofcb, dense_pchk_matrix_simplified, const_term, variable_member) != OF_STATUS_OK) + { + OF_TRACE_LVL(0,("Solve dense system failed\n")) + goto failure; + } + /* + * the system has been solved, so store the result in the canvas + */ + OF_TRACE_LVL (1, ("Solve dense system successful\n")) + nb_computed_repair_in_ml = ofcb->nb_repair_symbols - ofcb->nb_repair_symbol_ready; /* this is the number of repair found in ML */ + /* ignore the first nb_computed_repair_in_ml symbols found in ML as they are repair symbols and we don't need them */ + for (i = 0; i < nb_computed_repair_in_ml; i++) + { + if (variable_member[i] != NULL) + of_free(variable_member[i]); + } + /* the remaining symbols found in ML are source symbols, so we copy pointers */ + for (i = 0; i < ofcb->nb_source_symbols; i++) + { + if (ofcb->encoding_symbols_tab[i] == NULL) + { + ofcb->encoding_symbols_tab[i] = variable_member[nb_computed_repair_in_ml]; + nb_computed_repair_in_ml++; + } + } +#ifdef DEBUG + if (of_is_decoding_complete (ofcb)) + { + OF_TRACE_LVL (1, ("ML decoding successful\n")) + } + gettimeofday (&gdtv1, NULL); + timersub (&gdtv1, &gdtv0, &gdtv_delta); + OF_TRACE_LVL (1, ("gauss_decoding_end=%ld.%ld gauss_decoding_time=%ld.%06ld \n", + gdtv1.tv_sec, gdtv1.tv_usec, gdtv_delta.tv_sec, gdtv_delta.tv_usec)) +#endif + + for (i = 0; i < of_mod2dense_rows (dense_pchk_matrix_simplified); i++) + { + if (const_term[i]) + { + of_free(const_term[i]); + } + } + of_free(const_term); + const_term = NULL; + of_free(variable_member); + variable_member = NULL; + of_free(column_idx); + column_idx = NULL; + of_mod2dense_free(dense_pchk_matrix_simplified); + dense_pchk_matrix_simplified = NULL; + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +failure: + if (permutation_array != NULL) + { + of_free (permutation_array); + permutation_array = NULL; + } + if (const_term != NULL) + { + for (i = 0; i < of_mod2dense_rows (dense_pchk_matrix_simplified); i++) + { + if (const_term[i]) + { + of_free(const_term[i]); + } + } + of_free(const_term); + const_term = NULL; + } + if (variable_member != NULL) + { + of_free(variable_member); + variable_member = NULL; + } + if (column_idx != NULL) + { + of_free(column_idx); + column_idx = NULL; + } + if (dense_pchk_matrix_simplified != NULL) + { + of_mod2dense_free(dense_pchk_matrix_simplified); + dense_pchk_matrix_simplified = NULL; + } + OF_EXIT_FUNCTION + return OF_STATUS_FAILURE; + +no_mem: + OF_PRINT_ERROR(("out of memory")) + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + + +/****** Static Functions ****************************************************/ + + +of_status_t +of_linear_binary_code_prepar_linear_system (of_linear_binary_code_cb_t *ofcb) +{ + INT32 _row; + INT32 _col; + + OF_ENTER_FUNCTION + if (ofcb->index_rows == NULL) + { + ofcb->index_rows = (UINT32*) of_calloc (ofcb->nb_repair_symbols, sizeof (UINT32)); + } + if (ofcb->index_cols == NULL) + { + ofcb->index_cols = (UINT32*) of_calloc (ofcb->nb_total_symbols, sizeof (UINT32)); + } + for (_row = 0; _row < ofcb->nb_repair_symbols; _row++) + { + ofcb->index_rows[_row] = _row; + } + ofcb->remain_rows = _row; + for (_col = 0; _col < ofcb->nb_total_symbols; _col++) + { + ofcb->index_cols[_col] = _col; + } + ofcb->remain_cols = _col; + // Update the ML decoding variables too + for (_row = 0 ; _row < ofcb->nb_repair_symbols ; _row++) + { + of_mod2entry *e; + + ofcb->tab_nb_enc_symbols_per_equ[_row] = 0; + ofcb->tab_nb_unknown_symbols[_row] = 0; + for (e = of_mod2sparse_first_in_row (ofcb->pchk_matrix, _row); !of_mod2sparse_at_end (e); e = of_mod2sparse_next_in_row (e)) + { + ofcb->tab_nb_enc_symbols_per_equ[_row]++; + ofcb->tab_nb_unknown_symbols[_row]++; + } + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +static of_status_t +of_linear_binary_code_simplify_linear_system_with_a_symbol (of_linear_binary_code_cb_t *ofcb, + const void *new_symbol, + UINT32 new_symbol_esi) +{ + of_mod2entry *_e; // entry ("1") in parity check matrix and entry to delete in row/column (temp) + of_mod2entry *_del_me; + INT32 _row; + + OF_ENTER_FUNCTION + if (of_mod2sparse_empty_col (ofcb->pchk_matrix, of_get_symbol_col((of_cb_t*)ofcb, new_symbol_esi))) + { + OF_TRACE_LVL (1, ((" nothing to do, col empty\n"))) + OF_EXIT_FUNCTION + return OF_STATUS_OK; + } + if (of_is_source_symbol((of_cb_t*)ofcb, new_symbol_esi) && of_is_decoding_complete((of_session_t*)ofcb)) + { + // Decoding is now finished, return... + OF_TRACE_LVL (1, ((" decoding is finished!\n"))) + OF_EXIT_FUNCTION + return OF_STATUS_OK; + } + _e = of_mod2sparse_first_in_col (ofcb->pchk_matrix, of_get_symbol_col((of_cb_t*)ofcb, new_symbol_esi)); + while (!of_mod2sparse_at_end_col (_e)) + { + _row = of_mod2sparse_row (_e); + // If the constant term buffer does not exist, create it + if (ofcb->tab_const_term_of_equ[_row] == NULL) + { + if ((ofcb->tab_const_term_of_equ[_row] = of_malloc (ofcb->encoding_symbol_length)) == NULL) + { + goto no_mem; + } + memcpy(ofcb->tab_const_term_of_equ[_row], new_symbol, ofcb->encoding_symbol_length); + } + else + { + // Inject the symbol in the partial sum + of_add_to_symbol((ofcb->tab_const_term_of_equ[_row]), new_symbol, ofcb->encoding_symbol_length +#ifdef OF_DEBUG + , &(ofcb->stats_xor->nb_xor_for_ML) +#endif + ); + } + // Decrease the number of unknown symbols in the equation + ofcb->tab_nb_unknown_symbols[_row]--; // symbol is known + // Delete the current element + _del_me = _e; + _e = of_mod2sparse_next_in_col (_e); + of_mod2sparse_delete (ofcb->pchk_matrix, _del_me); + // If there is only one more symbol in the line, reinject it and progress like that + if (ofcb->tab_nb_unknown_symbols[_row] == 1) + { + of_mod2entry *__r; + UINT32 decoded_symbol_seqno; + + // Get the only one symbol in the equation + __r = of_mod2sparse_first_in_row (ofcb->pchk_matrix, _row); + decoded_symbol_seqno = of_get_symbol_esi ((of_cb_t*)ofcb, of_mod2sparse_col (__r)); + // Identify the symbol with its value, and reinject it. + if (of_is_source_symbol ((of_cb_t*)ofcb, decoded_symbol_seqno)) + { + if (ofcb->encoding_symbols_tab[decoded_symbol_seqno] == NULL) + { + if (ofcb->decoded_source_symbol_callback != NULL) + { + ofcb->encoding_symbols_tab[decoded_symbol_seqno] = + ofcb->decoded_source_symbol_callback(ofcb->context_4_callback, + ofcb->encoding_symbol_length, + decoded_symbol_seqno); + } + else + { + ofcb->encoding_symbols_tab[decoded_symbol_seqno] = of_malloc (ofcb->encoding_symbol_length); + } + if (ofcb->encoding_symbols_tab[decoded_symbol_seqno] == NULL) + { + goto no_mem; + } + // Source symbol. + memcpy((ofcb->encoding_symbols_tab[decoded_symbol_seqno]), + (ofcb->tab_const_term_of_equ[_row]), + ofcb->encoding_symbol_length); + of_free (ofcb->tab_const_term_of_equ[_row]); + ofcb->tab_const_term_of_equ[_row] = NULL; + // It'll be known at the end of this step + ofcb->tab_nb_unknown_symbols[_row]--; // symbol is known + of_mod2sparse_delete (ofcb->pchk_matrix, __r); + of_linear_binary_code_simplify_linear_system_with_a_symbol (ofcb, ofcb->encoding_symbols_tab[decoded_symbol_seqno], + decoded_symbol_seqno); + ofcb->nb_source_symbol_ready++; + } + } + else + { + // Decoded symbol is a parity symbol + if (ofcb->encoding_symbols_tab[decoded_symbol_seqno] == NULL) + { + if (ofcb->decoded_repair_symbol_callback != NULL) + { + ofcb->encoding_symbols_tab[decoded_symbol_seqno] = + ofcb->decoded_repair_symbol_callback(ofcb->context_4_callback, + ofcb->encoding_symbol_length, + decoded_symbol_seqno); + } + else + { + ofcb->encoding_symbols_tab[decoded_symbol_seqno] = of_malloc (ofcb->encoding_symbol_length); + } + if (ofcb->encoding_symbols_tab[decoded_symbol_seqno] == NULL) + { + goto no_mem; + } + // copy the content... + memcpy(ofcb->encoding_symbols_tab[decoded_symbol_seqno], + ofcb->tab_const_term_of_equ[_row], + ofcb->encoding_symbol_length); + of_free (ofcb->tab_const_term_of_equ[_row]); + ofcb->tab_const_term_of_equ[_row] = NULL; + // It'll be known at the end of this step + ofcb->tab_nb_unknown_symbols[_row]--; // symbol is known + ofcb->tab_nb_equ_for_repair[decoded_symbol_seqno - ofcb->nb_source_symbols]--; + of_mod2sparse_delete (ofcb->pchk_matrix, __r); + of_linear_binary_code_simplify_linear_system_with_a_symbol (ofcb, ofcb->encoding_symbols_tab[decoded_symbol_seqno], + decoded_symbol_seqno); + ofcb->nb_repair_symbol_ready++; + } + } + ofcb->remain_rows--; + } + } + ofcb->remain_cols--; + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +no_mem: + OF_PRINT_ERROR(("out of memory")) + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + + +of_status_t of_linear_binary_code_create_simplified_linear_system (of_linear_binary_code_cb_t *ofcb) +{ + INT32 _row; + INT32 _col; + of_mod2sparse *__pchk_matrix_simplified_cols; + UINT32 *index_rows; + UINT32 *index_cols; + + OF_ENTER_FUNCTION + ofcb->remain_rows = 0; + ofcb->remain_cols = 0; + if (ofcb->index_rows == NULL) + { + if ((ofcb->index_rows = (UINT32 *) of_calloc (ofcb->nb_repair_symbols, sizeof (UINT32))) == NULL) + { + goto no_mem; + } + } + if (ofcb->index_cols == NULL) + { + if ((ofcb->index_cols = (UINT32 *) of_calloc (ofcb->nb_total_symbols - ofcb->nb_repair_symbol_ready - ofcb->nb_source_symbol_ready, + sizeof (UINT32))) == NULL) + { + goto no_mem; + } + } + index_rows = (UINT32*) of_malloc(ofcb->nb_repair_symbols * sizeof(UINT32)); + index_cols = (UINT32*) of_malloc(ofcb->nb_total_symbols * sizeof(UINT32)); + if ((index_rows == NULL) || (index_cols == NULL)) + { + goto no_mem; + } + // Get the index of cols to copy from the original matrix + for (_col = 0 ; _col < ofcb->nb_total_symbols ; _col++) + { + if (!of_mod2sparse_empty_col (ofcb->pchk_matrix, _col)) + { + /* copy this col */ + index_cols[_col] = ofcb->remain_cols; // old location + ofcb->index_cols[ofcb->remain_cols++] = _col; // new location + } + } + // Get the index of rows to copy from the original matrix + for (_row = 0 ; _row < ofcb->nb_repair_symbols ; _row++) + { + if (!of_mod2sparse_empty_row (ofcb->pchk_matrix, _row)) + { + /* copy this row */ + index_rows[_row] = ofcb->remain_rows; + ofcb->index_rows[ofcb->remain_rows++] = _row; + } + } + if (ofcb->remain_cols == 0) + { + // the initial matrix is completely simplified, nothing remains. + OF_PRINT_LVL (1, ("%s: Failure, initial matrix is now empty, ofcb->remain_cols==0\n", __FUNCTION__)) + goto failure; + } + else if (ofcb->remain_rows < ofcb->remain_cols) + { + // impossible to continue as there are fewer rows than columns. + OF_PRINT_LVL (1, ("%s: Failure, fewer rows than columns, ofcb->remain_rows (%d) < ofcb->remain_cols (%d)\n", + __FUNCTION__, ofcb->remain_rows, ofcb->remain_cols)) + goto failure; + } + OF_TRACE_LVL (1, ("%s: Simplified Matrix: %dx%d; already decoded symbols: ready_src=%d, ready_parity=%d remaining_rows=%d remaining_cols=%d\n", + __FUNCTION__, ofcb->remain_rows, ofcb->remain_cols, ofcb->nb_source_symbol_ready, + ofcb->nb_repair_symbol_ready, ofcb->remain_rows, ofcb->remain_cols)) + + // allocate the new pchk_matrix_simplified, copy the non empty rows/cols in it + ofcb->pchk_matrix_simplified = of_mod2sparse_allocate (ofcb->nb_repair_symbols, ofcb->remain_cols); + of_mod2sparse_copy_filled_matrix(ofcb->pchk_matrix, ofcb->pchk_matrix_simplified, index_rows, index_cols); + of_mod2sparse_free (ofcb->pchk_matrix); + of_free (ofcb->pchk_matrix); + ofcb->pchk_matrix = NULL; + + of_free(index_rows); + of_free(index_cols); + OF_TRACE_LVL (1, ("ok\n")) + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +failure: + if (ofcb->index_rows) + { + of_free (ofcb->index_rows); + ofcb->index_rows = NULL; + } + if (ofcb->index_cols) + { + of_free (ofcb->index_cols); + ofcb->index_cols = NULL; + } + if (index_rows) + of_free(index_rows); + if (index_cols) + of_free(index_cols); + OF_EXIT_FUNCTION + return OF_STATUS_FAILURE; + +no_mem: + OF_PRINT_ERROR(("out of memory")) + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + + +#endif //ML_DECODING + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS + +#endif //OF_USE_DECODER diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_decoding.h b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_decoding.h new file mode 100644 index 0000000..6e38b70 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_decoding.h @@ -0,0 +1,61 @@ +/* $Id: of_ml_decoding.h 208 2014-12-12 18:39:20Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef ML_DECODING_H +#define ML_DECODING_H + +//#include "../../of_openfec_api.h" + +#ifdef OF_USE_DECODER +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS +#ifdef ML_DECODING + + +/** + * This function tries to finish decoding. + * + * @fn of_status_t of_linear_binary_code_finish_decoding_with_ml (of_linear_binary_code_cb_t *ofcb) + * @brief try to finish decoding + * @param ofcb (IN/OUT) Linear-Binary-Code control-block. + * @return 1 if it's OK, or 0 if an error appears. + */ +of_status_t of_linear_binary_code_finish_decoding_with_ml (of_linear_binary_code_cb_t *ofcb); + + +#endif //ML_DECODING + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS + +#endif //OF_USE_DECODER + +#endif /* ML_DECODING_H */ diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_tool.c b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_tool.c new file mode 100644 index 0000000..f98bede --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_tool.c @@ -0,0 +1,338 @@ +/* $Id: of_ml_tool.c 213 2014-12-12 22:36:41Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2011 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "../of_linear_binary_code.h" + +#ifdef OF_USE_DECODER +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS +#ifdef ML_DECODING + + +/****** Static Functions ****************************************************/ + + +/** + * This function transforms the matrix into a triangular matrix. It goes through each column and calls of_linear_binary_code_col_forward_elimination() + * to find the pivot and eliminate '1's below the pivot. + * + * @brief triangularize the dense system + * @param m (IN/OUT) address of the dense matrix. + * @param constant_tab (IN/OUT) + * @param ofcb (IN) Linear-Binary-Code control-block. + * @return 1 if it's OK, or 0 if an error took place. + */ +static INT32 +of_linear_binary_code_triangularize_dense_system (of_linear_binary_code_cb_t *ofcb, + of_mod2dense *m, + void **constant_tab); + + +/** + * This function finds the pivot for this column and eliminates '1's below this pivot. + * + * @brief eliminates "1" entries in parity check matrix + * @param m (IN/OUT) address of the dense matrix. + * @param constant_tab (IN/OUT) pointer to all constant members + * @param ofcb (IN/OUT) Linear-Binary-Code control-block. + * @param col_idx (IN) column index + * @param stats (IN) + * @return 1 if it's OK, or 0 if an error took place. + */ +static INT32 +of_linear_binary_code_col_forward_elimination (of_linear_binary_code_cb_t *ofcb, + of_mod2dense *m, + void **constant_tab, + INT32 col_idx); + + +/** + * This function computes the actual values of the symbols, starting from the bottom row up to the first one. It assumes the parity check matrix has + * already been transformed into a triangular matrix. + * + * @brief solve system with backward substitution + * @param variable_tab (IN/OUT) address of the dense matrix. + * @param constant_tab + * @param m (IN/OUT) address of the dense matrix. + * @param ofcb (IN/OUT) Linear-Binary-Code control-block. + * @return 1 if it's OK, or 0 if an error took place. + */ +static INT32 +of_linear_binary_code_backward_substitution (of_linear_binary_code_cb_t *ofcb, + of_mod2dense *m, + void *variable_tab[], + void *constant_tab[]); + + +/******************************************************************************/ + + + +/** + * This function solves the system: first triangularize the system, then for each column, + * do a forward elimination, then do the backward elimination. + */ +of_status_t +of_linear_binary_code_solve_dense_system (of_linear_binary_code_cb_t *ofcb, + of_mod2dense *m, + void **constant_tab, + void **variable_tab) +{ + OF_ENTER_FUNCTION + if (!of_linear_binary_code_triangularize_dense_system (ofcb, m, constant_tab)) + { + OF_TRACE_LVL(0,("%s: triangularize_dense_system failed for system with %d rows, %d cols\n", + __FUNCTION__, of_mod2dense_rows(m), of_mod2dense_cols(m))) + OF_EXIT_FUNCTION + return OF_STATUS_FAILURE; + } + //of_mod2dense_print_bitmap(m); + if (!of_linear_binary_code_backward_substitution (ofcb, m, variable_tab, constant_tab)) + { + OF_TRACE_LVL(0,("%s: backward_substitution failed\n", __FUNCTION__)) + OF_EXIT_FUNCTION + return OF_STATUS_FAILURE; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +/****** Static Functions ****************************************************/ + + +static +INT32 of_linear_binary_code_triangularize_dense_system (of_linear_binary_code_cb_t *ofcb, + of_mod2dense *m, + void **constant_tab) +{ + INT32 i, n; + + OF_ENTER_FUNCTION + n = of_mod2dense_cols (m); + /* for each row */ + for (i = 0; i < n; i++) + { + if (!of_linear_binary_code_col_forward_elimination(ofcb, m, constant_tab, i)) + { + OF_EXIT_FUNCTION + return 0; + } + } + OF_EXIT_FUNCTION + return 1; +} + + +static +INT32 of_linear_binary_code_col_forward_elimination (of_linear_binary_code_cb_t *ofcb, + of_mod2dense *m, + void **constant_tab, + INT32 col_idx) +{ + of_mod2word *s; + of_mod2word *t; + INT32 i, j, k; + INT32 n, p; + INT32 w; + INT32 w0; + INT32 b0; + INT32 symbol_size; + void *tmp_buffer; + + OF_ENTER_FUNCTION + symbol_size = ofcb->encoding_symbol_length; + n = of_mod2dense_cols (m); + p = of_mod2dense_rows (m); + w = m->n_words; + i = col_idx; + //printf("of_col_forward_elimination of col %d\n",i); + w0 = i >> of_mod2_wordsize_shift; // word index of the ith bit + b0 = i & of_mod2_wordsize_mask; // bit index of the ith bit in the w0-th word + /* search for the first non-null element of that column (pivot) */ + for (j = i; j < p; j++) + { + if (of_mod2_getbit(m->row[j][w0], b0)) + break; + } + /* now j is the index of the first non null element in column i */ + if (j == p) + { + /* it's a failure, it's not possible to choose a pivot for this empty column */ + OF_EXIT_FUNCTION + return 0; + } + if (j != i) + { + // swap columns i and j in the two matrices + //printf("swap rows %i and %i\n",j,i); + t = m->row[i]; + m->row[i] = m->row[j]; + m->row[j] = t; + // swap the partial sum + tmp_buffer = constant_tab[i]; + constant_tab[i] = constant_tab[j]; + constant_tab[j] = tmp_buffer; + //of_mod2dense_print(stdout,m); + } + /* we have found the pivot and made sure that it is at row i (potentially after swapping two rows). + * Now eliminate the other '1's below this pivot... */ + ofcb->nb_tmp_symbols = 0; + for (j = i + 1; j < p; j++) + { + if (of_mod2_getbit(m->row[j][w0], b0)) + { + /* there's a '1' below the pivot, so XOR the two rows (word by word to go faster). */ + //printf("\n\nxor in %i, %i\n",j,i); + s = m->row[j]; + t = m->row[i]; + s += w0; + t += w0; + for (k = w0; k < w; k++) + { + *s ^= *t; + s++; + t++; + } + //of_mod2dense_print(stdout,m); + if (constant_tab[i] != NULL) + { + /* if the buffer of line i is NULL there is nothing to add. + * add the constant term of the i to the constant term of line j */ + if (constant_tab[j] == NULL) + { + constant_tab[j] = of_malloc (symbol_size); + /* copy data directly, there's no XOR to perform */ + memcpy (constant_tab[j], constant_tab[i], symbol_size); + } + else + { + /* add constant term i to constant term j */ + ofcb->tmp_tab_symbols[ofcb->nb_tmp_symbols++] = constant_tab[j]; + } + } + else + { + constant_tab[i] = of_calloc (1, symbol_size); + } + } + } + if (ofcb->nb_tmp_symbols != 0) + { + if (ofcb->nb_tmp_symbols == 1) + { + of_add_to_symbol (ofcb->tmp_tab_symbols[0], constant_tab[i], symbol_size OP_ARG_VAL); + } + else + { + of_add_to_multiple_symbols (ofcb->tmp_tab_symbols, + constant_tab[i], + ofcb->nb_tmp_symbols, + ofcb->encoding_symbol_length +#ifdef OF_DEBUG + , &(ofcb->stats_xor->nb_xor_for_ML) +#endif + ); + } + } + OF_EXIT_FUNCTION + return 1; +} + + +/* old trivial backward substitution algorithm. */ +static +INT32 of_linear_binary_code_backward_substitution (of_linear_binary_code_cb_t *ofcb, + of_mod2dense *m, + void *variable_tab[], + void *constant_tab[]) +{ + INT32 i; /* current variable index for which we apply backward substition. It's also the row index. */ + INT32 j; /* */ + INT32 n; + INT32 w0; /* dense matrix word index for variable j */ + INT32 b0; /* dense matrix bit index in word of index w0 */ + + OF_ENTER_FUNCTION + n = of_mod2dense_cols (m); + /* go through all the rows, starting from the last one... */ + for (i = n - 1; i >= 0; i--) + { + ASSERT(variable_tab[i] == NULL); + //if (variable_tab[i] == NULL) + { + of_mod2word *row = m->row[i]; // row corresponding to variable i +#ifdef OF_DEBUG + w0 = i >> of_mod2_wordsize_shift; // word index of the ith bit + b0 = i & of_mod2_wordsize_mask; // bit index of the ith bit in the w0-th word + ASSERT(of_mod2_getbit(row[w0], b0)) +#endif + /* + * the missing source symbol in col i is equal to the sum of the constant term of this + * equation (i.e. row i) plus all the variables of this equation. + */ + //OF_TRACE_LVL(1, ("%s: rebuilding source symbol %d with col %d\n", __FUNCTION__, col_index[i], i)) + ASSERT(variable_tab[i] == NULL); + variable_tab[i] = constant_tab[i]; + constant_tab[i] = NULL; + /* determine the list of symbols to add to compute the decoded source symbol */ + ofcb->nb_tmp_symbols = 0; + for (j = i + 1; j < n; j++) + { + w0 = j >> of_mod2_wordsize_shift; // word index of the ith bit + b0 = j & of_mod2_wordsize_mask; // bit index of the ith bit in the w0-th word + /* search for the non-null element in row i */ + if (of_mod2_getbit(row[w0], b0)) + { + /* since the bit is set, add the variable_tab[j] symbol */ + ofcb->tmp_tab_symbols[ofcb->nb_tmp_symbols++] = variable_tab[j]; + } + } + if (ofcb->nb_tmp_symbols != 0) + { + of_add_from_multiple_symbols(variable_tab[i], (const void**)ofcb->tmp_tab_symbols, + ofcb->nb_tmp_symbols, ofcb->encoding_symbol_length +#ifdef OF_DEBUG + , &(ofcb->stats_xor->nb_xor_for_ML) +#endif + ); + } + } + } + OF_EXIT_FUNCTION + return 1; +} + + +#endif //ML_DECODING +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS +#endif //OF_USE_DECODER diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_tool.h b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_tool.h new file mode 100644 index 0000000..f2d5d64 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/ml_decoding/of_ml_tool.h @@ -0,0 +1,74 @@ +/* $Id: of_ml_tool.h 205 2014-12-10 04:17:19Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2011 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef OF_ML_TOOL +#define OF_ML_TOOL + + +#ifdef OF_USE_DECODER +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS +#ifdef ML_DECODING + +#ifdef OF_DEBUG +#define OP_ARGS ,UINT32* op +#define OP_ARG_VAL ,&(ofcb->stats_xor->nb_xor_for_ML) +#else +#define OP_ARGS +#define OP_ARG_VAL +#endif + + +/** + * This function solves the system: first triangularize the system, then for each column, + * do a forward elimination, then do the backward elimination. + * + * @fn INT32 of_linear_binary_code_solve_dense_system (of_mod2dense *m,void ** constant_member,void **variables,of_linear_binary_code_cb_t *ofcb) + * @brief solves the system + * @param m (IN/OUT) address of the dense matrix. + * @param variables + * @param constant_member (IN/OUT)pointer to all constant members + * @param ofcb (IN/OUT) Linear-Binary-Code control-block. + * @return error status + */ +of_status_t +of_linear_binary_code_solve_dense_system (of_linear_binary_code_cb_t *ofcb, + of_mod2dense *m, + void **constant_tab, + void **variable_tab); + + +#endif //ML_DECODING +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS +#endif //OF_USE_DECODER + +#endif //OF_ML_TOOL diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_create_pchk.c b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_create_pchk.c new file mode 100644 index 0000000..9f272cb --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_create_pchk.c @@ -0,0 +1,351 @@ +/* $Id: of_create_pchk.c 186 2014-07-16 07:17:53Z roca $ */ +/* + * The contents of this directory and its sub-directories are + * Copyright (c) 1995-2003 by Radford M. Neal + * + * Permission is granted for anyone to copy, use, modify, or distribute these + * programs and accompanying documents for any purpose, provided this copyright + * notice is retained and prominently displayed, along with a note saying + * that the original programs are available from Radford Neal's web page, and + * note is made of any changes made to these programs. These programs and + * documents are distributed without any warranty, express or implied. As the + * programs were written for research purposes only, they have not been tested + * to the degree that would be advisable in any important application. All use + * of these programs is entirely at the user's own risk. + */ + +#include "of_linear_binary_code.h" + + +of_mod2sparse* of_create_pchk_matrix (UINT32 nb_rows, + UINT32 nb_cols, + make_method make_method, + UINT32 left_degree, + UINT32 seed, + bool no4cycle, + of_session_type type, + UINT8 verbosity) +{ + OF_ENTER_FUNCTION + of_mod2sparse* m; + switch (type) { + case TypeREGULAR_LDPC: + m = of_create_pchk_matrix_general (nb_rows, nb_cols, make_method, left_degree, + seed, no4cycle, type, verbosity); + break; + + case Type2DMATRIX: + m = of_create_2D_pchk_matrix (nb_rows, nb_cols, type, verbosity); + break; + + default: + abort(); + OF_EXIT_FUNCTION + return NULL; + } + OF_EXIT_FUNCTION + return m; +} + + +of_mod2sparse* of_create_pchk_matrix_general (UINT32 nb_rows, + UINT32 nb_cols, + make_method make_method, + UINT32 left_degree, + UINT32 seed, + bool no4cycle, + of_session_type type, + UINT8 verbosity) +{ + UINT32 row_start = 0; + UINT32 row_end = 0; + UINT32 col_start = 0; + UINT32 col_end = 0; + INT32 i; + of_mod2sparse *pchkMatrix = NULL; + + OF_ENTER_FUNCTION + if (type != TypeLDGM && type != TypeSTAIRS && type != TypeTRIANGLE && type != TypeREGULAR_LDPC) + { + + OF_PRINT_ERROR(("unsupported code type (%d)\n", type)); + OF_EXIT_FUNCTION + return NULL; + } + /* a few sanity checks... */ + if (left_degree > nb_rows) + { + OF_PRINT_ERROR(("number of checks per bit (%d) is greater than total checks (%d)\n", + left_degree, nb_rows)); + OF_EXIT_FUNCTION + return NULL; + } + if (no4cycle) + { + OF_PRINT_ERROR(("no4cycle mode is no longer supported!")); + OF_EXIT_FUNCTION + return NULL; + } + of_rfc5170_srand (seed); + pchkMatrix = of_mod2sparse_allocate (nb_rows, nb_cols); + + switch (type) { + case TypeLDGM: + row_start = 0; + row_end = nb_rows; + col_start = nb_rows; + col_end = nb_cols; + break; + + case TypeREGULAR_LDPC: + row_start = 0; + row_end = nb_rows; + col_start = 0; + col_end = nb_cols; + break; + + default: + break; + } + of_fill_regular_pchk_matrix (pchkMatrix, row_start, row_end, col_start, col_end, make_method, + left_degree, no4cycle, verbosity); + + switch (type) { + case TypeLDGM: + for (i = 0; i < nb_rows; i++) + { + /* identity */ + of_mod2sparse_insert (pchkMatrix, i, i); + } + break; + + default: + // nothing to do + break; + } + + OF_EXIT_FUNCTION + return pchkMatrix; +} + + +of_mod2sparse* of_create_2D_pchk_matrix (UINT32 nb_rows, + UINT32 nb_cols, + of_session_type type, + UINT8 verbosity) +{ + OF_ENTER_FUNCTION + of_mod2sparse *pchkMatrix; + float d,l; // code dimensions for 2D pchk matrix + + if (nb_rows >= nb_cols) + { + OF_PRINT_ERROR(("In 2D parity check matrix, number of rows must not be greater than number of cols.\n")) + goto error; + } + for (d = floor(sqrt(nb_cols)); d > 0; d-- ) + { + l = ((float)((nb_cols-nb_rows))) / d; + if (l - floor(l) == 0 && ((d + l) == nb_rows)) + { + //it's OK for a correct 2D-pchk matrix + pchkMatrix = of_mod2sparse_allocate((l + d), (l * d) + (l + d)); + of_fill_2D_pchk_matrix(pchkMatrix, l, d, verbosity); + OF_EXIT_FUNCTION + return pchkMatrix; + } + } + +error: + OF_EXIT_FUNCTION + return NULL; +} + + +of_mod2sparse* of_fill_2D_pchk_matrix (of_mod2sparse *m, + UINT32 d, + UINT32 l, + UINT8 verbosity) +{ + OF_ENTER_FUNCTION + UINT32 i, j; + + for (i = 0; i < (l+d); i++) + { + of_mod2sparse_insert(m, i, i); + } + // create non interleaved constraints + for (i = 0; i < d; i++) + { + //set 1 for source symbols included in equation + for (j = 0; j < l; j++) + { + of_mod2sparse_insert(m, i, j + (i * l) + l + d); + } + } + // create interleaved constraints + for (i = d; i < l + d; i++) + { + for (j = 0; j < d; j++) + { + of_mod2sparse_insert(m, i, 4 * j + ( i - d )+l+d); + } + } + return m; + OF_EXIT_FUNCTION +} + + +of_mod2sparse* of_fill_regular_pchk_matrix (of_mod2sparse *m, + UINT32 row_start, + UINT32 row_end, + UINT32 col_start, + UINT32 col_end, + make_method make_method, + UINT32 left_degree, + bool no4cycle, + UINT8 verbosity) +{ + of_mod2entry *e; + UINT32 added, uneven; + INT32 i, j, k, t; + UINT32 *u; + of_mod2sparse *pchkMatrix = m; + UINT32 nb_col, nb_row; + + OF_ENTER_FUNCTION + nb_col = col_end - col_start; + nb_row = row_end - row_start; + + /* Create the initial version of the parity check matrix. */ + switch (make_method) + { + case Evencol: + for (j = col_start; j < col_end; j++) + { + for (k = 0; k < left_degree; k++) + { + do + { + i = of_rfc5170_rand (nb_row); + } + while (of_mod2sparse_find (pchkMatrix, i, j)); + of_mod2sparse_insert (pchkMatrix, i, j); + } + } + break; + + case Evenboth: + u = (UINT32*) of_calloc (left_degree * nb_col, sizeof * u); + + /* initialize a list of possible choices to guarantee a homogeneous "1" distribution */ + for (k = left_degree * nb_col - 1; k >= 0; k--) + { + u[k] = k % nb_row; + } + uneven = 0; + t = 0; /* left limit within the list of possible choices, u[] */ + for (j = col_start; j < col_end; j++) + { + /* for each source symbol column */ + for (k = 0; k < left_degree; k++) + { + /* add left_degree "1s" */ + /* check that valid available choices remain */ + for (i = t; i < left_degree*nb_col && of_mod2sparse_find (pchkMatrix, u[i], j); i++) + ; + + if (i < left_degree*nb_col) + { + /* choose one index within the list of possible choices */ + do + { + i = t + of_rfc5170_rand (left_degree * nb_col - t); + } + while (of_mod2sparse_find (pchkMatrix, u[i], j)); + of_mod2sparse_insert (pchkMatrix, u[i], j); + /* replace with u[t] which has never been chosen */ + u[i] = u[t]; + t++; + } + else + { + /* no choice left, choose one randomly */ + uneven += 1; + do + { + i = of_rfc5170_rand (nb_row); + } + while (of_mod2sparse_find (pchkMatrix, i, j)); + of_mod2sparse_insert (pchkMatrix, i, j); + } + } + } + + if (uneven > 0 && verbosity >= 1) + { + OF_PRINT_ERROR(("Had to place %d checks in rows unevenly\n", uneven)); + } + of_free (u); /* VR: added */ + break; + + default: + abort(); + } + + /* Add extra bits to avoid rows with less than two checks. */ + added = 0; + for (i = row_start; i < row_end; i++) + { + e = of_mod2sparse_first_in_row (pchkMatrix, i); + if (of_mod2sparse_at_end (e)) + { + j = (of_rfc5170_rand (nb_col) + col_start); + e = of_mod2sparse_insert (pchkMatrix, i, j); + added ++; + } + e = of_mod2sparse_first_in_row (pchkMatrix, i); + if (of_mod2sparse_at_end (of_mod2sparse_next_in_row (e)) && nb_col > 1) + { + do + { + j = (of_rfc5170_rand (nb_col)) + col_start; + } + while (j == of_mod2sparse_col (e)); + of_mod2sparse_insert (pchkMatrix, i, j); + added ++; + } + } + + if (added > 0 && verbosity >= 1) + { + OF_PRINT_ERROR(("Added %d extra bit-checks to make row counts at least two\n", added)); + } + + /* Add extra bits to try to avoid problems with even column counts. */ + if (left_degree % 2 == 0 && left_degree < nb_row && nb_col > 1 && added < 2) + { + UINT32 a; + for (a = 0; added + a < 2; a++) + { + do + { + i = of_rfc5170_rand (nb_row); + j = (of_rfc5170_rand (nb_col)) + col_start; + } + while (of_mod2sparse_find (pchkMatrix, i, j)); + of_mod2sparse_insert (pchkMatrix, i, j); + } + if (verbosity >= 1) + { + OF_PRINT_ERROR(("Added %d extra bit-checks to try to avoid problems from even column counts\n", a)); + } + OF_PRINT_LVL (1, ("Added %d extra bit-checks to try to avoid problems from even column counts\n", a)); + } + + OF_EXIT_FUNCTION + + return pchkMatrix; +} + + diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_create_pchk.h b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_create_pchk.h new file mode 100644 index 0000000..76a6e58 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_create_pchk.h @@ -0,0 +1,155 @@ +/* $Id: of_create_pchk.h 182 2014-07-15 09:27:51Z roca $ */ +/* + * The contents of this directory and its sub-directories are + * Copyright (c) 1995-2003 by Radford M. Neal + * + * Permission is granted for anyone to copy, use, modify, or distribute these + * programs and accompanying documents for any purpose, provided this copyright + * notice is retained and prominently displayed, along with a note saying + * that the original programs are available from Radford Neal's web page, and + * note is made of any changes made to these programs. These programs and + * documents are distributed without any warranty, express or implied. As the + * programs were written for research purposes only, they have not been tested + * to the degree that would be advisable in any important application. All use + * of these programs is entirely at the user's own risk. + */ + +#ifndef OF_LDPC_CREATE_PCHK +#define OF_LDPC_CREATE_PCHK + + +/** + * @enum make_method_enum + * @brief Define differents methods to build the parity check matrix. + */ +typedef enum make_method_enum +{ + Evencol, /* Uniform number of bits per column, with number specified */ + Evenboth /* Uniform (as possible) over both columns and rows */ +} make_method; + + +/** + * @enum SessionType_enum + * @brief Define differents type of sessions for creating the correct matrix + */ +typedef enum SessionType_enum +{ + TypeLDGM, + TypeSTAIRS, + TypeTRIANGLE, + TypeREAD_FROM_FILE, + TypeREAD_QC_FROM_FILE, + TypeLDPC_QC, + TypeREGULAR_LDPC, + Type2DMATRIX +} of_session_type; + + +/** + * This function creates the correct parity check matrix. + * + * @brief creates the correct parity check matrix + * @param nb_rows (IN) number of rows + * @param nb_cols (IN) number of cols + * @param make_method (IN) method to create the matrix + * @param left_degree (IN) number of "1" entry for each column + * @param seed (IN) seed for random generator + * @param no4cycle (IN) with or without cycles + * @param type (IN) type of matrix + * @param verbosity (IN) verbosity level + * @param stats (IN/OUT) memory statistics (can be NULL) + * @return pointer to the matrix + */ +of_mod2sparse* of_create_pchk_matrix (UINT32 nb_rows, + UINT32 nb_cols, + make_method make_method, + UINT32 left_degree, + UINT32 seed, + bool no4cycle, + of_session_type type, + UINT8 verbosity); + +/** + * This function creates a generic parity check matrix. + * + * @brief creates a matrix corresponding to RFC5170 + * @param nb_rows (IN) number of rows + * @param nb_cols (IN) number of cols + * @param make_method (IN) method to create the matrix + * @param left_degree (IN) number of "1" entry for each column + * @param seed (IN) seed for random generator + * @param no4cycle (IN) with or without cycles + * @param type (IN) type of matrix + * @param verbosity (IN) verbosity level + * @param stats (IN/OUT) memory statistics (can be NULL) + * @return pointer to the matrix + */ +of_mod2sparse* of_create_pchk_matrix_general (UINT32 nb_rows, + UINT32 nb_cols, + make_method make_method, + UINT32 left_degree, + UINT32 seed, + bool no4cycle, + of_session_type type, + UINT8 verbosity); + +/** + * This function fills a parity check matrix. + * + * @brief fills a parity check matrix + * @param m (IN) matrix to fill + * @param row_start (IN) number of row to start + * @param row_end (IN) number of row to stop + * @param col_start (IN) number of col to start + * @param col_end (IN) number of col to stop + * @param make_method (IN) method to fill the matrix + * @param left_degree (IN) number of "1" entry for each column + * @param no4cycle (IN) with or without cycles + * @param verbosity (IN) verbosity level + * @param stats (IN/OUT) memory statistics (can be NULL) + * @return pointer to the matrix + */ +of_mod2sparse* of_fill_regular_pchk_matrix (of_mod2sparse* m, + UINT32 row_start, + UINT32 row_end, + UINT32 col_start, + UINT32 col_end, + make_method make_method, + UINT32 left_degree, + bool no4cycle, + UINT8 verbosity); + +/** + * This function creates a parity check matrix for 2D codec. + * + * @brief creates a parity check matrix for 2D codec + * @param nb_rows (IN) number of rows + * @param nb_cols (IN) number of cols + * @param type (IN) type of matrix + * @param verbosity (IN) verbosity level + * @param stats (IN/OUT) memory statistics (can be NULL) + * @return pointer to the matrix + */ +of_mod2sparse* of_create_2D_pchk_matrix (UINT32 nb_rows, + UINT32 nb_cols, + of_session_type type, + UINT8 verbosity); + +/** + * This function fills a 2D parity check matrix. + * + * @brief fills a 2D parity check matrix + * @param m (IN/OUT) matrix to fill + * @param d (IN) number of rows + * @param l (IN) number of cols + * @param verbosity (IN) verbosity level + * @param stats (IN/OUT) memory statistics (can be NULL) + * @return pointer to the matrix + */ +of_mod2sparse* of_fill_2D_pchk_matrix (of_mod2sparse* m, + UINT32 d, + UINT32 l, + UINT8 verbosity); + +#endif diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_linear_binary_code.h b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_linear_binary_code.h new file mode 100644 index 0000000..221e666 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_linear_binary_code.h @@ -0,0 +1,147 @@ +/* $Id: of_linear_binary_code.h 209 2014-12-12 18:49:58Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2011 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef LINEAR_BINARY_CODE_H +#define LINEAR_BINARY_CODE_H + +#include +#include +#include +#include +//#ifdef USE_NEON +//#include +//#endif + +#include "../of_openfec_api.h" // includes of_type.h, of_debug.h + +#ifdef IL_SUPPORT +#include +#endif + +#ifdef ASSEMBLY_SSE_OPT +#include +#endif + +#include "../of_rand.h" +#include "../of_cb.h" +#include "../of_mem.h" +#include "of_symbol.h" +#include "../statistics/of_statistics.h" + +#include "binary_matrix/of_matrix_sparse.h" +#include "binary_matrix/of_matrix_dense.h" +#include "of_create_pchk.h" + +#include "binary_matrix/of_matrix_convert.h" +#include "binary_matrix/of_hamming_weight.h" +#include "binary_matrix/of_tools.h" + + +/** + * Linear-Binary-Code stable codec specific control block structure. + */ +typedef struct of_linear_binary_code_cb +{ +/***************************************************************************** +* of_cb_t * +******************************************************************************/ + of_codec_id_t codec_id; /* must begin with fec_codec_id */ + of_codec_type_t codec_type; /* must be 2nd item */ + UINT32 nb_source_symbols; /** k parameter (AKA code dimension). */ + UINT32 nb_repair_symbols; /** r = n - k parameter. */ + UINT32 encoding_symbol_length; /** symbol length. */ +/*****************************************************************************/ + + UINT32 nb_total_symbols; /** n parameter (AKA code length). */ + /* parity check matrix */ + of_mod2sparse* pchk_matrix; + + /** statistics for this codec instance. */ + of_symbol_stats_op_t *stats_xor; +#ifdef OF_DEBUG + of_symbols_stats_t *stats_symbols; +#endif + + UINT32 nb_source_symbol_ready; // Number of source symbols ready + UINT32 nb_repair_symbol_ready; // Number of parity symbols ready + +#ifdef ML_DECODING + UINT32 *index_rows; // Indirection index to access initial m_chekValues array + UINT32 *index_cols; // Indirection index to access initial symbol array + UINT32 remain_cols; // Nb of non empty remaining cols in the future simplified matrix + UINT32 remain_rows; // Nb of non empty remaining rows in the future simplified matrix + + of_mod2sparse *pchk_matrix_simplified; // Simplified Parity Check Matrix in sparse mode format + of_mod2sparse *original_pchkMatrix; + of_mod2sparse *pchk_matrix_gauss; // Parity Check matrix in sparse mode format. + + UINT32 dec_step; // Current step in the Gauss decoding algorithm + UINT32 threshold_simplification;// threshold (number of symbols) above which we + // run the Gaussian Elimination algorithm +#endif + +#ifdef OF_USE_DECODER /* { */ + /** table of all check values, i.e. that contain the constant term of each equation. */ + void** tab_const_term_of_equ; + /** table containing the number of encoding symbols of each equation. */ + UINT16* tab_nb_enc_symbols_per_equ; + /** table containing the number of unknow symbols (i.e. neither received nor decoded + * at that time) of each equation. */ + UINT16* tab_nb_unknown_symbols; + /** table containing the number of equations in which a repair symbol is included. */ + UINT16* tab_nb_equ_for_repair; + + void ** repair_symbols_values; + void ** tmp_tab_symbols; + UINT16 nb_tmp_symbols; +#endif /* } OF_USE_DECODER */ + + void **encoding_symbols_tab; + + /** callbacks registered by the application. */ + void* (*decoded_source_symbol_callback) (void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi); /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi); /* encoding symbol ID in {0..k-1} */ + void* context_4_callback; +} of_linear_binary_code_cb_t; + + +#include "it_decoding/of_it_decoding.h" +#include "ml_decoding/of_ml_decoding.h" +#include "ml_decoding/of_ml_tool.h" + + +#endif diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_symbol.c b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_symbol.c new file mode 100644 index 0000000..487fb5b --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_symbol.c @@ -0,0 +1,657 @@ +/* $Id: of_symbol.c 206 2014-12-10 04:47:09Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "of_linear_binary_code.h" + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + + +#ifndef OF_DEBUG +void of_add_from_multiple_symbols (void *to, + const void **from, + UINT32 from_size, + UINT32 symbol_size) +#else +void of_add_from_multiple_symbols (void *to, + const void **from, + UINT32 from_size, + UINT32 symbol_size, + UINT32 *op) +#endif +{ + OF_ENTER_FUNCTION +#ifdef OF_DEBUG + if (op != NULL) + (*op)+=from_size; +#endif + UINT32 i; +//#ifndef ASSEMBLY_SSE_OPT /* { */ + UINT32 symbolSize32; + UINT32 symbolSize32rem; + //printf("%i\n",from_size); + + symbolSize32 = symbol_size >> 2; + symbolSize32rem = symbol_size % 4; // Remaining bytes when the symbol + // size is not multiple of 32 bits. + +#if defined (__LP64__) || (__WORDSIZE == 64) // { + /* + * 64-bit machines + */ + + UINT32 symbolSize64; // Size of symbols in 64-bit unit + // symbol_size is not necessarily a multiple of 8, but >> 3 will divide + // it by 8 and keep the integral part automatically. + symbolSize64 = symbol_size >> 3; + while (from_size >=8) + { + UINT64* t = (UINT64*) to; // to pointer to 64-bit integers + UINT64* ps1 = (UINT64*)from[0]; + UINT64* ps2 = (UINT64*)from[1]; + UINT64* ps3 = (UINT64*)from[2]; + UINT64* ps4 = (UINT64*)from[3]; + UINT64* ps5 = (UINT64*)from[4]; + UINT64* ps6 = (UINT64*)from[5]; + UINT64* ps7 = (UINT64*)from[6]; + UINT64* ps8 = (UINT64*)from[7]; + from_size-=8; + from+=8; + for (i = symbolSize64; i > 0; i--) + { + *t ^= (*ps1 ^ *ps2 ^ *ps3 ^ *ps4 ^ *ps5 ^ *ps6 ^ *ps7 ^ *ps8); + t++; + ps1++; + ps2++; + ps3++; + ps4++; + ps5++; + ps6++; + ps7++; + ps8++; + } + UINT32* t32 = (UINT32*) t; // to pointer to 32-bit integers + UINT32* ps1_32 = (UINT32*) ps1; // from pointer to 32-bit integers + UINT32* ps2_32 = (UINT32*) ps2; // from pointer to 32-bit integers + UINT32* ps3_32 = (UINT32*) ps3; // from pointer to 32-bit integers + UINT32* ps4_32 = (UINT32*) ps4; // from pointer to 32-bit integers + UINT32* ps5_32 = (UINT32*) ps5; // from pointer to 32-bit integers + UINT32* ps6_32 = (UINT32*) ps6; // from pointer to 32-bit integers + UINT32* ps7_32 = (UINT32*) ps7; // from pointer to 32-bit integers + UINT32* ps8_32 = (UINT32*) ps8; // from pointer to 32-bit integers + + /* then perform a 32-bit XOR if needed... */ + if ( (symbolSize64 << 1) < symbolSize32) + { + * (UINT32*) t32 ^= (* (UINT32*) ps1_32 ^ * (UINT32*) ps2_32 ^ * (UINT32*) ps3_32 ^ * (UINT32*) ps4_32 ^ + * (UINT32*) ps5_32 ^ * (UINT32*) ps6_32 ^ * (UINT32*) ps7_32 ^ * (UINT32*) ps8_32); + ps1_32++; + ps2_32++; + ps3_32++; + ps4_32++; + ps5_32++; + ps6_32++; + ps7_32++; + ps8_32++; + t32++; + } + if (symbolSize32rem > 0) + { + for (i = 0; i < symbolSize32rem; i++) + { + * (UINT8*) ( (UINT8*) t32 + i) ^= ((* (UINT8*) ( (UINT8*) ps1_32 + i)) ^ (* (UINT8*) ( (UINT8*) ps2_32 + i) ) ^ + (* (UINT8*) ( (UINT8*) ps3_32 + i) ) ^ (* (UINT8*) ( (UINT8*) ps4_32 + i) ) ^ + (* (UINT8*) ( (UINT8*) ps5_32 + i) ) ^ (* (UINT8*) ( (UINT8*) ps6_32 + i) ) ^ + (* (UINT8*) ( (UINT8*) ps7_32 + i) ) ^ (* (UINT8*) ( (UINT8*) ps8_32 + i) ) ); + } + } + } + while (from_size >=4) + { + UINT64* t = (UINT64*) to; // to pointer to 64-bit integers + UINT64* ps1 = (UINT64*)from[0]; + UINT64* ps2 = (UINT64*)from[1]; + UINT64* ps3 = (UINT64*)from[2]; + UINT64* ps4 = (UINT64*)from[3]; + from_size-=4; + from+=4; + for (i = symbolSize64; i > 0; i--) + { + *t ^= (*ps1 ^ *ps2 ^ *ps3 ^ *ps4); + t++; + ps1++; + ps2++; + ps3++; + ps4++; + } + UINT32* t32 = (UINT32*) t; // to pointer to 32-bit integers + UINT32* ps1_32 = (UINT32*) ps1; // from pointer to 32-bit integers + UINT32* ps2_32 = (UINT32*) ps2; // from pointer to 32-bit integers + UINT32* ps3_32 = (UINT32*) ps3; // from pointer to 32-bit integers + UINT32* ps4_32 = (UINT32*) ps4; // from pointer to 32-bit integers + + /* then perform a 32-bit XOR if needed... */ + if ( (symbolSize64 << 1) < symbolSize32) + { + * (UINT32*) t32 ^= (* (UINT32*) ps1_32 ^ * (UINT32*) ps2_32 ^ * (UINT32*) ps3_32 ^ * (UINT32*) ps4_32 ); + ps1_32++; + ps2_32++; + ps3_32++; + ps4_32++; + t32++; + } + if (symbolSize32rem > 0) + { + for (i = 0; i < symbolSize32rem; i++) + { + * (UINT8*) ( (UINT8*) t32 + i) ^= ((* (UINT8*) ( (UINT8*) ps1_32 + i)) ^ (* (UINT8*) ( (UINT8*) ps2_32 + i) ) ^ + (* (UINT8*) ( (UINT8*) ps3_32 + i) ) ^ (* (UINT8*) ( (UINT8*) ps4_32 + i) ) ); + } + } + } + while (from_size >=2) + { + UINT64* t = (UINT64*) to; // to pointer to 64-bit integers + UINT64* ps1 = (UINT64*)from[0]; + UINT64* ps2 = (UINT64*)from[1]; + from+=2; + from_size-=2; + for (i = symbolSize64; i > 0; i--) + { + *t ^= (*ps1 ^ *ps2); + t++; + ps1++; + ps2++; + } + UINT32* t32 = (UINT32*) t; // to pointer to 32-bit integers + UINT32* ps1_32 = (UINT32*) ps1; // from pointer to 32-bit integers + UINT32* ps2_32 = (UINT32*) ps2; // from pointer to 32-bit integers + /* then perform a 32-bit XOR if needed... */ + if ( (symbolSize64 << 1) < symbolSize32) + { + * (UINT32*) t32 ^= (* (UINT32*) ps1_32 ^ * (UINT32*) ps2_32); + ps1_32++; + ps2_32++; + t32++; + } + if (symbolSize32rem > 0) + { + for (i = 0; i < symbolSize32rem; i++) + { + * (UINT8*) ( (UINT8*) t32 + i) ^= ((* (UINT8*) ( (UINT8*) ps1_32 + i)) ^ (* (UINT8*) ( (UINT8*) ps2_32 + i) )); + } + } + } + + if (from_size == 0) return; + + UINT64 *t = (UINT64*) to; // to pointer to 64-bit integers + UINT64 *f = (UINT64*) from[0]; // from pointer to 64-bit integers + for (i = symbolSize64; i > 0; i--) + { + *t ^= *f; + t++; + f++; + } + UINT32 *t32 = (UINT32*) t; // to pointer to 32-bit integers + UINT32 *f32 = (UINT32*) f; // from pointer to 32-bit integers + /* then perform a 32-bit XOR if needed... */ + if ( (symbolSize64 << 1) < symbolSize32) + { + * (UINT32*) t32 ^= * (UINT32*) f32; + t32++; + f32++; + } + /* finally perform as many 8-bit XORs as needed if symbol size is not + * multiple of 32 bits... */ + if (symbolSize32rem > 0) + { + for (i = 0; i < symbolSize32rem; i++) + { + * (UINT8*) ( (UINT8*) t32 + i) ^= * (UINT8*) ( (UINT8*) f32 + i); + } + } + +#else //defined (__LP64__) || (__WORDSIZE == 64) } { + + /* + * 32-bit machines + */ + UINT32 *t32 = (UINT32*) to; // to pointer to 32-bit integers + UINT32 *f32 = (UINT32*) from; // from pointer to 32-bit integers + /* First perform as many 32-bit XORs as needed... */ + for (i = symbolSize32; i > 0; i--) + { + *t32 ^= *f32; + t32++; + f32++; + } + /* finally perform as many 8-bit XORs as needed if symbol size is not + * multiple of 32 bits... */ + if (symbolSize32rem > 0) + { + for (i = 0; i < symbolSize32rem; i++) + { + * (UINT8*) ( (UINT8*) t32 + i) ^= * (UINT8*) ( (UINT8*) f32 + i); + } + } +#endif //defined (__LP64__) || (__WORDSIZE == 64) } + +//#else /* } ASSEMBLY_SSE_OPT { */ + +//#endif +} + + +#ifndef OF_DEBUG +void of_add_to_multiple_symbols (void **to, + const void *from, + UINT32 to_size, + UINT32 symbol_size) +#else +void of_add_to_multiple_symbols (void **to, + const void *from, + UINT32 to_size, + UINT32 symbol_size, + UINT32 *op) +#endif +{ + OF_ENTER_FUNCTION +#ifdef OF_DEBUG + if (op != NULL) + (*op) += to_size; +#endif + UINT32 i; + //#ifndef ASSEMBLY_SSE_OPT /* { */ + UINT32 symbolSize32; + UINT32 symbolSize32rem; + + symbolSize32 = symbol_size >> 2; + symbolSize32rem = symbol_size % 4; // Remaining bytes when the symbol + // size is not multiple of 32 bits. +#if defined (__LP64__) || (__WORDSIZE == 64) // { + /* + * 64-bit machines + */ + UINT32 symbolSize64; // Size of symbols in 64-bit unit + // symbol_size is not necessarily a multiple of 8, but >> 3 will divide + // it by 8 and keep the integral part automatically. + symbolSize64 = symbol_size >> 3; + UINT64 *pt1, *pt2, *pt3, *pt4, *pt5, *pt6, *pt7, *pt8, *from_s, from_value; + + while (to_size >= 8) + { + from_s = (UINT64*) from; // to pointer to 64-bit integers + pt1 = (UINT64*)to[0]; + pt2 = (UINT64*)to[1]; + pt3 = (UINT64*)to[2]; + pt4 = (UINT64*)to[3]; + pt5 = (UINT64*)to[4]; + pt6 = (UINT64*)to[5]; + pt7 = (UINT64*)to[6]; + pt8 = (UINT64*)to[7]; + to += 8; + to_size -= 8; + for (i = symbolSize64; i > 0; i--) + { + from_value = *from_s; + *pt1 ^= from_value; + *pt2 ^= from_value ; + *pt3 ^= from_value ; + *pt4 ^= from_value ; + *pt5 ^= from_value ; + *pt6 ^= from_value ; + *pt7 ^= from_value ; + *pt8 ^= from_value ; + from_s++; + pt1++; + pt2++; + pt3++; + pt4++; + pt5++; + pt6++; + pt7++; + pt8++; + } + UINT32* from_s32 = (UINT32*) from_s; // to pointer to 32-bit integers + /* then perform a 32-bit XOR if needed... */ + from_s32 = (UINT32*) from_s; // pointer to 32-bit integers + if ( (symbolSize64 << 1) < symbolSize32) + { + (* (UINT32*) pt1++) ^= *from_s32; + (* (UINT32*) pt2++) ^= *from_s32; + (* (UINT32*) pt3++) ^= *from_s32; + (* (UINT32*) pt4++) ^= *from_s32; + (* (UINT32*) pt5++) ^= *from_s32; + (* (UINT32*) pt6++) ^= *from_s32; + (* (UINT32*) pt7++) ^= *from_s32; + (* (UINT32*) pt8++) ^= *from_s32; + from_s32++; + } + if (symbolSize32rem > 0) + { + UINT8* s8; + for (i = 0; i < symbolSize32rem; i++) + { + s8 = ( (UINT8*) from_s32 + i); + (* (UINT8*) ( (UINT8*) pt1 + i)) ^= * (UINT8*) s8; + (* (UINT8*) ( (UINT8*) pt2 + i)) ^= * (UINT8*) s8; + (* (UINT8*) ( (UINT8*) pt3 + i)) ^= * (UINT8*) s8; + (* (UINT8*) ( (UINT8*) pt4 + i)) ^= * (UINT8*) s8; + (* (UINT8*) ( (UINT8*) pt5 + i)) ^= * (UINT8*) s8; + (* (UINT8*) ( (UINT8*) pt6 + i)) ^= * (UINT8*) s8; + (* (UINT8*) ( (UINT8*) pt7 + i)) ^= * (UINT8*) s8; + (* (UINT8*) ( (UINT8*) pt8 + i)) ^= * (UINT8*) s8; + } + } + } + while (to_size >= 4) + { + UINT32 *from_s32; // to pointer to 32-bit integers + + from_s = (UINT64*) from; // to pointer to 64-bit integers + pt1 = (UINT64*)to[0]; + pt2 = (UINT64*)to[1]; + pt3 = (UINT64*)to[2]; + pt4 = (UINT64*)to[3]; + to += 4; + to_size -= 4; + for (i = symbolSize64; i > 0; i--) + { + from_value = *from_s; + *pt1 ^= from_value; + *pt2 ^= from_value; + *pt3 ^= from_value; + *pt4 ^= from_value; + from_s++; + pt1++; + pt2++; + pt3++; + pt4++; + } + /* then perform a 32-bit XOR if needed... */ + from_s32 = (UINT32*) from_s; + if ( (symbolSize64 << 1) < symbolSize32) + { + (* (UINT32*) pt1++) ^= *from_s32; + (* (UINT32*) pt2++) ^= *from_s32; + (* (UINT32*) pt3++) ^= *from_s32; + (* (UINT32*) pt4++) ^= *from_s32; + from_s32++; + } + if (symbolSize32rem > 0) + { + UINT8 *s8; + for (i = 0; i < symbolSize32rem; i++) + { + s8 = ( (UINT8*) from_s32 + i); + (* (UINT8*) ( (UINT8*) pt1 + i)) ^= * (UINT8*) s8; + (* (UINT8*) ( (UINT8*) pt2 + i)) ^= * (UINT8*) s8; + (* (UINT8*) ( (UINT8*) pt3 + i)) ^= * (UINT8*) s8; + (* (UINT8*) ( (UINT8*) pt4 + i)) ^= * (UINT8*) s8; + } + } + } + while (to_size >= 2) + { + UINT32 *from_s32; // to pointer to 32-bit integers + + from_s = (UINT64*) from; // to pointer to 64-bit integers + pt1 = (UINT64*)to[0]; + pt2 = (UINT64*)to[1]; + + to += 2; + to_size -= 2; + for (i = symbolSize64; i > 0; i--) + { + *pt1 ^= *from_s ; + *pt2 ^= *from_s ; + from_s++; + pt1++; + pt2++; + } + /* then perform a 32-bit XOR if needed... */ + from_s32 = (UINT32*) from_s; // pointer to 32-bit integers + if ( (symbolSize64 << 1) < symbolSize32) + { + (* (UINT32*) pt1++) ^= *from_s32; + (* (UINT32*) pt2++) ^= *from_s32; + from_s32++; + } + if (symbolSize32rem > 0) + { + UINT8 *s8; + for (i = 0; i < symbolSize32rem; i++) + { + s8 = ( (UINT8*) from_s32 + i); + (* (UINT8*) ( (UINT8*) pt1 + i)) ^= * (UINT8*) s8; + (* (UINT8*) ( (UINT8*) pt2 + i)) ^= * (UINT8*) s8; + } + } + } + + if (to_size == 0) return; + + UINT64 *t = (UINT64*) to[0]; // to pointer to 64-bit integers + UINT64 *f = (UINT64*) from; // from pointer to 64-bit integers + for (i = symbolSize64; i > 0; i--) + { + *t ^= *f; + t++; + f++; + } + UINT32* t32 = (UINT32*) t; // to pointer to 32-bit integers + UINT32 *f32 = (UINT32*) f; // from pointer to 32-bit integers + /* then perform a 32-bit XOR if needed... */ + if ( (symbolSize64 << 1) < symbolSize32) + { + * (UINT32*) t32 ^= * (UINT32*) f32; + t32++; + f32++; + } + /* finally perform as many 8-bit XORs as needed if symbol size is not + * multiple of 32 bits... */ + if (symbolSize32rem > 0) + { + for (i = 0; i < symbolSize32rem; i++) + { + * (UINT8*) ( (UINT8*) t32 + i) ^= * (UINT8*) ( (UINT8*) f32 + i); + } + } + +#else //defined (__LP64__) || (__WORDSIZE == 64) } { + + /* + * 32-bit machines + */ + UINT32 *t32 = (UINT32*) to; // to pointer to 32-bit integers + UINT32 *f32 = (UINT32*) from; // from pointer to 32-bit integers + /* First perform as many 32-bit XORs as needed... */ + for (i = symbolSize32; i > 0; i--) + { + *t32 ^= *f32; + t32++; + f32++; + } + /* finally perform as many 8-bit XORs as needed if symbol size is not + * multiple of 32 bits... */ + if (symbolSize32rem > 0) + { + for (i = 0; i < symbolSize32rem; i++) + { + * (UINT8*) ( (UINT8*) t32 + i) ^= * (UINT8*) ( (UINT8*) f32 + i); + } + } +#endif //defined (__LP64__) || (__WORDSIZE == 64) } + + //#else /* } ASSEMBLY_SSE_OPT { */ + + //#endif /* } ASSEMBLY_SSE_OPT */ +} + + + +#ifdef OF_DEBUG +void of_add_to_symbol (void *to, + const void *from, + UINT32 symbol_size, + UINT32 *op) +#else +void of_add_to_symbol (void *to, + const void *from, + UINT32 symbol_size) +#endif +{ + //OF_ENTER_FUNCTION + UINT32 i; +#ifdef OF_DEBUG + if (op != NULL) + (*op)++; +#endif +#ifndef ASSEMBLY_SSE_OPT /* { */ + UINT32 symbolSize32; + UINT32 symbolSize32rem; + + symbolSize32 = symbol_size >> 2; + symbolSize32rem = symbol_size % 4; // Remaining bytes when the symbol + // size is not multiple of 32 bits. + +#if defined (__LP64__) || (__WORDSIZE == 64) // { + /* + * 64-bit machines + */ + + UINT32 symbolSize64; // Size of symbols in 64-bit unit + // symbol_size is not necessarily a multiple of 8, but >> 3 will divide + // it by 8 and keep the integral part automatically. + symbolSize64 = symbol_size >> 3; + /* First perform as many 64-bit XORs as needed... */ + UINT64 *t = (UINT64*) to; // to pointer to 64-bit integers + UINT64 *f = (UINT64*) from; // from pointer to 64-bit integers + for (i = symbolSize64; i > 0; i--) + { + *t ^= *f; + t++; + f++; + } + UINT32 *t32 = (UINT32*) t; // to pointer to 32-bit integers + UINT32 *f32 = (UINT32*) f; // from pointer to 32-bit integers + /* then perform a 32-bit XOR if needed... */ + if ( (symbolSize64 << 1) < symbolSize32) + { + * (UINT32*) t32 ^= * (UINT32*) f32; + t32++; + f32++; + } + /* finally perform as many 8-bit XORs as needed if symbol size is not + * multiple of 32 bits... */ + if (symbolSize32rem > 0) + { + for (i = 0; i < symbolSize32rem; i++) + { + * (UINT8*) ( (UINT8*) t32 + i) ^= * (UINT8*) ( (UINT8*) f32 + i); + } + } + +#else //defined (__LP64__) || (__WORDSIZE == 64) } { + + /* + * 32-bit machines + */ + UINT32 *t32 = (UINT32*) to; // to pointer to 32-bit integers + UINT32 *f32 = (UINT32*) from; // from pointer to 32-bit integers + /* First perform as many 32-bit XORs as needed... */ + for (i = symbolSize32; i > 0; i--) + { + *t32 ^= *f32; + t32++; + f32++; + } + /* finally perform as many 8-bit XORs as needed if symbol size is not + * multiple of 32 bits... */ + if (symbolSize32rem > 0) + { + for (i = 0; i < symbolSize32rem; i++) + { + * (UINT8*) ( (UINT8*) t32 + i) ^= * (UINT8*) ( (UINT8*) f32 + i); + } + } +#endif //defined (__LP64__) || (__WORDSIZE == 64) } + +#else /* } ASSEMBLY_SSE_OPT { */ + + /* + * machine with SSE capable CPU + * Use assembly language to XOR two 128 bit registers at a time. + */ + UINT32 symbolSize32rem = symbol_size % 16; // Remaining bytes when the symbol + // size is not multiple of 32 bits. + UINT32 symbolSize128; + symbolSize128 = symbol_size >> 4; + float *dst128; + float *src128; + dst128 = (float *) to; + src128 = (float *) from; + __m128 a, b; + + for (i = symbolSize128 ; i-- ;) + { + a = _mm_load_ps (dst128); + b = _mm_load_ps (src128); + a = _mm_xor_ps (a, b); + _mm_store_ps (dst128, a); + dst128 += 4; + src128 += 4; + } + if (symbolSize32rem > 0) + { + for (i = 0; i < symbolSize32rem; i++) + { + * (UINT8*) ( (UINT8*) dst128 + i) ^= * (UINT8*) ( (UINT8*) src128 + i); + } + } +#endif /* } ASSEMBLY_SSE_OPT */ + OF_EXIT_FUNCTION +} + + +void of_print_xor_symbols_statistics (of_symbol_stats_op_t *xor) +{ + if (xor != NULL) + { + OF_TRACE_LVL(0, ("XOR stats:\n\tnb_xor_for_IT=%u nb_xor_for_ML=%u\n", + xor->nb_xor_for_IT, xor->nb_xor_for_ML)) + } +} + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS diff --git a/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_symbol.h b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_symbol.h new file mode 100644 index 0000000..fb883c2 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/linear_binary_codes_utils/of_symbol.h @@ -0,0 +1,155 @@ +/* $Id: of_symbol.h 198 2014-07-17 08:41:01Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef OF_SYMBOL +#define OF_SYMBOL + + +#ifdef OF_USE_LINEAR_BINARY_CODES_UTILS + + +typedef struct of_symbol_stats_op +{ + UINT32 nb_xor_for_IT; + UINT32 nb_xor_for_ML; +} of_symbol_stats_op_t; + + +/** + * @brief check if the symbol number "new_symbol_esi" is a source symbol + * @param ofcb (IN) Pointer to the control block. + * @param new_symbol_esi (IN) encoding symbol ID + * @return Error status. + */ +#define of_is_source_symbol(ofcb,new_symbol_esi) (((new_symbol_esi) < (ofcb)->nb_source_symbols) ? true : false) + +/* + * @brief check if the symbol number "new_symbol_esi" is a repair symbol + * @param ofcb (IN) Pointer to the control block. + * @param new_symbol_esi (IN) encoding symbol ID + * @return Error status. + */ +#define of_is_repair_symbol(ofcb,new_symbol_esi) (((new_symbol_esi) < (ofcb)->nb_source_symbols) ? false : true) + +/** + * @brief get the encoding symbol ID of a matrix column + * @param ofcb (IN) Pointer to the control block. + * @param matrix_col (IN) number of the matrix column + * @return Error status. + */ +#define of_get_symbol_esi(ofcb,matrix_col) (((matrix_col) < (ofcb)->nb_repair_symbols) ? (INT32)((matrix_col) + (ofcb)->nb_source_symbols) : (INT32)((matrix_col) - (ofcb)->nb_repair_symbols)) + +/** + * @brief get symbol matrix column + * @param ofcb (IN) Pointer to the control block. + * @param esi (IN) encoding symbol ID + * @return Error status. + */ +#define of_get_symbol_col(ofcb,esi) (((esi) < (ofcb)->nb_source_symbols) ? (INT32)((esi) + (ofcb)->nb_repair_symbols) : (INT32)((esi) - (ofcb)->nb_source_symbols)) + +/** + * Compute the XOR sum of two symbols: to = to + from. + * This function must be highly optimized, since it is one of the most computationally + * expensive ones. These optimizations depend on the target platform, from both the + * hardware and software point of views. + * + * @param to (IN/OUT) source symbol. + * @param from (IN) symbol added to the source symbol. + * @param symbol_size (IN) size in byte + */ +#ifdef OF_DEBUG +void of_add_to_symbol (void *to, + const void *from, + UINT32 symbol_size, + UINT32*); +#else +void of_add_to_symbol (void *to, + const void *from, + UINT32 symbol_size); +#endif + +/** + * Compute the XOR sum of several symbols: to = to + from1 + from2 + .... + * This function must be highly optimized, since it is one of the most computationally + * expensive ones. These optimizations depend on the target platform, from both the + * hardware and software point of views. + * + * @param to (IN/OUT) source symbol. + * @param from (IN) symbols added to the source symbol. + * @param from_size (IN) number of "from" symbols + * @param symbol_size (IN) size in byte + */ +#ifdef OF_DEBUG +void of_add_from_multiple_symbols (void *to, + const void **from, + UINT32 from_size, + UINT32 symbol_size, + UINT32*); +#else +void of_add_from_multiple_symbols (void *to, + const void **from, + UINT32 from_size, + UINT32 symbol_size); +#endif + +/** + * Compute the XOR sum of several symbols: to1 = to1 + from; to2 = to2 + from; ... + * This function must be highly optimized, since it is one of the most computationally + * expensive ones. These optimizations depend on the target platform, from both the + * hardware and software point of views. + * + * @param to (IN/OUT) source symbols. + * @param from (IN) symbol added to the source symbol. + * @param to_size (IN) number of "to" symbols + * @param symbol_size (IN) size in byte + */ +#ifdef OF_DEBUG +void of_add_to_multiple_symbols (void **to, + const void *from, + UINT32 to_size, + UINT32 symbol_size, + UINT32*); +#else +void of_add_to_multiple_symbols (void **to, + const void *from, + UINT32 to_size, + UINT32 symbol_size); +#endif + +#ifdef OF_DEBUG +void of_print_xor_symbols_statistics(of_symbol_stats_op_t*); +#endif + +#endif //OF_USE_LINEAR_BINARY_CODES_UTILS + +#endif //OF_SYMBOL diff --git a/thirdparty/openfec/src/lib_common/of_cb.h b/thirdparty/openfec/src/lib_common/of_cb.h new file mode 100644 index 0000000..1160cc5 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/of_cb.h @@ -0,0 +1,54 @@ +/* $Id: of_cb.h 72 2012-04-13 13:27:26Z detchart $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef OF_CB +#define OF_CB + +/** + * @struct of_cb_t + * @brief Generic (empty) control block for a codec. + * + * This is the structure where all the pieces + * of information related to a codec instanciation are stored. + * All the instanciated control block structures MUST begin with the entries listed below. + */ +typedef struct of_cb +{ + of_codec_id_t codec_id; + of_codec_type_t codec_type; + UINT32 nb_source_symbols; + UINT32 nb_repair_symbols; + UINT32 encoding_symbol_length; +} of_cb_t; + +#endif //OF_CB diff --git a/thirdparty/openfec/src/lib_common/of_debug.h b/thirdparty/openfec/src/lib_common/of_debug.h new file mode 100644 index 0000000..716e2e4 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/of_debug.h @@ -0,0 +1,104 @@ +/* $Id: of_debug.h 72 2012-04-13 13:27:26Z detchart $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef OF_DEBUG_H +#define OF_DEBUG_H /* { */ + +/****** general macros ******/ + + +#define OF_ENTER_FUNCTION OF_TRACE_LVL(2, ("-> %s:\n",__FUNCTION__)) +#define OF_EXIT_FUNCTION OF_TRACE_LVL(2, ("<- %s:\n",__FUNCTION__)) + +/* + * Message print macros exist into two categories: + * - OF_PRINT_*: print either to stdout or stderr, possibly controlled by a verbosity + * level in case of OF_PRINT_LVL. The printf code is always compiled. + * - OF_TRACE_LVL: print debug messages, possibly controlled by a verbosity level. + * The printf code is only compiled in OF_DEBUG mode, there's no code otherwise. + */ + +/** + * Print to stdout. + */ +#define OF_PRINT(a) { printf a; fflush(stdout); } + +/** + * Print to stdout with a verbosity level. + */ +#define OF_PRINT_LVL(l, a) if (of_verbosity >= (l)) { \ + printf a; \ + fflush(stdout); \ + } + +/** + * Print to stderr. + */ +#define OF_PRINT_ERROR(a) { fprintf(stderr, "ERROR in \"%s\":%d:%s(): ", \ + __FILE__, __LINE__, __FUNCTION__); \ + printf a; fflush(stderr); fflush(stdout); } +#define OF_PRINT_FAILURE(a) { fprintf(stderr, "Failure in \"%s\":%d:%s(): ", \ + __FILE__, __LINE__, __FUNCTION__); \ + printf a; fflush(stderr); fflush(stdout); } + +/** + * Trace with a level in OF_DEBUG mode only + */ +#ifdef OF_DEBUG +#define OF_TRACE_LVL(l, a) if (of_verbosity >= (l)) { \ + printf a; \ + fflush(stdout); \ + } +#else +#define OF_TRACE_LVL(l, a) +#endif + + +/** + * assertion in OF_DEBUG mode + */ +#ifdef ASSERT +#undef ASSERT +#endif +#ifdef OF_DEBUG +#define ASSERT(c) if (!(c)) { \ + fprintf(stderr, "ASSERT [%s:%d] failed\n", \ + __FILE__, __LINE__); \ + fflush(stderr); \ + exit(-1); \ + } +#else /* OF_DEBUG */ +#define ASSERT(c) +#endif /* OF_DEBUG */ + +#endif /* } OF_DEBUG_H */ diff --git a/thirdparty/openfec/src/lib_common/of_mem.c b/thirdparty/openfec/src/lib_common/of_mem.c new file mode 100644 index 0000000..c736e9a --- /dev/null +++ b/thirdparty/openfec/src/lib_common/of_mem.c @@ -0,0 +1,84 @@ +/* $Id: of_mem.c 182 2014-07-15 09:27:51Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2011 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include +#include +#include "of_openfec_api.h" + +void* of_malloc (size_t size) +{ + return malloc (size); +} + + +void* of_calloc (size_t nmemb, + size_t size) +{ + return calloc (nmemb, size); +} + + +void* of_realloc (void* ptr, + size_t size) +{ + return realloc (ptr, size); + +} + + +void of_free (void* ptr) +{ + if (ptr) { + free (ptr); + } +} + + +#if 0 +void of_dump_buffer (char* buf, UINT32 size) +{ + UINT32 i; + UINT32 *s32; + + if (size % 4 != 0) + { + size = (size % 4) * 4; + } + for (i = 0, s32 = (UINT32*)buf; i < size; i += 4, s32++) + { + printf ("%08x ", *s32); + } + printf ("\n"); +} +#endif + diff --git a/thirdparty/openfec/src/lib_common/of_mem.h b/thirdparty/openfec/src/lib_common/of_mem.h new file mode 100644 index 0000000..3852561 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/of_mem.h @@ -0,0 +1,78 @@ +/* $Id: of_mem.h 186 2014-07-16 07:17:53Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/* + * This module implements memory management operations. + * In debug mode, it also performs memory usage statistics. + */ + +#ifndef OF_MEM_H +#define OF_MEM_H + + +/** + * @fn inline void* of_malloc (size_t size) + * @brief do a malloc + * @param size (IN) size of wanted allocated area. + * @return allocated pointer or NULL if error. + */ +void* of_malloc (size_t size); + +/** + * @fn inline void* of_calloc (size_t nmemb,size_t size) + * @brief do a calloc + * @param nmemb (IN) number of elements + * @param size (IN) size of wanted allocated area. + * @return allocated pointer or NULL if error. + */ +void* of_calloc (size_t nmemb, size_t size); + +/** + * @fn inline void* of_realloc (void* ptr, size_t size) + * @brief realloc memory adress + * @param ptr (IN) pointer to realloc + * @param size (IN) size of wanted allocated area. + * @return allocated pointer or NULL if error. + */ +void* of_realloc (void* ptr, size_t size); + +/** + * @fn inline void of_free (void* ptr) + * @brief free amemory adress + * @param ptr (IN) pointer to free + * @return void + */ +void of_free (void* ptr); + + +#endif //OF_MEM_H diff --git a/thirdparty/openfec/src/lib_common/of_openfec_api.c b/thirdparty/openfec/src/lib_common/of_openfec_api.c new file mode 100644 index 0000000..5bdd72f --- /dev/null +++ b/thirdparty/openfec/src/lib_common/of_openfec_api.c @@ -0,0 +1,800 @@ +/* $Id: of_openfec_api.c 214 2014-12-12 23:14:02Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +#include "of_openfec_api.h" + +#ifdef OF_USE_REED_SOLOMON_CODEC +#include "../lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8_includes.h" +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC +#include "../lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m_includes.h" +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC +#include "../lib_stable/ldpc_staircase/of_ldpc_includes.h" +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC +#include "../lib_stable/2d_parity_matrix/of_2d_parity_includes.h" +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC +#include "../lib_advanced/ldpc_from_file/of_ldpc_ff_includes.h" +#endif + +UINT32 of_verbosity; + +of_status_t of_create_codec_instance(of_session_t** ses, of_codec_id_t codec_id, + of_codec_type_t codec_type, + UINT32 verbosity) { + of_status_t status; + + OF_ENTER_FUNCTION + of_verbosity = verbosity; + /** + * each codec must realloc control block. + */ + (*ses) = of_calloc(1, sizeof(of_cb_t)); + if (*ses == NULL) { + OF_PRINT_ERROR(("Error, of_calloc failed\n")) + goto error2; + } + ((of_cb_t*)(*ses))->codec_type = codec_type; + ((of_cb_t*)(*ses))->codec_id = codec_id; + + switch (codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + status = of_rs_create_codec_instance((of_rs_cb_t**)ses); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_create_codec_instance((of_rs_2_m_cb_t**)ses); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = of_ldpc_staircase_create_codec_instance( + (of_ldpc_staircase_cb_t**)ses); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_create_codec_instance((of_2d_parity_cb_t**)ses); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = of_ldpc_ff_create_codec_instance((of_ldpc_ff_cb_t**)ses); + break; +#endif + default: + OF_PRINT_ERROR(("Error, codec %d non available\n", codec_id)) + goto error; + } + OF_EXIT_FUNCTION + return status; + +error: + of_free(*ses); + *ses = NULL; +error2: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +of_status_t of_release_codec_instance(of_session_t* ses) { + of_status_t status; + + OF_ENTER_FUNCTION + if (ses != NULL) { + switch (((of_cb_t*)ses)->codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + status = of_rs_release_codec_instance((of_rs_cb_t*)ses); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_release_codec_instance((of_rs_2_m_cb_t*)ses); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = of_ldpc_staircase_release_codec_instance( + (of_ldpc_staircase_cb_t*)ses); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_release_codec_instance((of_2d_parity_cb_t*)ses); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = of_ldpc_staircase_release_codec_instance( + (of_ldpc_staircase_cb_t*)ses); + break; +#endif + default: + OF_PRINT_ERROR( + ("Error, codec %d non available\n", ((of_cb_t*)ses)->codec_id)) + goto error; + } + of_free(ses); + ses = NULL; + } + OF_EXIT_FUNCTION + return status; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +of_status_t of_set_fec_parameters(of_session_t* ses, of_parameters_t* params) { + of_status_t status; + + OF_ENTER_FUNCTION + if ((ses == NULL) || (params == NULL)) { + OF_PRINT_ERROR(("Error, bad ses or params pointer (null)\n")) + goto error; + } +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + if (((of_cb_t*)ses)->codec_id != OF_CODEC_LDPC_FROM_FILE_ADVANCED && + ((params->nb_source_symbols <= 0) || + (params->nb_repair_symbols <= 0)) || + (params->encoding_symbol_length <= 0)) { + OF_PRINT_ERROR(("Error, bad parameters:")) + if (params->nb_source_symbols <= 0) { + OF_PRINT_ERROR(("nb_source_symbols %d <= 0\n", params->nb_source_symbols)) + } + if (params->nb_repair_symbols <= 0) { + OF_PRINT_ERROR(("nb_repair_symbols %d <= 0\n", params->nb_repair_symbols)) + } + if (params->encoding_symbol_length <= 0) { + OF_PRINT_ERROR( + ("encoding_symbol_length %d <= 0\n", params->encoding_symbol_length)) + } + goto error; + } +#endif + switch (((of_cb_t*)ses)->codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + status = of_rs_set_fec_parameters((of_rs_cb_t*)ses, + (of_rs_parameters_t*)params); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_set_fec_parameters((of_rs_2_m_cb_t*)ses, + (of_rs_2_m_parameters_t*)params); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = of_ldpc_staircase_set_fec_parameters( + (of_ldpc_staircase_cb_t*)ses, (of_ldpc_parameters_t*)params); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_set_fec_parameters( + (of_2d_parity_cb_t*)ses, (of_2d_parity_parameters_t*)params); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = of_ldpc_ff_set_fec_parameters((of_ldpc_ff_cb_t*)ses, + (of_ldpc_ff_parameters_t*)params); + break; +#endif + default: + OF_PRINT_ERROR( + ("Error, codec %d non available\n", ((of_cb_t*)ses)->codec_id)) + goto error; + } + OF_EXIT_FUNCTION + return status; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +of_status_t of_set_callback_functions( + of_session_t* ses, + void* (*decoded_source_symbol_callback)(void* context, UINT32 size, + UINT32 esi), + void* (*decoded_repair_symbol_callback)(void* context, UINT32 size, + UINT32 esi), + void* context_4_callback) { + of_status_t status; + + OF_ENTER_FUNCTION + if (ses == NULL) { + OF_PRINT_ERROR(("Error, bad ses pointer (null)\n")) + goto error; + } + if ((decoded_source_symbol_callback == NULL) && + (decoded_repair_symbol_callback == NULL)) { + OF_PRINT_ERROR( + ("decoded_source_symbol_callback and decoded_repair_symbol_callback or " + "both NULL\n")) + goto error; + } + switch (((of_cb_t*)ses)->codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + status = of_rs_set_callback_functions( + (of_rs_cb_t*)ses, decoded_source_symbol_callback, + decoded_repair_symbol_callback, context_4_callback); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_set_callback_functions( + (of_rs_2_m_cb_t*)ses, decoded_source_symbol_callback, + decoded_repair_symbol_callback, context_4_callback); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = of_ldpc_staircase_set_callback_functions( + (of_ldpc_staircase_cb_t*)ses, decoded_source_symbol_callback, + decoded_repair_symbol_callback, context_4_callback); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_set_callback_functions( + (of_2d_parity_cb_t*)ses, decoded_source_symbol_callback, + decoded_repair_symbol_callback, context_4_callback); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = of_ldpc_staircase_set_callback_functions( + (of_ldpc_staircase_cb_t*)ses, decoded_source_symbol_callback, + decoded_repair_symbol_callback, context_4_callback); + break; +#endif + default: + OF_PRINT_ERROR( + ("Error, codec %d non available\n", ((of_cb_t*)ses)->codec_id)) + goto error; + } + OF_EXIT_FUNCTION + return status; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +of_status_t of_more_about(of_session_t* ses, char** version_str, + char** copyrights_str) { + OF_ENTER_FUNCTION + static char of_version_string[] = + "OpenFEC.org - Version 1.4.2, December 16th, 2014\n"; + static char of_copyrights_string[] = + "\n\ + OpenFEC.org - Because free, open source AL-FEC codes and codecs matter\n\ + Copyright (c) 2003-2014 INRIA - All rights reserved\n\ + \n\ + LDPC codecs:\n\ + Copyright (c) 2003-2014 INRIA - All rights reserved\n\ + This library contains code from R. Neal:\n\ + Copyright (c) 1995-2003 by Radford M. Neal\n\ + \n\ + Reed-Solomon codecs:\n\ + This library contains code from L. Rizzo:\n\ + Copyright (c) 1997-98 Luigi Rizzo (luigi@iet.unipi.it)\n\ + Portions derived from code by Phil Karn (karn@ka9q.ampr.org), \n\ + Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari \n\ + Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995 \n\ + \n\ + See the associated LICENCE.TXT file for licence information\n"; + + if (version_str) { + *version_str = of_version_string; + } + if (copyrights_str) { + *copyrights_str = of_copyrights_string; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + +#ifdef OF_USE_ENCODER + +of_status_t of_build_repair_symbol(of_session_t* ses, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build) { + of_status_t status; + + OF_ENTER_FUNCTION + if (ses == NULL) { + OF_PRINT_ERROR(("Error, bad ses pointer (null)\n")) + goto error; + } + if (!(((of_cb_t*)ses)->codec_type & OF_ENCODER)) { + OF_PRINT_ERROR(("Error, bad codec_type\n")) + goto error; + } + switch (((of_cb_t*)ses)->codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + status = of_rs_build_repair_symbol((of_rs_cb_t*)ses, encoding_symbols_tab, + esi_of_symbol_to_build); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_build_repair_symbol( + (of_rs_2_m_cb_t*)ses, encoding_symbols_tab, esi_of_symbol_to_build); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = of_ldpc_staircase_build_repair_symbol( + (of_ldpc_staircase_cb_t*)ses, encoding_symbols_tab, + esi_of_symbol_to_build); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_build_repair_symbol((of_2d_parity_cb_t*)ses, + encoding_symbols_tab, + esi_of_symbol_to_build); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = of_ldpc_ff_build_repair_symbol( + (of_ldpc_ff_cb_t*)ses, encoding_symbols_tab, esi_of_symbol_to_build); + break; +#endif + default: + OF_PRINT_ERROR( + ("Error, codec %d non available\n", ((of_cb_t*)ses)->codec_id)) + goto error; + } + OF_EXIT_FUNCTION + return status; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +#endif // OF_USE_ENCODER + +#ifdef OF_USE_DECODER + +of_status_t of_decode_with_new_symbol(of_session_t* ses, + void* const new_symbol_buf, + UINT32 new_symbol_esi) { + of_status_t status; + + OF_ENTER_FUNCTION + if (ses == NULL) { + OF_PRINT_ERROR(("Error, bad ses pointer (null)\n")) + goto error; + } + if (new_symbol_esi >= (((of_cb_t*)ses)->nb_source_symbols + + ((of_cb_t*)ses)->nb_repair_symbols)) { + OF_PRINT_ERROR(("Error, bad parameters new_symbol_esi(%d) out of range\n", + new_symbol_esi)) + goto error; + } + if (new_symbol_buf == NULL || + new_symbol_esi >= (((of_cb_t*)ses)->nb_source_symbols + + ((of_cb_t*)ses)->nb_repair_symbols) || + !(((of_cb_t*)ses)->codec_type & OF_DECODER)) { + OF_PRINT_ERROR(("Error, bad parameters\n")) + goto error; + } + switch (((of_cb_t*)ses)->codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + status = of_rs_decode_with_new_symbol((of_rs_cb_t*)ses, new_symbol_buf, + new_symbol_esi); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_decode_with_new_symbol((of_rs_2_m_cb_t*)ses, + new_symbol_buf, new_symbol_esi); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = of_ldpc_staircase_decode_with_new_symbol( + (of_ldpc_staircase_cb_t*)ses, new_symbol_buf, new_symbol_esi); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_decode_with_new_symbol( + (of_2d_parity_cb_t*)ses, new_symbol_buf, new_symbol_esi); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = of_ldpc_staircase_decode_with_new_symbol( + (of_ldpc_staircase_cb_t*)ses, new_symbol_buf, new_symbol_esi); + break; +#endif + default: + OF_PRINT_ERROR( + ("Error, codec %d non available\n", ((of_cb_t*)ses)->codec_id)) + goto error; + } + OF_EXIT_FUNCTION + return status; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +of_status_t of_set_available_symbols(of_session_t* ses, + void* const encoding_symbols_tab[]) { + of_status_t status; + + OF_ENTER_FUNCTION + if (ses == NULL) { + OF_PRINT_ERROR(("Error, bad ses pointer (null)\n")) + goto error; + } + if (encoding_symbols_tab == NULL) { + OF_PRINT_ERROR(("Error, bad encoding_symbols_tab (null)\n")) + goto error; + } + if (!((of_cb_t*)ses)->codec_type & OF_DECODER) { + OF_PRINT_ERROR(("Error, bad codec_type\n")) + goto error; + } + switch (((of_cb_t*)ses)->codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + status = + of_rs_set_available_symbols((of_rs_cb_t*)ses, encoding_symbols_tab); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_set_available_symbols((of_rs_2_m_cb_t*)ses, + encoding_symbols_tab); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = of_ldpc_staircase_set_available_symbols( + (of_ldpc_staircase_cb_t*)ses, encoding_symbols_tab); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = of_ldpc_staircase_set_available_symbols( + (of_ldpc_staircase_cb_t*)ses, encoding_symbols_tab); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_set_available_symbols((of_2d_parity_cb_t*)ses, + encoding_symbols_tab); + break; +#endif + default: + OF_PRINT_ERROR( + ("Error, codec %d non available\n", ((of_cb_t*)ses)->codec_id)) + goto error; + } + OF_EXIT_FUNCTION + return status; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +of_status_t of_finish_decoding(of_session_t* ses) { + of_status_t status; + + OF_ENTER_FUNCTION + if (ses == NULL) { + OF_PRINT_ERROR(("Error, bad ses pointer (null)\n")) + goto error; + } + if (!((of_cb_t*)ses)->codec_type & OF_DECODER) { + OF_PRINT_ERROR(("Error, bad codec_type\n")) + goto error; + } + switch (((of_cb_t*)ses)->codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + status = of_rs_finish_decoding((of_rs_cb_t*)ses); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_finish_decoding((of_rs_2_m_cb_t*)ses); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = of_ldpc_staircase_finish_decoding((of_ldpc_staircase_cb_t*)ses); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_finish_decoding((of_2d_parity_cb_t*)ses); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = of_ldpc_staircase_finish_decoding((of_ldpc_staircase_cb_t*)ses); + break; +#endif + default: + OF_PRINT_ERROR( + ("Error, codec %d non available\n", ((of_cb_t*)ses)->codec_id)) + goto error; + } + OF_EXIT_FUNCTION + return status; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +bool of_is_decoding_complete(of_session_t* ses) { + of_status_t status; + + OF_ENTER_FUNCTION + if (ses == NULL) { + OF_PRINT_ERROR(("Error, bad ses pointer (null)\n")) + goto error; + } + if (!((of_cb_t*)ses)->codec_type & OF_DECODER) { + OF_PRINT_ERROR(("Error, bad codec_type\n")) + goto error; + } + switch (((of_cb_t*)ses)->codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + status = of_rs_is_decoding_complete((of_rs_cb_t*)ses); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_is_decoding_complete((of_rs_2_m_cb_t*)ses); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = + of_ldpc_staircase_is_decoding_complete((of_ldpc_staircase_cb_t*)ses); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = + of_ldpc_staircase_is_decoding_complete((of_ldpc_staircase_cb_t*)ses); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_is_decoding_complete((of_2d_parity_cb_t*)ses); + break; +#endif + default: + OF_PRINT_ERROR( + ("Error, codec %d non available\n", ((of_cb_t*)ses)->codec_id)) + goto error; + } + OF_EXIT_FUNCTION + return status; + +error: + OF_EXIT_FUNCTION + /* should be a fatal error since we arrive here because something wrong + happen, but this is not permitted */ + return false; +} + +of_status_t of_get_source_symbols_tab(of_session_t* ses, + void* source_symbols_tab[]) { + of_status_t status; + + OF_ENTER_FUNCTION + if (ses == NULL) { + OF_PRINT_ERROR(("Error, bad ses pointer (null)\n")) + goto error; + } + if (!((of_cb_t*)ses)->codec_type & OF_DECODER) { + OF_PRINT_ERROR(("Error, bad codec_type\n")) + goto error; + } + switch (((of_cb_t*)ses)->codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + status = + of_rs_get_source_symbols_tab((of_rs_cb_t*)ses, source_symbols_tab); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_get_source_symbols_tab((of_rs_2_m_cb_t*)ses, + source_symbols_tab); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = of_ldpc_staircase_get_source_symbols_tab( + (of_ldpc_staircase_cb_t*)ses, source_symbols_tab); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_get_source_symbols_tab((of_2d_parity_cb_t*)ses, + source_symbols_tab); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = of_ldpc_staircase_get_source_symbols_tab( + (of_ldpc_staircase_cb_t*)ses, source_symbols_tab); + break; +#endif + default: + OF_PRINT_ERROR( + ("Error, codec %d non available\n", ((of_cb_t*)ses)->codec_id)) + goto error; + } + OF_EXIT_FUNCTION + return status; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +of_status_t of_set_control_parameter(of_session_t* ses, UINT32 type, + void* value, UINT32 length) { + of_status_t status; + + OF_ENTER_FUNCTION + if (ses == NULL) { + OF_PRINT_ERROR(("Error, bad ses pointer (null)\n")) + goto error; + } + switch (((of_cb_t*)ses)->codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + // status = of_rs_set_control_parameter ( (of_rs_cb_t*) ses, type, value, + // length); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_set_control_parameter((of_rs_2_m_cb_t*)ses, type, + value, length); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = of_ldpc_staircase_set_control_parameter( + (of_ldpc_staircase_cb_t*)ses, type, value, length); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_set_control_parameter((of_2d_parity_cb_t*)ses, type, + value, length); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = of_ldpc_ff_set_control_parameter((of_ldpc_ff_cb_t*)ses, type, + value, length); + break; +#endif + default: + OF_PRINT_ERROR( + ("Error, codec %d non available\n", ((of_cb_t*)ses)->codec_id)) + goto error; + } + OF_EXIT_FUNCTION + return status; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +of_status_t of_get_control_parameter(of_session_t* ses, UINT32 type, + void* value, UINT32 length) { + of_status_t status; + + OF_ENTER_FUNCTION + if (ses == NULL) { + OF_PRINT_ERROR(("Error, bad ses pointer (null)\n")) + goto error; + } + switch (((of_cb_t*)ses)->codec_id) { +#ifdef OF_USE_REED_SOLOMON_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_8_STABLE: + status = + of_rs_get_control_parameter((of_rs_cb_t*)ses, type, value, length); + break; +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + case OF_CODEC_REED_SOLOMON_GF_2_M_STABLE: + status = of_rs_2_m_get_control_parameter((of_rs_2_m_cb_t*)ses, type, + value, length); + break; +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + case OF_CODEC_LDPC_STAIRCASE_STABLE: + status = of_ldpc_staircase_get_control_parameter( + (of_ldpc_staircase_cb_t*)ses, type, value, length); + break; +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC + case OF_CODEC_LDPC_FROM_FILE_ADVANCED: + status = of_ldpc_ff_get_control_parameter((of_ldpc_ff_cb_t*)ses, type, + value, length); + break; +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + case OF_CODEC_2D_PARITY_MATRIX_STABLE: + status = of_2d_parity_get_control_parameter((of_2d_parity_cb_t*)ses, type, + value, length); + break; +#endif + default: + OF_PRINT_ERROR( + ("Error, codec %d non available\n", ((of_cb_t*)ses)->codec_id)) + goto error; + } + OF_EXIT_FUNCTION + return status; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + +#endif // OF_USE_DECODER diff --git a/thirdparty/openfec/src/lib_common/of_openfec_api.h b/thirdparty/openfec/src/lib_common/of_openfec_api.h new file mode 100644 index 0000000..a3661e9 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/of_openfec_api.h @@ -0,0 +1,588 @@ +/* $Id: of_openfec_api.h 189 2014-07-16 08:53:50Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef OPENFEC_API_H +#define OPENFEC_API_H + +#include "of_openfec_profile.h" +#include "of_types.h" + +#ifdef OF_USE_REED_SOLOMON_CODEC +#include "../lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8_api.h" +#endif +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC +#include "../lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m_api.h" +#endif +#ifdef OF_USE_LDPC_STAIRCASE_CODEC +#include "../lib_stable/ldpc_staircase/of_ldpc_staircase_api.h" +#endif +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC +#include "../lib_stable/2d_parity_matrix/of_2d_parity_api.h" +#endif +#ifdef OF_USE_LDPC_FROM_FILE_CODEC +#include "../lib_advanced/ldpc_from_file/of_ldpc_ff_api.h" +#endif +#include "of_debug.h" + +/****** OpenFEC.org general definitions + * ***********************************************************/ + +/** + * The of_fec_codec_id_t enum identifies the FEC code/codec being used. + * A given of_fec_codec_id_t can then be used by one or several FEC schemes + *(that specify both the codes and way of using these codes), as specified in: + * - RFC 5052, "Forward Error Correction (FEC) Building Block" for + *file/object transfer applications, or + * - (work under progress) "Forward Error + *Correction (FEC) Framework" for real-time streaming applications. + * + * The following FEC codec IDs are currently identified (but not necessarily + *supported): + * + * OF_CODEC_NIL = 0 reserved invalid value + * + *** Stable codecs *** + * + * + * OF_CODEC_REED_SOLOMON_GF_2_8_STABLE + * Reed-Solomon codes over GF(2^8), stable + *version. + * - E.g. FEC Encoding ID 5 (RMT IETF WG) + * (see RFC 5510, "Reed-Solomon Forward + *Error Correction (FEC) schemes") + * - E.g. FEC Encoding ID 129 / FEC + *Instance ID 0 (see RFC 5510, "Reed-Solomon Forward Error Correction (FEC) + *Schemes") + * + * OF_CODEC_REED_SOLOMON_GF_2_M_STABLE + * Reed-Solomon codes over GF(2^m), stable + *version. + * + * + * OF_CODEC_LDPC_STAIRCASE_STABLE LDPC-Staircase large block FEC codes, + *stable version. + * - E.g. FEC Encoding ID 3 + * (see RFC 5170, "Low Density Parity + *Check (LDPC) Staircase and Triangle Forward Error Correction (FEC) Schemes") + * + * OF_CODEC_LDPC_TRIANGLE_STABLE LDPC-Staircase large block FEC codes, + *stable version. + * - E.g. FEC Encoding ID 4 + * (see RFC 5170, "Low Density Parity + *Check (LDPC) Staircase and Triangle Forward Error Correction (FEC) Schemes") + * + * OF_CODEC_2D_PARITY_MATRIX_STABLE 2D-parity-matrix codes, stable version. + * + * + *** Advanced codecs *** + * + * OF_CODEC_LDPC_FROM_FILE_ADVANCED LDPC codes whose binary parity check + *matrix is provided by the application within an ASCII file. The format of this + *ASCII file is the usual LDPC structure [REF]. + */ +typedef enum { + OF_CODEC_NIL = 0, + OF_CODEC_REED_SOLOMON_GF_2_8_STABLE = 1, + OF_CODEC_REED_SOLOMON_GF_2_M_STABLE = 2, + OF_CODEC_LDPC_STAIRCASE_STABLE = 3, + // OF_CODEC_LDPC_TRIANGLE_STABLE = 4, + OF_CODEC_2D_PARITY_MATRIX_STABLE = 5, + OF_CODEC_LDPC_FROM_FILE_ADVANCED = 6 +} of_codec_id_t; + +/** + * Specifies if this codec instance is a pure encoder, a pure decoder, or a + * codec capable of both encoding and decoding. + */ +typedef UINT8 of_codec_type_t; + +#define OF_ENCODER 0x1 +#define OF_DECODER 0x2 +#define OF_ENCODER_AND_DECODER (OF_ENCODER | OF_DECODER) + +/** + * Function return value, indicating wether the function call succeeded + *(OF_STATUS_OK) or not. In case of failure, the detailed error type is returned + *in a global variable, of_errno (see of_errno.h). + * + * OF_STATUS_OK = 0 Success + * OF_STATUS_FAILURE, Failure. The function called did not + *succeed to perform its task, however this is not an error. This can happen for + *instance when decoding did not succeed (which is a valid output). + * OF_STATUS_ERROR, Generic error type. The caller is + *expected to be able to call the library in the future after having corrected + * the error cause. + * OF_STATUS_FATAL_ERROR Fatal error. The caller is expected to + *stop using this codec instance immediately (it replaces an exit() system + * call). + */ +typedef enum { + OF_STATUS_OK = 0, + OF_STATUS_FAILURE, + OF_STATUS_ERROR, + OF_STATUS_FATAL_ERROR +} of_status_t; + +/** + * Throughout the API, a pointer to this structure is used as an identifier of + * the current codec instance, also known as "session". + * + * This generic structure is meant to be extended by each codec and new pieces + * of information that are specific to each codec be specified there. However, + * all the codec specific structures MUST begin the same entries as the ones + * provided in this generic structure, otherwise hazardeous behaviors may + * happen. + */ +typedef struct of_session { + of_codec_id_t codec_id; + of_codec_type_t codec_type; +} of_session_t; + +/** + * Generic FEC parameter structure used by of_set_fec_parameters(). + * + * This generic structure is meant to be extended by each codec and new pieces + * of information that are specific to each codec be specified there. However, + * all the codec specific structures MUST begin the same entries as the ones + * provided in this generic structure, otherwise hazardeous behaviors may + * happen. + */ +typedef struct of_parameters { + UINT32 nb_source_symbols; + UINT32 nb_repair_symbols; + UINT32 encoding_symbol_length; +} of_parameters_t; + +/** Verbosity level for the whole library. */ +extern UINT32 of_verbosity; + +/****** OpenFEC.org general methods/functions + * *****************************************************/ + +/* + * Usual functions shared by encoders and decoders + * *********************************************** + */ + +/** + * This function allocates and partially initializes a new session structure. + * Throughout the API, a pointer to this session is used as an identifier of the + *current codec instance. + * + * @fn of_status_t of_create_codec_instance (of_session_t** ses, + *of_codec_id_t codec_id, of_codec_type_t codec_type, UINT32 verbosity) + * @brief create a codec instance + *02@param ses (IN/OUT) address of the pointer to a session. This + *pointer is updated by this function. In case of success, it points to a + *session structure allocated by the library. In case of failure it points to + *NULL. + * @param codec_id identifies the FEC code/codec being used. + * @param codec_type indicates if this is a coder, a decoder, or both. + * @param verbosity set the verbosity level: 0: no trace, 1: main traces, 2: + *maximum. + * @return Error status. The ses pointer is updated according to + *the success return status. + */ +of_status_t of_create_codec_instance(of_session_t** ses, of_codec_id_t codec_id, + of_codec_type_t codec_type, + UINT32 verbosity); + +/** + * This function releases all the internal resources used by this FEC codec + *instance. None of the source symbol buffers will be free'ed by this function, + *even those decoded by the library if any, regardless of whether a callback has + *been registered or not. It's the responsibility of the caller to free them. + * + * @fn of_status_t of_release_codec_instance (of_session_t* ses) + * @brief release all resources used by the codec + *02@param ses (IN) Pointer to the session. + * @return Error status. + */ +of_status_t of_release_codec_instance(of_session_t* ses); + +/** + * Second step of the initialization. + * This is the place where the application specifies the parameters associated + *to the desired FEC codec. + * + * At a receiver, the parameters can be extracted from the FEC OTI that is + *usually communicated to the receiver by either an in-band mechanism (e.g. the + *EXT_FTI header extension of ALC/LCT, or the FLUTE File Delivery Table, or the + *FCAST meta-data), or an out-of-band mechanism (e.g. in an SDP session + *description), or set statically for a specific use-case. + * + * Note also that a subset of the FEC OTI information is not strictly needed by + *the codec but only required for instance when using the associated object + *blocking functions. This is the case of the object length (Transfer Length). + * + * @fn of_status_t of_set_fec_parameters (of_session_t* ses, + *of_parameters_t* params) + * @brief set all the FEC codec parameters (e.g. k, n, or symbol + *size) 02@param ses (IN) Pointer to the session. + * @param params (IN) pointer to a structure containing the FEC + *parameters associated to a specific FEC codec. + * @return Error status. + */ +of_status_t of_set_fec_parameters(of_session_t* ses, of_parameters_t* params); + +/** + * Set the various callback functions for this session. + * + * - The decoded_source_symbol callback function is called each time a source + *symbol (not a repair symbol!) is decoded by one of the decoding functions. + *What this function does is application-dependant, but it MUST return either a + *pointer to a data buffer, left uninitialized, of the appropriate size, or NULL + *if the application prefers to let the OpenFEC library allocate the buffer. In + *any case the OpenFEC library is responsible for storing the actual symbol + *value within the data buffer. In all cases (i.e. whether the data buffer is + *allocated by the application or codec), it is the responsibility of the + * application to free this buffer when needed, once decoding is over (but not + *before since the codec does not keep any internal copy). + * + * - The decoded_repair_symbol callback is similar but limited to decoded repair + *symbols. It is not expected that this callback be frequently used (decoded + *repair symbols are usually temporary, internal symbols). It might be used for + *statistics purposes, e.g. to identify which repair symbol is decoded and when. + *Unlike the decoded_source_symbol callback, this one is not expected to return + *any data buffer. + * + * All the callback functions require an opaque context parameter, that must be + * initialized accordingly by the application, since it is application specific. + * + * @fn of_status_t of_set_callback_functions (of_session_t *ses,void* + *(*decoded_source_symbol_callback) (void *context,UINT32 size,UINT32 + *esi), void* (*decoded_repair_symbol_callback) (void *context,UINT32 + *size,UINT32 esi),void* context_4_callback) + * @brief set various callbock functions (see header + *of_open_fec_api.h) 02@param ses (IN) Pointer to the session. + * + * @param decoded_source_symbol_callback + * (IN) Pointer to the function, within the + *application, that needs to be called each time a source symbol is decoded. If + *this callback is not initialized, the symbol is managed internally. + * + * @param decoded_repair_symbol_callback + * (IN) Pointer to the function, within the + *application, that needs to be called each time a repair symbol is decoded. If + *this callback is not initialized, the symbol is managed internally. + * + * @param context_4_callback (IN) Pointer to the application-specific context + *that will be passed to the callback function (if any). This context is not + * interpreted by this function. + * + * @return Completion status (LDPC_OK or LDPC_ERROR). + */ +of_status_t of_set_callback_functions( + of_session_t* ses, + void* (*decoded_source_symbol_callback)( + void* context, UINT32 size, /* size of decoded source symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback)( + void* context, UINT32 size, /* size of decoded repair symbol */ + UINT32 esi), /* encoding symbol ID in {k..n-1} */ + void* context_4_callback); + +#ifdef OF_USE_ENCODER +/* + * Encoder specific functions + * ************************** + */ + +/** + * Create a single repair symbol, i.e. perform an encoding. + * The application needs to communicate all the source symbols by means of the + * encoding_symbols_tab[] table, which contains pointers to buffers totally + *managed by the application, and that contain the source symbols. This table + *may also contain a subset of the repair symbols, those that have already been + *built. For instance, with OF_CODEC_LDPC_STAIRCASE_STABLE the repair symbol of + *ESI i+1 depends on the repair symbol of ESI i. In any case, upon calling this + *function, the entry: encoding_symbols_tab[esi_of_symbol_to_build] can either + *be set to NULL, in which case the library allocates a buffer and copies the + * newly built symbol to it, or point to a buffer allocated by the application, + *in which case the library only copies the newly built symbol to it. + * + * @fn of_status_t of_build_repair_symbol (of_session_t* ses, void* + *encoding_symbols_tab[], UINT32 esi_of_symbol_to_build) + * @brief build a repair symbol (encoder only) + *02@param ses (IN) Pointer to the session. + * @param encoding_symbols_tab (IN/OUT) table of source and repair symbols. + * The entry for the repair symbol to build can + *either point to a buffer allocated by the application, or let to NULL meaning + *that of_build_repair_symbol will allocate memory. + * @param esi_of_symbol_to_build + * (IN) encoding symbol ID of the repair symbol to + *build in {k..n-1} + * @return Error status. + */ +of_status_t of_build_repair_symbol(of_session_t* ses, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build); + +#endif /* OF_USE_ENCODER */ + +#ifdef OF_USE_DECODER +/* + * Decoder specific functions + * ************************** + */ + +/** + * Try to decode using the newly received symbol. + * Although no decoding algorithm is specified here, in case of LDPC-* codecs, + *this function usually performs on an ITerative decoding (IT) algorithm, on the + *fly as each new symbol is available. In case of Reed-Solomon, as long as the + *number of available symbols is inferior to k, this function only registers the + *new symbol in an internal table. Then as soon as exactly k symbols are + *available, decoding takes place. + * + * Be careful, no codec keep any internal copy of the symbols provided by the + *application. Therefore it is assumed that the buffer provided by this + *function, whether it contains a fresh source or repair symbol, will be + *available throughout the decoding process. This is motivated by performance + *reasons since it means the codec does not need to keep any internal copy of + *received symbols. + * + * @fn of_status_t of_decode_with_new_symbol (of_session_t* ses, + *void* const new_symbol_buf, UINT32 new_symbol_esi) + * @brief (try to) decode with a newly received symbol + *02@param ses (IN) Pointer to the session. + * @param new_symbol_buf (IN) Pointer to the encoding symbol now + *available (i.e. a new symbol received by the application, or a decoded symbol + *in case of a recursive call). + * @param new_symbol_esi (IN) Encoding symbol ID of the newly symbol + *available, in {0..n-1}. + * @return Error status (NB: this function does not return + *OF_STATUS_FAILURE). + */ +of_status_t of_decode_with_new_symbol(of_session_t* ses, + void* const new_symbol_buf, + UINT32 new_symbol_esi); + +/** + * Inform the decoder of all the available (e.g. received from the network) + *encoding symbols. This function should not be used when the application uses + *of_decode_with_new_symbol() since the available symbols are already known. No + *decoding is performed at this step, a call to of_finish_decoding() is needed. + *The goal is only to give the application the opportunity to register the set + *of symbols available for the future decoding. This function must be called + *only once for a given session. + * + * Be careful, no codec keep any internal copy of the symbols provided by the + *application Therefore it is assumed that the buffers provided by this + *function, whether they contain fresh source or repair symbols, will be + *available throughout the decoding process. This is motivated by performance + *reasons since it means the codec does not need to keep any internal copy of + *received symbols. + * + * @fn of_status_t of_set_available_symbols + *(of_session_t* ses, void* const encoding_symbols_tab[]); + * @brief inform the decoder of all the available + *(received) symbols 02@param ses (IN) Pointer to the + *session. + * @param encoding_symbols_tab (IN) Pointer to the available encoding symbols + *table. To each available symbol the corresponding entry in the table must + *point to the associated buffer. Entries set to NULL are interpreted as + * corresponding to erased symbols. + * @return Error status. + */ +of_status_t of_set_available_symbols(of_session_t* ses, + void* const encoding_symbols_tab[]); + +#if 0 /* NOT YET */ +/** + * Idem but the application specifies the list of available symbols instead of using a table. + */ +of_status_t of_set_available_symbol_list (of_session_t* ses, + of_es_list_t encoding_symbols_list); +#endif + +/** + * Finish decoding with whatever symbol is available. + * The application is expected to have used either of_decode_with_new_symbol() + *or of_set_available_symbols() prior to calling this function. + * + * Although no decoding algorithm is specified here (this is codec specific), in + *case of the LDPC-* codecs, this function usually performs an ITerative + *decoding (IT) algorithm first (if not already done by using + *of_decode_with_new_symbol()) and finishes with a Gaussian Elimination. + * + * @fn of_status_t of_finish_decoding (of_session_t* + *ses) + * @brief finish decoding with available symbols + *02@param ses (IN) Pointer to the session. + * @return Error status. Returns OF_STATUS_FAILURE if decoding + *failed, or OF_STATUS_OK if decoding succeeded, or OF_STATUS_*_ERROR in case of + *(fatal) error. + */ +of_status_t of_finish_decoding(of_session_t* ses); + +/** + * Returns true if the decoding is finished, i.e. if all the source symbols have + *been received or decoded. Returns false otherwise. + * + * @fn bool of_is_decoding_complete (of_session_t* + *ses) + * @brief check if decoding is finished + *02@param ses (IN) Pointer to the session. + * @return Boolean. Warning, this is one of the very functions of + *the library that does not return an error status. + */ +bool of_is_decoding_complete(of_session_t* ses); + +/** + * Get a copy of the table of available (received or decoded) source symbols. + * This function is usually called once decoding is finished. In some + *situations, it might be interesting to call it even if decoding is not + *succesful, since additional source symbols might have been decoded. + * + * @fn of_status_t of_get_source_symbols_tab (of_session_t* + *ses, void* source_symbols_tab[]) + * @brief get the table of available source symbols (after + *decoding) 02@param ses (IN) Pointer to the session. + * @param source_symbols_tab (IN/OUT) table, that will be filled by the + *library and returned to the application. + * @return Error status. + */ +of_status_t of_get_source_symbols_tab(of_session_t* ses, + void* source_symbols_tab[]); + +#endif /* OF_USE_DECODER */ + +/* + * Additional functions + * ******************** + */ + +/** + * Return information about the OpenFEC Library in general, and the codec used + *in particular on condition the session pointer is not NULL. If the session + *pointer is NULL, only the general string is returned. Note that the returned + *string is totally managed by the library and must not be released by the + *application. + * + *02@param ses (IN) Pointer to the session or NULL. + *02@param version_str (IN/OUT) address of a pointer to a string. This pointer + *is updated by this function to point ot a static string (that must not be + *released by the caller). 02@param copyrights_str (IN/OUT) address of a pointer + *to a string. This pointer is updated by this function to point ot a static + *string (that must not be released by the caller). + * @return Error status. + */ +of_status_t of_more_about(of_session_t* ses, char** version_str, + char** copyrights_str); + +/** + * This function sets a FEC scheme/FEC codec specific control parameter, in + *addition to the FEC OTI, using a type/value method. + * + *02@param ses (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID + *specific. + * @param value (IN) Pointer to the value of the parameter. The type of + *the object pointed is FEC codec ID specific. + * @param length (IN) length of pointer value + * @return Error status. + */ +of_status_t of_set_control_parameter(of_session_t* ses, UINT32 type, + void* value, UINT32 length); + +/** + * This function gets a FEC scheme/FEC codec specific control parameter, in + *addition to the FEC OTI, using a type/value method. + * + *02@param ses (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID + *specific. + * @param value (IN/OUT) Pointer to the value of the parameter. The type + *of the object pointed is FEC codec ID specific. This function updates the + *value object accordingly. The application, who knows the FEC codec ID, is + *responsible to allocating the approriate object pointed by the value pointer. + * @param length (IN) length of pointer value + * @return Error status. + */ +of_status_t of_get_control_parameter(of_session_t* ses, UINT32 type, + void* value, UINT32 length); + +/** + * Control parameters for of_set_control_parameter()/of_get_control_parameter() + *functions: + * - range {0 .. 1023} inclusive are for generic parameters; + * - range {1024 .. above} inclusive are for code/codec specific parameters + *(and different codecs can re-use the same value); The "void * value" type + *depends on the type. The generic parameters are listed bellow, the code/codec + *specific parameters are listed in the codec directory. + */ + +/** + * Get the maximum k parameter for this codec. To the potential limits of the + * code itself (e.g. RS over GF(2^8) have a strict limit to k +#include "of_openfec_api.h" +#include "of_rand.h" + + +UINT64 of_seed; + +/** + * Set this constant to check the conformity for this prng. + * Do that only in debug mode since it's time consumming. + */ +//#define CHECK_PRNG_CONFORMITY + +#if CHECK_PRNG_CONFORMITY +/** + * Check that the PRNG is compliant with [Park88]. + */ +void +of_check_prng (void) +{ + OF_ENTER_FUNCTION + INT32 i; + UINT64 val; + + of_seed = 1; + for (i = 0; i < 10000; i++) + { + val = of_rand (0x7FFFFFFF); + } + if (val != 1043618065) + { + fprintf (stderr, "ldpc_rand: ERROR, invalid PRNG, 10,000th value is %d\n", val); + OF_EXIT_FUNCTION + return; + } + else + { + fprintf (stderr, "ldpc_rand: okay, PRNG is valid, 10,000th value is %d\n", val); + } + OF_EXIT_FUNCTION +} +#endif + + +/** + * Initialize the PRNG with a of_seed between 1 and 0x7FFFFFFE + * (2^^31-2) inclusive. + */ +void of_rfc5170_srand (UINT64 s) +{ + OF_ENTER_FUNCTION + if ( (s >= 1) && (s <= 0x7FFFFFFE)) + of_seed = s; + else + { + fprintf (stderr, "ldpc_rand: ERROR, seed (%llu) out of range\n", of_seed); + OF_EXIT_FUNCTION + return; + } +#if CHECK_PRNG_CONFORMITY + check_PRNG(); + of_seed = s; +#endif + OF_EXIT_FUNCTION +} + + +/** + * Returns a random integer between 0 and maxv-1 inclusive. + * Derived from rand31pmc, Robin Whittle, Sept 20th 2005. + * http://www.firstpr.com.au/dsp/rand31/ + * 16807 multiplier constant (7^^5) + * 0x7FFFFFFF modulo constant (2^^31-1) + * The inner PRNG produces a value between 1 and 0x7FFFFFFE + * (2^^31-2) inclusive. + * This value is then scaled between 0 and maxv-1 inclusive. + * This is the PRNG required by the LDPC-staircase RFC 5170. + */ +UINT64 +of_rfc5170_rand (UINT64 maxv) +{ + //OF_ENTER_FUNCTION + UINT64 hi, lo; + lo = 16807 * (of_seed & 0xFFFF); + hi = 16807 * (of_seed >> 16); + lo += (hi & 0x7FFF) << 16; + lo += hi >> 15; + if (lo > 0x7FFFFFFF) + lo -= 0x7FFFFFFF; + of_seed = (UINT64) lo; + //OF_EXIT_FUNCTION + return ( (UINT64) + ( (double) of_seed * (double) maxv / (double) 0x7FFFFFFF)); +} + diff --git a/thirdparty/openfec/src/lib_common/of_rand.h b/thirdparty/openfec/src/lib_common/of_rand.h new file mode 100644 index 0000000..8900c8f --- /dev/null +++ b/thirdparty/openfec/src/lib_common/of_rand.h @@ -0,0 +1,62 @@ +/* $Id: of_rand.h 186 2014-07-16 07:17:53Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef OF_RAND +#define OF_RAND + + +/** + * \fn void of_rfc5170_srand (UINT64 s) + * \brief Initialize the PRNG with a of_seed between 1 and 0x7FFFFFFE + * (2^^31-2) inclusive. + * \param s (IN) seed + * \return void + */ +void of_rfc5170_srand (UINT64 s); + + +/** + * \fn UINT64 of_rfc5170_rand (UINT64 maxv) + * \brief Derived from rand31pmc, Robin Whittle, Sept 20th 2005. + * http://www.firstpr.com.au/dsp/rand31/ + * 16807 multiplier constant (7^^5) + * 0x7FFFFFFF modulo constant (2^^31-1) + * The inner PRNG produces a value between 1 and 0x7FFFFFFE + * (2^^31-2) inclusive. + * This value is then scaled between 0 and maxv-1 inclusive. + * This is the PRNG required by the LDPC-staircase RFC 5170. + * \return Returns a random integer between 0 and maxv-1 inclusive. + */ +UINT64 of_rfc5170_rand (UINT64 maxv); + +#endif //OF_RAND diff --git a/thirdparty/openfec/src/lib_common/of_types.h b/thirdparty/openfec/src/lib_common/of_types.h new file mode 100644 index 0000000..66c2a91 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/of_types.h @@ -0,0 +1,82 @@ +/* $Id: of_types.h 72 2012-04-13 13:27:26Z detchart $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + + +#ifndef OF_TYPES +#define OF_TYPES + + +#ifndef __cplusplus +#ifndef bool +#define bool UINT32 +#define true 1 +#define false 0 +#endif +#endif /* !__cplusplus */ + +#ifndef UINT32 +#define INT8 char +#define INT16 short +#define UINT8 unsigned char +#define UINT16 unsigned short + +#if defined(__LP64__) || (__WORDSIZE == 64) /* 64 bit architectures */ +#define INT32 int /* yes, it's also true in LP64! */ +#define UINT32 unsigned int /* yes, it's also true in LP64! */ + +#else /* 32 bit architectures */ + +#define INT32 int /* int creates fewer compilations pbs than long */ +#define UINT32 unsigned int /* int creates fewer compilations pbs than long */ +#endif /* 32/64 architectures */ + +#endif /* !UINT32 */ + +#ifndef UINT64 +#ifdef WIN32 +#define INT64 __int64 +#define UINT64 __uint64 +#else /* UNIX */ +#define INT64 long long +#define UINT64 unsigned long long +#endif /* OS */ +#endif /* !UINT64 */ + + +/** + * gf type is used for Reed-Solomon codecs (over 2^8 and 2^m with m <=8). + * It reprensents a Galois field element. + */ +typedef unsigned char gf; + +#endif //OF_TYPES diff --git a/thirdparty/openfec/src/lib_common/statistics/of_statistics.c b/thirdparty/openfec/src/lib_common/statistics/of_statistics.c new file mode 100644 index 0000000..6a96347 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/statistics/of_statistics.c @@ -0,0 +1,56 @@ +/* $Id: of_statistics.c 207 2014-12-10 19:47:50Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include +#include "../of_types.h" +#include "../of_debug.h" +#include "../of_openfec_api.h" +#include "of_statistics.h" + + +#ifdef OF_DEBUG + + +void of_print_symbols_stats(of_symbols_stats_t* stats) +{ + OF_TRACE_LVL(0,("nb source symbols received: %u\n", stats->nb_source_symbols_received)) + OF_TRACE_LVL(0,("nb repair symbols received: %u\n", stats->nb_repair_symbols_received)); + OF_TRACE_LVL(0,("nb source symbols built during IT decoding: %i\n", stats->nb_source_symbols_built_with_it)); + OF_TRACE_LVL(0,("nb repair symbols built during IT decoding: %i\n", stats->nb_repair_symbols_built_with_it)); + OF_TRACE_LVL(0,("nb source symbols built during ML decoding: %i\n", stats->nb_source_symbols_built_with_ml)); + OF_TRACE_LVL(0,("nb repair symbols built during ML decoding: %i\n", stats->nb_repair_symbols_built_with_ml)); + OF_TRACE_LVL(0,("nb source symbols ignored: %i\n", stats->nb_source_symbols_ignored)); + OF_TRACE_LVL(0,("nb repair symbols ignored: %i\n", stats->nb_repair_symbols_ignored)); +} + +#endif diff --git a/thirdparty/openfec/src/lib_common/statistics/of_statistics.h b/thirdparty/openfec/src/lib_common/statistics/of_statistics.h new file mode 100644 index 0000000..bc7e6e0 --- /dev/null +++ b/thirdparty/openfec/src/lib_common/statistics/of_statistics.h @@ -0,0 +1,73 @@ +/* $Id: of_statistics.h 186 2014-07-16 07:17:53Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef STATISTICS_H +#define STATISTICS_H + + +#ifdef OF_DEBUG + + +/** + * Symbol level statistics. + */ +typedef struct of_symbols_stats +{ + /** Number of source symbols received by decoder (they havn't been decoded). */ + UINT32 nb_source_symbols_received; + /** Number of repair symbols received by decoder (they havn't been decoded). */ + UINT32 nb_repair_symbols_received; + /** Number of source symbols decoded during IT decoding. */ + UINT32 nb_source_symbols_built_with_it; + /** Number of source symbols decoded during ML decoding. */ + UINT32 nb_source_symbols_built_with_ml; + /** Number of repair symbols decoded during IT decoding. */ + UINT32 nb_repair_symbols_built_with_it; + /** Number of repair symbols decoded during ML decoding. */ + UINT32 nb_repair_symbols_built_with_ml; + /** Number of source symbols ...... */ + UINT32 nb_source_symbols_ignored; + /** Number of repair symbols ...... */ + UINT32 nb_repair_symbols_ignored; +} of_symbols_stats_t; + + +/** + * Print the statistics to the standard output. + */ +void of_print_symbols_stats(of_symbols_stats_t*); + + +#endif // OF_DEBUG + +#endif //STATISTICS_H diff --git a/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity.h b/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity.h new file mode 100644 index 0000000..3e5aeb1 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity.h @@ -0,0 +1,319 @@ +/* $Id: of_2d_parity.h 184 2014-07-15 09:42:57Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + +#ifndef OF_2D_PARITY_H +#define OF_2D_PARITY_H + +typedef struct of_2d_symbol_stats_op +{ + UINT32 nb_xor_for_IT; + UINT32 nb_xor_for_ML; +} of_2d_symbol_stats_op_t; + +/** + * 2d-parity stable codec specific control block structure. + */ +typedef struct of_2d_parity_cb +{ +/***************************************************************************** +* of_linear_binary_code_cb * +******************************************************************************/ +/* * +************************************************************************** * +* of_cb_t * * +************************************************************************** */ + of_codec_id_t codec_id; /* must begin with fec_codec_id * */ + of_codec_type_t codec_type; /* must be 2nd item * */ + UINT32 nb_source_symbols; /** k parameter (AKA code dimension).* */ + UINT32 nb_repair_symbols; /** r = n - k parameter. * */ + UINT32 encoding_symbol_length; /** symbol length. * */ +/************************************************************************* */ + + UINT32 nb_total_symbols; /** n parameter (AKA code length). */ + + /* parity check matrix */ + of_mod2sparse* pchk_matrix; + + /** usage statistics, for this codec instance. */ + of_symbol_stats_op_t *stats_xor; +#ifdef OF_DEBUG + of_symbols_stats_t* stats_symbols; +#endif + UINT32 nb_source_symbol_ready; // Number of source symbols ready + UINT32 nb_repair_symbol_ready; // Number of parity symbols ready + +#ifdef ML_DECODING /* { */ + UINT32 *index_rows; // Indirection index to access initial m_chekValues array + UINT32 *index_cols; // Indirection index to access initial symbol array + UINT32 remain_cols; // Nb of non empty remaining cols in the future simplified matrix + UINT32 remain_rows; // Nb of non empty remaining rows in the future simplified matrix + + of_mod2sparse *pchk_matrix_simplified; // Simplified Parity Check Matrix in sparse mode format + of_mod2sparse *original_pchkMatrix; + of_mod2sparse* pchk_matrix_gauss; // Parity Check matrix in sparse mode format. + // This matrix is also used as a generator matrix + UINT32 dec_step; // Current step in the Gauss decoding algorithm + UINT32 threshold_simplification; // threshold (number of symbols) above which we + // run the Gaussian Elimination algorithm +#endif /* } ML_DECODING */ + +#ifdef OF_USE_DECODER /* { */ + /** table of all check values, i.e. that contain the constant term of each equation. */ + void** tab_const_term_of_equ; + /** table containing the number of encoding symbols of each equation. */ + UINT16* tab_nb_enc_symbols_per_equ; + /** table containing the number of unknow symbols (i.e. neither received nor decoded + * at that time) of each equation. */ + UINT16* tab_nb_unknown_symbols; + /** table containing the number of equations in which a repair symbol is included. */ + UINT16* tab_nb_equ_for_repair; + + void** repair_symbols_values; +#endif /* } OF_USE_DECODER */ + + void **encoding_symbols_tab; + + /** callbacks registered by the application. */ + void* (*decoded_source_symbol_callback) (void *context,/* */ + UINT32 size, /* size of decoded source symbol */ + UINT32 esi); /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context,/* */ + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi); /* encoding symbol ID in {0..k-1} */ + void* context_4_callback;/* */ +/*****************************************************************************/ + + /** Maximum number of source symbols supported by this codec for practical reasons. */ + UINT32 max_nb_source_symbols; + /** Maximum number of encoding symbols supported by this codec for practical reasons. */ + UINT32 max_nb_encoding_symbols; + + /** ESI of first non decoded source symbol. + * Used by is_decoding_complete function. */ + UINT32 first_non_decoded; + +} of_2d_parity_cb_t; + + +/* + * Function prototypes. + */ + /** + * This function create the codec instance for the 2D parity codec. + * + * @fn of_status_t of_2d_parity_create_codec_instance (of_2d_parity_cb_t** of_cb) + * @brief create a 2D parity codec instance + * @param of_cb (IN/OUT) address of the pointer to a 2D parity codec control block. This pointer is updated + * by this function. + * In case of success, it points to a session structure allocated by the + * library. In case of failure it points to NULL. + * @return Error status. The ofcb pointer is updated according to the success return + * status. + */ +of_status_t of_2d_parity_create_codec_instance (of_2d_parity_cb_t** of_cb); + + +/** + * This function releases all the internal resources used by this FEC codec instance. + * None of the source symbol buffers will be free'ed by this function, even those decoded by + * the library if any, regardless of whether a callback has been registered or not. It's the + * responsibility of the caller to free them. + * + * @fn of_status_t of_2d_parity_release_codec_instance (of_2d_parity_cb_t* ofcb) + * @brief release all resources used by the codec + * @param ofcb (IN) Pointer to the control block. + * @return Error status. + */ +of_status_t of_2d_parity_release_codec_instance (of_2d_parity_cb_t* ofcb); + +/** + * + * @fn of_status_t of_2d_parity_set_fec_parameters (of_2d_parity_cb_t* ofcb, of_2d_parity_parameters_t* params) + * @brief set all the FEC codec parameters (e.g. k, n, or symbol size) + * @param ofcb (IN) Pointer to the control block. + * @param params (IN) pointer to a structure containing the FEC parameters associated to + * a specific FEC codec. + * @return Error status. + */ +of_status_t of_2d_parity_set_fec_parameters (of_2d_parity_cb_t* ofcb, + of_2d_parity_parameters_t* params); +/** + * @fn of_status_t of_2d_parity_set_callback_functions (of_2d_parity_cb_t *ofcb,void* (*decoded_source_symbol_callback) + * (void *context,UINT32 size,UINT32 esi), void* (*decoded_repair_symbol_callback) + * (void *context,UINT32 size,UINT32 esi),void* context_4_callback) + * @brief set various callbock functions (see header of_open_fec_api.h) + * @param ofcb (IN) Pointer to the session. + * + * @param decoded_source_symbol_callback + * (IN) Pointer to the function, within the application, that + * needs to be called each time a source symbol is decoded. + * If this callback is not initialized, the symbol is managed + * internally. + * + * @param decoded_repair_symbol_callback + * (IN) Pointer to the function, within the application, that + * needs to be called each time a repair symbol is decoded. + * If this callback is not initialized, the symbol is managed + * internally. + * + * @param context_4_callback (IN) Pointer to the application-specific context that will be + * passed to the callback function (if any). This context is not + * interpreted by this function. + * + * @return Completion status (LDPC_OK or LDPC_ERROR). + */ +of_status_t of_2d_parity_set_callback_functions (of_2d_parity_cb_t* ofcb, + void* (*decoded_source_symbol_callback) (void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* context_4_callback); + +#ifdef OF_USE_ENCODER +/** + * @fn of_status_t of_2d_parity_build_repair_symbol (of_2d_parity_cb_t* ofcb, void* encoding_symbols_tab[], UINT32 esi_of_symbol_to_build) + * @brief build a repair symbol (encoder only) + * @param ofcb (IN) Pointer to the session. + * @param encoding_symbols_tab (IN/OUT) table of source and repair symbols. + * The entry for the repair symbol to build can either point + * to a buffer allocated by the application, or let to NULL + * meaning that of_build_repair_symbol will allocate memory. + * @param esi_of_symbol_to_build + * (IN) encoding symbol ID of the repair symbol to build in + * {k..n-1} + * @return Error status. + */ +of_status_t of_2d_parity_build_repair_symbol (of_2d_parity_cb_t* ofcb, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build); +#endif //OF_USE_ENCODER + +#ifdef OF_USE_DECODER +/** + * @fn of_status_t of_2d_parity_decode_with_new_symbol (of_2d_parity_cb_t* ofcb, void* const new_symbol_buf, UINT32 new_symbol_esi) + * @brief (try to) decode with a newly received symbol + * @param ofcb (IN) Pointer to the session. + * @param new_symbol (IN) Pointer to the encoding symbol now available (i.e. a new + * symbol received by the application, or a decoded symbol in case + * of a recursive call). + * @param new_symbol_esi (IN) Encoding symbol ID of the newly symbol available, in {0..n-1}. + * @return Error status (NB: this function does not return OF_STATUS_FAILURE). + */ +of_status_t of_2d_parity_decode_with_new_symbol (of_2d_parity_cb_t* ofcb, + void* new_symbol, + UINT32 new_symbol_esi); + +/** + * @fn of_status_t of_2d_parity_set_available_symbols (of_2d_parity_cb_t* ofcb, void* const encoding_symbols_tab[]); + * @brief inform the decoder of all the available (received) symbols + * @param ofcb (IN) Pointer to the session. + * @param encoding_symbols_tab (IN) Pointer to the available encoding symbols table. To each + * available symbol the corresponding entry in the table must point + * to the associated buffer. Entries set to NULL are interpreted as + * corresponding to erased symbols. + * @return Error status. + */ +of_status_t of_2d_parity_set_available_symbols (of_2d_parity_cb_t* ofcb, + void* const encoding_symbols_tab[]); + +/** + * @fn of_status_t of_2d_parity_finish_decoding (of_2d_parity_cb_t* ofcb) + * @brief finish decoding with available symbols + * @param ofcb (IN) Pointer to the session. + * @return Error status. Returns OF_STATUS_FAILURE if decoding failed, or + * OF_STATUS_OK if decoding succeeded, or OF_STATUS_*_ERROR in case + * of (fatal) error. + */ +of_status_t of_2d_parity_finish_decoding (of_2d_parity_cb_t* ofcb); + +/** + * @fn bool of_2d_parity_is_decoding_complete (of_2d_parity_cb_t* ofcb) + * @brief check if decoding is finished + * @param ofcb (IN) Pointer to the session. + * @return Boolean. Warning, this is one of the very functions of the library that + * does not return an error status. + */ +bool of_2d_parity_is_decoding_complete (of_2d_parity_cb_t* ofcb); + +/** + * @fn of_status_t of_2d_parity_get_source_symbols_tab (of_2d_parity_cb_t* ofcb, void* source_symbols_tab[]) + * @brief get the table of available source symbols (after decoding) + * @param ofcb (IN) Pointer to the session. + * @param source_symbols_tab (IN/OUT) table, that will be filled by the library and returned + * to the application. + * @return Error status. + */ +of_status_t of_2d_parity_get_source_symbols_tab (of_2d_parity_cb_t* ofcb, + void* source_symbols_tab[]); + +/** + * @fn of_status_t of_2d_parity_set_control_parameter (of_2d_parity_cb_t* ofcb,UINT32 type,void* value,UINT32 length) + * @brief set a specific FEC parameter + * @param ofcb (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID specific. + * @param value (IN) Pointer to the value of the parameter. The type of the object pointed + * is FEC codec ID specific. + * @param length (IN) length of pointer value + * @return Error status. + */ +of_status_t of_2d_parity_set_control_parameter(of_2d_parity_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length); + +/** + * @fn of_status_t of_2d_parity_get_control_parameter (of_2d_parity_cb_t* ofcb,UINT32 type,void* value,UINT32 length) + * @brief get a specific FEC parameter + * @param ofcb (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID specific. + * @param value (IN/OUT) Pointer to the value of the parameter. The type of the object + * pointed is FEC codec ID specific. This function updates the value object + * accordingly. The application, who knows the FEC codec ID, is responsible + * to allocating the approriate object pointed by the value pointer. + * @param length (IN) length of pointer value + * @return Error status. + */ +of_status_t of_2d_parity_get_control_parameter(of_2d_parity_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length); + +#endif //OF_USE_DECODER + +#endif //OF_2D_PARITY_H + +#endif /* #ifdef OF_USE_2D_PARITY_MATRIX_CODEC */ diff --git a/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity_api.c b/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity_api.c new file mode 100644 index 0000000..2f272d5 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity_api.c @@ -0,0 +1,464 @@ +/* $Id: of_2d_parity_api.c 185 2014-07-15 09:57:16Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "of_2d_parity_includes.h" + +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + + + +of_status_t of_2d_parity_create_codec_instance (of_2d_parity_cb_t** of_cb) +{ + of_codec_type_t codec_type; /* temporary value */ + of_2d_parity_cb_t *cb; + + OF_ENTER_FUNCTION + cb = (of_2d_parity_cb_t*) of_realloc (*of_cb, sizeof (of_2d_parity_cb_t)); + /* realloc does not initialize the additional buffer space, so do that manually, + * then re-initialize a few parameters */ + codec_type = cb->codec_type; + memset(cb, 0, sizeof(*cb)); + *of_cb = cb; + cb->codec_id = OF_CODEC_2D_PARITY_MATRIX_STABLE; + cb->codec_type = codec_type; + cb->max_nb_source_symbols = OF_2D_PARITY_MATRIX_MAX_NB_SOURCE_SYMBOLS_DEFAULT; /* init it immediately... */ + cb->max_nb_encoding_symbols = OF_2D_PARITY_MATRIX_MAX_NB_ENCODING_SYMBOLS_DEFAULT; /* init it immediately... */ + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_2d_parity_release_codec_instance (of_2d_parity_cb_t* ofcb) +{ + UINT32 i; + + OF_ENTER_FUNCTION + if (ofcb->pchk_matrix != NULL) + { + of_mod2sparse_free(ofcb->pchk_matrix); + of_free (ofcb->pchk_matrix); + ofcb->pchk_matrix = NULL; + } + if (ofcb->encoding_symbols_tab != NULL) + { + /* do not try to free source buffers, it's the responsibility of the application + * using this library to free everything. Only try to free repair symbols. */ + for (i = ofcb->nb_source_symbols; i < ofcb->nb_total_symbols; i++) + { + if (ofcb->encoding_symbols_tab[i] != NULL) + { + of_free (ofcb->encoding_symbols_tab[i]); + ofcb->encoding_symbols_tab[i] = NULL; + } + } + of_free (ofcb->encoding_symbols_tab); + ofcb->encoding_symbols_tab = NULL; + } +#ifdef OF_USE_DECODER + if(ofcb->codec_type & OF_DECODER) + { + if (ofcb->tab_nb_enc_symbols_per_equ != NULL) + { + of_free (ofcb->tab_nb_enc_symbols_per_equ); + ofcb->tab_nb_enc_symbols_per_equ = NULL; + } + if (ofcb->tab_nb_equ_for_repair != NULL) + { + of_free (ofcb->tab_nb_equ_for_repair); + ofcb->tab_nb_equ_for_repair = NULL; + } + if (ofcb->tab_nb_unknown_symbols != NULL) + { + of_free (ofcb->tab_nb_unknown_symbols); + ofcb->tab_nb_unknown_symbols = NULL; + } + if (ofcb->tab_const_term_of_equ != NULL) + { + for (i = 0; i < ofcb->nb_repair_symbols; i++) + { + if (ofcb->tab_const_term_of_equ[i] != NULL) + { + of_free (ofcb->tab_const_term_of_equ[i]); + ofcb->tab_const_term_of_equ[i] = NULL; + } + } + of_free(ofcb->tab_const_term_of_equ); + } + } +#endif + +#ifdef OF_2D_PARITY_ML_DECODING + if (ofcb->index_rows != NULL) + { + of_free (ofcb->index_rows); + ofcb->index_rows = NULL; + } + if (ofcb->index_cols != NULL) + { + of_free (ofcb->index_cols); + ofcb->index_cols = NULL; + } + if (ofcb->pchk_matrix_simplified != NULL) + { + of_mod2sparse_free (ofcb->pchk_matrix_simplified); + of_free(ofcb->pchk_matrix_simplified); + ofcb->pchk_matrix_simplified = NULL; + } + if (ofcb->original_pchkMatrix != NULL) + { + of_mod2sparse_free (ofcb->original_pchkMatrix); + ofcb->original_pchkMatrix = NULL; + } + if (ofcb->pchk_matrix_gauss != NULL) + { + of_mod2sparse_free (ofcb->pchk_matrix_gauss); + ofcb->pchk_matrix_gauss = NULL; + } +#endif +#ifdef OF_DEBUG + if (ofcb->stats_xor != NULL) + { + of_print_xor_symbols_statistics(ofcb->stats_xor); + of_free(ofcb->stats_xor); + } +#endif + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_2d_parity_set_fec_parameters (of_2d_parity_cb_t* ofcb, + of_2d_parity_parameters_t* params) +{ + of_mod2entry *e; + UINT32 row; + UINT32 seq; + + OF_ENTER_FUNCTION + +#ifdef OF_DEBUG + ofcb->stats_xor = of_calloc(1, sizeof(of_2d_symbol_stats_op_t)); + ofcb->stats_symbols = of_calloc(1,sizeof(of_symbols_stats_t)); +#endif + if ((ofcb->nb_source_symbols = params->nb_source_symbols) > ofcb->max_nb_source_symbols) { + OF_PRINT_ERROR(("of_2d_parity_set_fec_parameters: ERROR, invalid nb_source_symbols parameter (got %d, maximum is %d)", + ofcb->nb_source_symbols, ofcb->max_nb_source_symbols)); + goto error; + } + ofcb->nb_repair_symbols = params->nb_repair_symbols; + ofcb->nb_total_symbols = ofcb->nb_source_symbols + ofcb->nb_repair_symbols; + if (ofcb->nb_total_symbols > ofcb->max_nb_encoding_symbols) { + OF_PRINT_ERROR(("of_2d_parity_set_fec_parameters: ERROR, invalid number of encoding symbols (got %d, maximum is %d)", + ofcb->nb_total_symbols, ofcb->max_nb_encoding_symbols)); + goto error; + } + ofcb->encoding_symbol_length = params->encoding_symbol_length; + OF_TRACE_LVL (1, ("%s: k=%u, n-k=%u, n=%u, symbol_length=%u, PRNG seed=%u, N1=%u\n", __FUNCTION__, + ofcb->nb_source_symbols, ofcb->nb_repair_symbols, ofcb->nb_total_symbols, + ofcb->encoding_symbol_length, 0, 0)) + ofcb->pchk_matrix = of_create_pchk_matrix (ofcb->nb_repair_symbols, ofcb->nb_total_symbols, Evenboth, + 0, 0, false, Type2DMATRIX, 1); + + if (ofcb->pchk_matrix == NULL) + { + OF_PRINT_ERROR(("of_2d_parity_set_fec_parameters : ERROR, parity check matrix can't be created with this parameters..")) + goto error; + } +#ifdef OF_DEBUG + if (of_verbosity >= 2) + { + of_mod2sparse_matrix_stats(stdout, ofcb->pchk_matrix, ofcb->nb_source_symbols, ofcb->nb_repair_symbols); + } +#endif + +#ifdef OF_2D_PARITY_ML_DECODING + ofcb->pchk_matrix_simplified = NULL; +#endif + if ((ofcb->encoding_symbols_tab = (void**) of_calloc (ofcb->nb_total_symbols, sizeof (void*))) == NULL) { + goto no_mem; + } +#ifdef OF_USE_DECODER + if (ofcb->codec_type & OF_DECODER) + { + ofcb->tab_nb_unknown_symbols = (UINT16*) + of_calloc (ofcb->nb_repair_symbols, sizeof (UINT16)); + ofcb->tab_const_term_of_equ = (void**) + of_calloc (ofcb->nb_repair_symbols, sizeof (void*)); + ofcb->tab_nb_equ_for_repair = (UINT16*) + of_calloc (ofcb->nb_repair_symbols, sizeof (UINT16)); + ofcb->tab_nb_enc_symbols_per_equ = (UINT16*) + of_calloc (ofcb->nb_repair_symbols, sizeof (UINT16)); + if (ofcb->tab_nb_unknown_symbols == NULL || ofcb->tab_const_term_of_equ == NULL || + ofcb->tab_nb_equ_for_repair == NULL || ofcb->tab_nb_enc_symbols_per_equ == NULL) { + goto no_mem; + } + // and update the various tables now + for (row = 0; row < ofcb->nb_repair_symbols; row++) + { + for (e = of_mod2sparse_first_in_row (ofcb->pchk_matrix, row); + !of_mod2sparse_at_end (e); + e = of_mod2sparse_next_in_row (e)) + { + ofcb->tab_nb_enc_symbols_per_equ[row]++; + ofcb->tab_nb_unknown_symbols[row]++; + } + } + for (seq = ofcb->nb_source_symbols; seq < (ofcb->nb_total_symbols); seq++) + { + for (e = of_mod2sparse_first_in_col (ofcb->pchk_matrix, of_get_symbol_col ((of_cb_t*)ofcb, seq)); + !of_mod2sparse_at_end (e); + e = of_mod2sparse_next_in_col (e)) + { + ofcb->tab_nb_equ_for_repair[seq - ofcb->nb_source_symbols]++; + } + } + } +#endif //OF_USE_DECODER + ofcb->nb_source_symbol_ready = 0; // Number of source symbols ready + ofcb->nb_repair_symbol_ready = 0; // Number of parity symbols ready + //ofcb->nb_non_dup_symbols_recvd = 0;// Number of non-duplicated symbols received +#ifdef OF_2D_PARITY_ML_DECODING + ofcb->index_rows = NULL; // Indirection index to access initial m_chekValues array + ofcb->index_cols = NULL; // Indirection index to access initial symbol array + ofcb->remain_cols = 0; // Nb of non empty remaining cols in the future simplified matrix + ofcb->remain_rows = 0; // Nb of non empty remaining rows in the future simplified matrix + ofcb->pchk_matrix_simplified = NULL; // Simplified Parity Check Matrix in sparse mode format + ofcb->original_pchkMatrix = NULL; + ofcb->pchk_matrix_gauss = NULL; // Parity Check matrix in sparse mode format. This matrix + // is also used as a generator matrix in LDGM-* modes + ofcb->dec_step = 0; // Current step in the Gauss Elimination algorithm + ofcb->threshold_simplification = 0; // threshold (number of symbols) above which we + // run the Gauss Elimination algorithm +#endif + + OF_EXIT_FUNCTION + return OF_STATUS_OK; +no_mem: + OF_PRINT_ERROR(("out of memory")); +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + + +of_status_t of_2d_parity_set_callback_functions ( + of_2d_parity_cb_t* ofcb, + void* (*decoded_source_symbol_callback) ( + void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) ( + void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi), /* encoding symbol ID in {k..n-1} */ + void* context_4_callback) +{ + OF_ENTER_FUNCTION + ofcb->decoded_source_symbol_callback = decoded_source_symbol_callback; + ofcb->decoded_repair_symbol_callback = decoded_repair_symbol_callback; + ofcb->context_4_callback = context_4_callback; + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + +#ifdef OF_USE_ENCODER + +of_status_t of_2d_parity_build_repair_symbol (of_2d_parity_cb_t* ofcb, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build) +{ + of_mod2entry *e; + UINT32 col_to_build; + UINT32 esi; + void *to_add_buf; + void *parity_symbol; + OF_ENTER_FUNCTION + if (esi_of_symbol_to_build< ofcb->nb_source_symbols || esi_of_symbol_to_build >= ofcb->nb_total_symbols) + { + OF_PRINT_ERROR(("of_2d_parity_build_repair_symbol: Error, bad esi of encoding symbol (%d)", esi_of_symbol_to_build)) + goto error; + } + parity_symbol = encoding_symbols_tab[esi_of_symbol_to_build]; + memset (parity_symbol, 0, ofcb->encoding_symbol_length); + col_to_build = of_get_symbol_col ((of_cb_t*)ofcb, esi_of_symbol_to_build); + e = of_mod2sparse_first_in_row (ofcb->pchk_matrix, col_to_build); + while (!of_mod2sparse_at_end (e)) + { + // paritySymbol_index in {0.. n-k-1} range, so this test is ok + if (e->col != col_to_build) + { + // don't add paritySymbol to itself + esi = of_get_symbol_esi ((of_cb_t*)ofcb, e->col); + to_add_buf = (void*) encoding_symbols_tab[esi]; + if (to_add_buf == NULL) + { + OF_PRINT_ERROR(("symbol %d is not allocated", esi)); + goto error; + } +#ifdef OF_DEBUG + of_add_to_symbol (parity_symbol, to_add_buf, ofcb->encoding_symbol_length, &(ofcb->stats_xor->nb_xor_for_IT)); +#else + of_add_to_symbol (parity_symbol, to_add_buf, ofcb->encoding_symbol_length); +#endif + } + e = of_mod2sparse_next_in_row (e); + } + OF_TRACE_LVL (1, ("%s: repair symbol (esi=%d) built\n", __FUNCTION__, esi_of_symbol_to_build)) + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + +#endif //OF_USE_ENCODER + +#ifdef OF_USE_DECODER + +of_status_t of_2d_parity_decode_with_new_symbol (of_2d_parity_cb_t* ofcb, + void* new_symbol, + UINT32 new_symbol_esi) +{ + OF_ENTER_FUNCTION + return of_linear_binary_code_decode_with_new_symbol((of_linear_binary_code_cb_t*)ofcb,new_symbol,new_symbol_esi); +} + + +of_status_t of_2d_parity_set_available_symbols (of_2d_parity_cb_t* ofcb, + void* const encoding_symbols_tab[]) +{ + OF_ENTER_FUNCTION + UINT32 i; + for (i = 0; i < ofcb->nb_total_symbols; i++) + { + if (encoding_symbols_tab[i] != NULL) + { + ofcb->encoding_symbols_tab[i] = of_calloc (1, ofcb->encoding_symbol_length); + memcpy (ofcb->encoding_symbols_tab[i], encoding_symbols_tab[i], ofcb->encoding_symbol_length); + } + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_2d_parity_finish_decoding (of_2d_parity_cb_t* ofcb) +{ + OF_ENTER_FUNCTION +#ifdef OF_2D_PARITY_ML_DECODING + return of_linear_binary_code_finish_decoding_with_ml ((of_linear_binary_code_cb_t*)ofcb); +#else + return OF_STATUS_ERROR; +#endif +} + +bool of_2d_parity_is_decoding_complete (of_2d_parity_cb_t* ofcb) +{ + for (; ofcb->first_non_decoded < ofcb->nb_source_symbols; ofcb->first_non_decoded++) + { + if (ofcb->encoding_symbols_tab[ofcb->first_non_decoded] == NULL) + { + OF_TRACE_LVL (1, ("decoding not complete (%u source symbols ready, %u expected)\n", + ofcb->nb_source_symbol_ready, ofcb->nb_source_symbols)) + //ASSERT(ofcb->nb_source_symbol_ready < ofcb->nb_source_symbols); + return false; + } + } + OF_TRACE_LVL (1, ("decoding is complete\n")) + //ASSERT(ofcb->nb_source_symbol_ready == ofcb->nb_source_symbols); + return true; +} + + +of_status_t of_2d_parity_get_source_symbols_tab(of_2d_parity_cb_t* ofcb, + void* source_symbols_tab[]) +{ + OF_ENTER_FUNCTION + memcpy (source_symbols_tab, ofcb->encoding_symbols_tab, sizeof (void *) * ofcb->nb_source_symbols); + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + +#endif //OF_USE_DECODER + +of_status_t of_2d_parity_set_control_parameter (of_2d_parity_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length) +{ + OF_PRINT_ERROR(("of_2d_parity_set_control_parameter: ERROR, not implemented...\n")) + return OF_STATUS_ERROR; +} + + +of_status_t of_2d_parity_get_control_parameter (of_2d_parity_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length) +{ + OF_ENTER_FUNCTION + switch (type) { + case OF_CTRL_GET_MAX_K: + if (value == NULL || length != sizeof(UINT32)) { + OF_PRINT_ERROR(("%s: OF_CTRL_GET_MAX_K ERROR: null value or bad length (got %d, expected %ld)\n", + __FUNCTION__, length, sizeof(UINT32))) + goto error; + } + *(UINT32*)value = ofcb->max_nb_source_symbols; + OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_K (%d)\n", __FUNCTION__, *(UINT32*)value)) + break; + + case OF_CTRL_GET_MAX_N: + if (value == NULL || length != sizeof(UINT32)) { + OF_PRINT_ERROR(("%s: OF_CTRL_GET_MAX_N ERROR: null value or bad length (got %d, expected %ld)\n", + __FUNCTION__, length, sizeof(UINT32))) + goto error; + } + *(UINT32*)value = ofcb->max_nb_encoding_symbols; + OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_N (%d)\n", __FUNCTION__, *(UINT32*)value)) + break; + + default: + OF_PRINT_ERROR(("%s: unknown type (%d)\n", __FUNCTION__, type)) + goto error; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + +#endif /* #ifdef OF_USE_2D_PARITY_MATRIX_CODEC */ diff --git a/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity_api.h b/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity_api.h new file mode 100644 index 0000000..892aea8 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity_api.h @@ -0,0 +1,62 @@ +/* $Id: of_2d_parity_api.h 72 2012-04-13 13:27:26Z detchart $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + +#ifndef OF_CODEC_STABLE_2D_PARITY_API +#define OF_CODEC_STABLE_2D_PARITY_API + + +#include "../../lib_common/of_types.h" + + +/** + * @struct of_2d_parity_parameters_t + * @brief 2D parity stable codec specific FEC parameter structure. + * + * This structure contains the pieces of information required to initialize a codec instance, + * using the of_set_fec_parameters() function. + */ +typedef struct of_2d_parity_parameters +{ + UINT32 nb_source_symbols; /* must be 1st item */ + UINT32 nb_repair_symbols; /* must be 2nd item */ + UINT32 encoding_symbol_length; /* must be 3rd item */ + /* + * FEC codec id specific attributes follow... + */ +} of_2d_parity_parameters_t; + + +#endif /* OF_CODEC_STABLE_2D_PARITY_API */ + +#endif /* #ifdef OF_USE_2D_PARITY_MATRIX_CODEC */ \ No newline at end of file diff --git a/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity_includes.h b/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity_includes.h new file mode 100644 index 0000000..8c16dff --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_2d_parity_includes.h @@ -0,0 +1,55 @@ +/* $Id: of_2d_parity_includes.h 189 2014-07-16 08:53:50Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +#ifndef OF_2D_PARITY_INCLUDES +#define OF_2D_PARITY_INCLUDES + +#include +#include +#include +#include + +#include "../../lib_common/of_openfec_api.h" + +/* + * the remaining includes will only be considered if of_codec_profile.h is + * included above by of_openfec_api.h => of_openfec_profile.h + */ +#ifdef OF_USE_2D_PARITY_MATRIX_CODEC + +#include "../../lib_common/linear_binary_codes_utils/of_linear_binary_code.h" + +#include "of_2d_parity_api.h" +#include "of_2d_parity.h" + +#endif //OF_USE_2D_PARITY_MATRIX_CODEC +#endif //OF_2D_PARITY_INCLUDES diff --git a/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_codec_profile.h b/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_codec_profile.h new file mode 100644 index 0000000..0a5a4b7 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/2d_parity_matrix/of_codec_profile.h @@ -0,0 +1,112 @@ +/* $Id: of_codec_profile.h 175 2014-07-11 09:58:38Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +/****** GENERAL SETUP OPTIONS; EDIT AS APPROPRIATE ****************************/ + +#define OF_USE_2D_PARITY_MATRIX_CODEC + +#ifdef OF_DEBUG +/* additional parameter for memory statistic purposes */ +#define MEM_STATS_ARG ,ofcb->stats +#define MEM_STATS ,stats +#else +#define MEM_STATS_ARG +#define MEM_STATS +#endif + +/** + * Define if you want to enable the use of the ML (Maximum Likelyhood) decoding. + * If enabled, in practice decoding will start with IT decoding and end with ML + * decoding (in this case a Gaussian Elimination) if needed. + * + * Warning: ML decoding enables to reach the best erasure recovery capabilities, + * at the expense of potentially significant computation loads, depending on + * the size and complexity of the simplified system at the end of IT decoding. + * + * See the MAX_NB_SOURCE_SYMBOLS_DEFAULT/MAX_NB_ENCODING_SYMBOLS_DEFAULT + * constants that enable to limit the computation overheads. + */ +#define ML_DECODING + +#ifdef ML_DECODING +#define OF_2D_PARITY_ML_DECODING +#endif + + +/** + * This optimization is only significant in 32-bit architectures. + * With LP64 architectures, padding will be needed, adding 32 more bits, + * which makes this optimization useless... + * + * NB: not yet operational... + */ +#if defined (__LP64__) || (__WORDSIZE == 64) +// useless with 64-bit architectures +#else + +#endif + + +/** + * Define IL_SUPPORT in debug mode if you want to have the possibility to + * produce H/G matrix images, e.g. to include in a report on new LDPC code + * evaluation. + * More precisely, we are relying on the DevIL library (http://openil.sourceforge.net/). + * Please install it on your machine before compiling the OpenFEC library + * if needed. + */ +//#define IL_SUPPORT + + +/** + * Default maximum number of source and encoding symbols for this codec. + * This value depends in particular on the kind of decoder used. To this + * limit, codec implementation details might add other limits (e.g. if + * the ESI values are stored in UINT16 instead of UINT32...). + * + * Hints: + * If ML decoding is enabled and used, then limit yourself to a value + * that is not too high, since decoding might finish with a Gaussian + * elimination on the simplified system. + * In situations where decoding is restricted to IT, the main limit is + * the available memory. It usually means you can set very large values. + */ +#ifndef OF_2D_PARITY_MATRIX_MAX_NB_SOURCE_SYMBOLS_DEFAULT +#ifdef ML_DECODING +#define OF_2D_PARITY_MATRIX_MAX_NB_SOURCE_SYMBOLS_DEFAULT 16 +#define OF_2D_PARITY_MATRIX_MAX_NB_ENCODING_SYMBOLS_DEFAULT 24 +#else +#define OF_2D_PARITY_MATRIX_MAX_NB_SOURCE_SYMBOLS_DEFAULT 16 +#define OF_2D_PARITY_MATRIX_MAX_NB_ENCODING_SYMBOLS_DEFAULT 24 +#endif +#endif diff --git a/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_codec_profile.h b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_codec_profile.h new file mode 100644 index 0000000..8f45f8c --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_codec_profile.h @@ -0,0 +1,99 @@ +/* $Id: of_codec_profile.h 199 2014-10-21 14:25:02Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + + +/****** GENERAL SETUP OPTIONS; EDIT AS APPROPRIATE ****************************/ + +#define OF_USE_LDPC_STAIRCASE_CODEC + +#ifdef OF_DEBUG +/* additional parameter for memory statistic purposes */ +#define MEM_STATS_ARG ,ofcb->stats +#define MEM_STATS ,stats +#else +#define MEM_STATS_ARG +#define MEM_STATS +#endif + +/** + * Define if you want to enable the use of the ML (Maximum Likelyhood) decoding. + * If enabled, in practice decoding will start with IT decoding and end with ML + * decoding (in this case a Gaussian Elimination) if needed. + * + * Warning: ML decoding enables to reach the best erasure recovery capabilities, + * at the expense of potentially significant computation loads, depending on + * the size and complexity of the simplified system at the end of IT decoding. + * + * See the MAX_NB_SOURCE_SYMBOLS_DEFAULT/MAX_NB_ENCODING_SYMBOLS_DEFAULT + * constants that enable to limit the computation overheads. + */ +#define ML_DECODING + +#ifdef ML_DECODING +#define OF_LDPC_STAIRCASE_ML_DECODING +#endif + + +/** + * Define IL_SUPPORT in debug mode if you want to have the possibility to + * produce H/G matrix images, e.g. to include in a report on new LDPC code + * evaluation. + * More precisely, we are relying on the DevIL library (http://openil.sourceforge.net/). + * Please install it on your machine before compiling the OpenFEC library + * if needed. + */ +//#define IL_SUPPORT + + +/** + * Default maximum number of source and encoding symbols for this codec. + * This value depends in particular on the kind of decoder used. To this + * limit, codec implementation details might add other limits (e.g. if + * the ESI values are stored in UINT16 instead of UINT32...). + * + * Hints: + * If ML decoding is enabled and used, then limit yourself to a value + * that is not too high, since decoding might finish with a Gaussian + * elimination on the simplified system. + * In situations where decoding is restricted to IT, the main limit is + * the available memory. It usually means you can set very large values. + */ +#ifndef OF_LDPC_STAIRCASE_MAX_NB_SOURCE_SYMBOLS_DEFAULT +#ifdef ML_DECODING +#define OF_LDPC_STAIRCASE_MAX_NB_SOURCE_SYMBOLS_DEFAULT 50000 +#define OF_LDPC_STAIRCASE_MAX_NB_ENCODING_SYMBOLS_DEFAULT 50000 +#else +#define OF_LDPC_STAIRCASE_MAX_NB_SOURCE_SYMBOLS_DEFAULT 100000 +#define OF_LDPC_STAIRCASE_MAX_NB_ENCODING_SYMBOLS_DEFAULT 100000 +#endif +#endif diff --git a/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_includes.h b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_includes.h new file mode 100644 index 0000000..69b7224 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_includes.h @@ -0,0 +1,57 @@ +/* $Id: of_ldpc_includes.h 189 2014-07-16 08:53:50Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef OF_LDPC_INCLUDES +#define OF_LDPC_INCLUDES + +#include +#include +#include +#include + +#include "../../lib_common/of_openfec_api.h" + +/* + * the remaining includes will only be considered if of_codec_profile.h is + * included above by of_openfec_api.h => of_openfec_profile.h + */ +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + +#include "../../lib_common/linear_binary_codes_utils/of_linear_binary_code.h" + +#include "of_ldpc_staircase_api.h" +#include "of_ldpc_staircase.h" + + +#endif //OF_USE_LDPC_STAIRCASE_CODEC +#endif //OF_LDPC_INCLUDES diff --git a/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase.h b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase.h new file mode 100644 index 0000000..4fae05b --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase.h @@ -0,0 +1,328 @@ +/* $Id: of_ldpc_staircase.h 184 2014-07-15 09:42:57Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + +#ifndef OF_LDPC_STAIRCASE_H +#define OF_LDPC_STAIRCASE_H + +/** + * LDPC-Staircase stable codec specific control block structure. + */ +typedef struct of_ldpc_staircase_cb +{ + /****** of_linear_binary_code_cb part { *******************************/ + /****** of_cb part { **************************************************/ + of_codec_id_t codec_id; + of_codec_type_t codec_type; + UINT32 nb_source_symbols; /** k parameter (AKA code dimension). */ + UINT32 nb_repair_symbols; /** r = n - k parameter. */ + UINT32 encoding_symbol_length; /** symbol length. */ + /****** } of_cb part **************************************************/ + + UINT32 nb_total_symbols; /** n parameter (AKA code length). */ + + /* parity check matrix */ + of_mod2sparse *pchk_matrix; + + /** usage statistics for this codec instance. */ + of_symbol_stats_op_t *stats_xor; +#ifdef OF_DEBUG + of_symbols_stats_t *stats_symbols; +#endif + UINT32 nb_source_symbol_ready; // Number of source symbols ready + UINT32 nb_repair_symbol_ready; // Number of parity symbols ready + +#ifdef ML_DECODING /* { */ + UINT32 *index_rows; // Indirection index to access initial m_chekValues array + UINT32 *index_cols; // Indirection index to access initial symbol array + UINT32 remain_cols; // Nb of non empty remaining cols in the future simplified matrix + UINT32 remain_rows; // Nb of non empty remaining rows in the future simplified matrix + + of_mod2sparse *pchk_matrix_simplified; // Simplified Parity Check Matrix in sparse mode format + of_mod2sparse *original_pchkMatrix; + of_mod2sparse *pchk_matrix_gauss; // Parity Check matrix in sparse mode format. + UINT32 dec_step; // Current step in the Gauss decoding algorithm + UINT32 threshold_simplification; // threshold (number of symbols) above which we + // run the Gaussian Elimination algorithm +#endif /* } ML_DECODING */ + +#ifdef OF_USE_DECODER /* { */ + /** table of all check values, i.e. that contain the constant term of each equation. */ + void** tab_const_term_of_equ; + /** table containing the number of encoding symbols of each equation. */ + UINT16* tab_nb_enc_symbols_per_equ; + /** table containing the number of unknow symbols (i.e. neither received nor decoded + * at that time) of each equation. */ + UINT16* tab_nb_unknown_symbols; + /** table containing the number of equations in which a repair symbol is included. */ + UINT16* tab_nb_equ_for_repair; + + void** repair_symbols_values; + void** tmp_tab_symbols; + UINT16 nb_tmp_symbols; +#endif /* } OF_USE_DECODER */ + + void **encoding_symbols_tab; + + /** callbacks registered by the application. */ + void* (*decoded_source_symbol_callback) (void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi); /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi); /* encoding symbol ID in {0..k-1} */ + void* context_4_callback; + + /****** } of_linear_binary_code_cb part *******************************/ + + /** Maximum number of source symbols supported by this codec for practical reasons. */ + UINT32 max_nb_source_symbols; + /** Maximum number of encoding symbols supported by this codec for practical reasons. */ + UINT32 max_nb_encoding_symbols; + /** Seed used to build this code. */ + UINT32 prng_seed; + /** Target number or "1s" per column for H1 (see RFC5170). */ + UINT8 N1; + /** During H1 creation, have extra entries been added per row to make the row hamming weight at least two? */ + bool extra_entries_added_in_pchk; + /** ESI of first non decoded source symbol. Used by is_decoding_complete function. */ + UINT32 first_non_decoded; +} of_ldpc_staircase_cb_t; + + +/* + * Function prototypes. + */ +/** + * This function create the codec instance for the LDPC-SC codec. + * + * @fn of_status_t of_ldpc_staircase_create_codec_instance (of_ldpc_staircase_cb_t** of_cb) + * @brief create a LDPC-SC codec instance + * @param of_cb (IN/OUT) address of the pointer to a LDPC-SC codec control block. This pointer is updated + * by this function. + * In case of success, it points to a session structure allocated by the + * library. In case of failure it points to NULL. + * @return Error status. The ofcb pointer is updated according to the success return + * status. + */ +of_status_t of_ldpc_staircase_create_codec_instance (of_ldpc_staircase_cb_t** of_cb); + +/** + * This function releases all the internal resources used by this FEC codec instance. + * None of the source symbol buffers will be free'ed by this function, even those decoded by + * the library if any, regardless of whether a callback has been registered or not. It's the + * responsibility of the caller to free them. + * + * @fn of_status_t of_ldpc_staircase_release_codec_instance (of_ldpc_staircase_cb_t* ofcb) + * @brief release all resources used by the codec + * @param ofcb (IN) Pointer to the control block. + * @return Error status. + */ +of_status_t of_ldpc_staircase_release_codec_instance (of_ldpc_staircase_cb_t* ofcb); + +/** + * + * @fn of_status_t of_ldpc_staircase_set_fec_parameters (of_ldpc_staircase_cb_t* ofcb, of_ldpc_parameters_t* params) + * @brief set all the FEC codec parameters (e.g. k, n, or symbol size) + * @param ofcb (IN) Pointer to the control block. + * @param params (IN) pointer to a structure containing the FEC parameters associated to + * a specific FEC codec. + * @return Error status. + */ +of_status_t of_ldpc_staircase_set_fec_parameters (of_ldpc_staircase_cb_t* ofcb, + of_ldpc_parameters_t* params); + +/** + * @fn of_status_t of_ldpc_staircase_set_callback_functions (of_ldpc_staircase_cb_t *ofcb,void* (*decoded_source_symbol_callback) + * (void *context,UINT32 size,UINT32 esi), void* (*decoded_repair_symbol_callback) + * (void *context,UINT32 size,UINT32 esi),void* context_4_callback) + * @brief set various callbock functions (see header of_open_fec_api.h) + * @param ofcb (IN) Pointer to the session. + * + * @param decoded_source_symbol_callback + * (IN) Pointer to the function, within the application, that + * needs to be called each time a source symbol is decoded. + * If this callback is not initialized, the symbol is managed + * internally. + * + * @param decoded_repair_symbol_callback + * (IN) Pointer to the function, within the application, that + * needs to be called each time a repair symbol is decoded. + * If this callback is not initialized, the symbol is managed + * internally. + * + * @param context_4_callback (IN) Pointer to the application-specific context that will be + * passed to the callback function (if any). This context is not + * interpreted by this function. + * + * @return Completion status (LDPC_OK or LDPC_ERROR). + */ +of_status_t of_ldpc_staircase_set_callback_functions (of_ldpc_staircase_cb_t* ofcb, + void* (*decoded_source_symbol_callback) (void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* context_4_callback); + +#ifdef OF_USE_ENCODER +/** + * @fn of_status_t of_ldpc_staircase_build_repair_symbol (of_ldpc_staircase_cb_t* ofcb, void* encoding_symbols_tab[], UINT32 esi_of_symbol_to_build) + * @brief build a repair symbol (encoder only) + * @param ofcb (IN) Pointer to the session. + * @param encoding_symbols_tab (IN/OUT) table of source and repair symbols. + * The entry for the repair symbol to build can either point + * to a buffer allocated by the application, or let to NULL + * meaning that of_build_repair_symbol will allocate memory. + * @param esi_of_symbol_to_build + * (IN) encoding symbol ID of the repair symbol to build in + * {k..n-1} + * @return Error status. + */ +of_status_t of_ldpc_staircase_build_repair_symbol (of_ldpc_staircase_cb_t* ofcb, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build); +#endif //OF_USE_ENCODER + +#ifdef OF_USE_DECODER +/** + * @fn of_status_t of_ldpc_staircase_decode_with_new_symbol (of_ldpc_staircase_cb_t* ofcb, void* const new_symbol_buf, UINT32 new_symbol_esi) + * @brief (try to) decode with a newly received symbol + * @param ofcb (IN) Pointer to the session. + * @param new_symbol (IN) Pointer to the encoding symbol now available (i.e. a new + * symbol received by the application, or a decoded symbol in case + * of a recursive call). + * @param new_symbol_esi (IN) Encoding symbol ID of the newly symbol available, in {0..n-1}. + * @return Error status (NB: this function does not return OF_STATUS_FAILURE). + */ +of_status_t of_ldpc_staircase_decode_with_new_symbol (of_ldpc_staircase_cb_t* ofcb, + void* new_symbol, + UINT32 new_symbol_esi); + +/** + * @fn of_status_t of_ldpc_staircase_set_available_symbols (of_ldpc_staircase_cb_t* ofcb, void* const encoding_symbols_tab[]); + * @brief inform the decoder of all the available (received) symbols + * @param ofcb (IN) Pointer to the session. + * @param encoding_symbols_tab (IN) Pointer to the available encoding symbols table. To each + * available symbol the corresponding entry in the table must point + * to the associated buffer. Entries set to NULL are interpreted as + * corresponding to erased symbols. + * @return Error status. + */ +of_status_t of_ldpc_staircase_set_available_symbols (of_ldpc_staircase_cb_t* ofcb, + void* const encoding_symbols_tab[]); + +/** + * @fn of_status_t of_ldpc_staircase_finish_decoding (of_ldpc_staircase_cb_t* ofcb) + * @brief finish decoding with available symbols + * @param ofcb (IN) Pointer to the session. + * @return Error status. Returns OF_STATUS_FAILURE if decoding failed, or + * OF_STATUS_OK if decoding succeeded, or OF_STATUS_*_ERROR in case + * of (fatal) error. + */ +of_status_t of_ldpc_staircase_finish_decoding (of_ldpc_staircase_cb_t* ofcb); + +/** + * @fn bool of_ldpc_staircase_is_decoding_complete (of_ldpc_staircase_cb_t* ofcb) + * @brief check if decoding is finished + * @param ofcb (IN) Pointer to the session. + * @return Boolean. Warning, this is one of the very functions of the library that + * does not return an error status. + */ +bool of_ldpc_staircase_is_decoding_complete (of_ldpc_staircase_cb_t* ofcb); + +/** + * @fn of_status_t of_ldpc_staircase_get_source_symbols_tab (of_ldpc_staircase_cb_t* ofcb, void* source_symbols_tab[]) + * @brief get the table of available source symbols (after decoding) + * @param ofcb (IN) Pointer to the session. + * @param source_symbols_tab (IN/OUT) table, that will be filled by the library and returned + * to the application. + * @return Error status. + */ +of_status_t of_ldpc_staircase_get_source_symbols_tab (of_ldpc_staircase_cb_t* ofcb, + void* source_symbols_tab[]); + +/** + * @fn of_status_t of_ldpc_staircase_set_control_parameter (of_ldpc_staircase_cb_t* ofcb,UINT32 type,void* value,UINT32 length) + * @brief set a specific FEC parameter + * @param ofcb (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID specific. + * @param value (IN) Pointer to the value of the parameter. The type of the object pointed + * is FEC codec ID specific. + * @param length (IN) length of pointer value + * @return Error status. + */ +of_status_t of_ldpc_staircase_set_control_parameter(of_ldpc_staircase_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length); + +/** + * @fn of_status_t of_ldpc_staircase_get_control_parameter (of_ldpc_staircase_cb_t* ofcb, UINT32 type, void* value, UINT32 length) + * @brief get a specific FEC parameter + * @param ofcb (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID specific. + * @param value (IN/OUT) Pointer to the value of the parameter. The type of the object + * pointed is FEC codec ID specific. This function updates the value object + * accordingly. The application, who knows the FEC codec ID, is responsible + * to allocating the approriate object pointed by the value pointer. + * @param length (IN) length of pointer value + * @return Error status. + */ +of_status_t of_ldpc_staircase_get_control_parameter(of_ldpc_staircase_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length); + +/** + * @brief Create the LDPC-Staircase matrix as defined in RFC 5170. + * @param nb_rows (IN) number of rows, also equal to n-k. + * @param nb_cols (IN) number of columns, also equal to n. + * @param left_degree (IN) another name of the N1 parameter. + * @param seed (IN) seed to use for the PRNG. + * @param ofcb (IN/OUT) + * @return pointer to the parity check matrix that has just been allocated and initialized. + */ +of_mod2sparse* of_create_pchck_matrix_rfc5170_compliant (UINT32 nb_rows, + UINT32 nb_cols, + UINT32 left_degree, + UINT32 seed, + of_ldpc_staircase_cb_t *ofcb); + +#endif //OF_USE_DECODER + +#endif //OF_LDPC_STAIRCASE_H + +#endif /* #ifdef OF_USE_LDPC_STAIRCASE_CODEC */ diff --git a/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase_api.c b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase_api.c new file mode 100644 index 0000000..f50c620 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase_api.c @@ -0,0 +1,570 @@ +/* $Id: of_ldpc_staircase_api.c 186 2014-07-16 07:17:53Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "of_ldpc_includes.h" +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + + +of_status_t of_ldpc_staircase_create_codec_instance (of_ldpc_staircase_cb_t** of_cb) +{ + of_codec_type_t codec_type; /* temporary value */ + of_ldpc_staircase_cb_t *cb; + + OF_ENTER_FUNCTION + cb = (of_ldpc_staircase_cb_t*) of_realloc (*of_cb, sizeof (of_ldpc_staircase_cb_t)); + /* realloc does not initialize the additional buffer space, so do that manually, + * then re-initialize a few parameters */ + codec_type = cb->codec_type; + memset(cb, 0, sizeof(*cb)); + *of_cb = cb; + cb->codec_id = OF_CODEC_LDPC_STAIRCASE_STABLE; + cb->codec_type = codec_type; + cb->max_nb_source_symbols = OF_LDPC_STAIRCASE_MAX_NB_SOURCE_SYMBOLS_DEFAULT; /* init it immediately... */ + cb->max_nb_encoding_symbols = OF_LDPC_STAIRCASE_MAX_NB_ENCODING_SYMBOLS_DEFAULT; /* init it immediately... */ + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_ldpc_staircase_release_codec_instance (of_ldpc_staircase_cb_t* ofcb) +{ + OF_ENTER_FUNCTION + UINT32 i; + if (ofcb->pchk_matrix != NULL) + { + of_mod2sparse_free(ofcb->pchk_matrix); + of_free (ofcb->pchk_matrix); + ofcb->pchk_matrix = NULL; + } + if (ofcb->encoding_symbols_tab != NULL) + { + /* do not try to free source buffers, it's the responsibility of the application + * using this library to free everything. Only try to free repair symbols. */ + for (i = ofcb->nb_source_symbols; i < ofcb->nb_total_symbols; i++) + { + if (ofcb->encoding_symbols_tab[i] != NULL) + { + of_free (ofcb->encoding_symbols_tab[i]); + ofcb->encoding_symbols_tab[i] = NULL; + } + } + of_free (ofcb->encoding_symbols_tab); + ofcb->encoding_symbols_tab = NULL; + } +#ifdef OF_USE_DECODER + if (ofcb->codec_type & OF_DECODER) + { + if (ofcb->tmp_tab_symbols != NULL) + { + of_free(ofcb->tmp_tab_symbols); + ofcb->tmp_tab_symbols = NULL; + } + if (ofcb->tab_nb_enc_symbols_per_equ != NULL) + { + of_free (ofcb->tab_nb_enc_symbols_per_equ); + ofcb->tab_nb_enc_symbols_per_equ = NULL; + } + if (ofcb->tab_nb_equ_for_repair != NULL) + { + of_free (ofcb->tab_nb_equ_for_repair); + ofcb->tab_nb_equ_for_repair = NULL; + } + if (ofcb->tab_nb_unknown_symbols != NULL) + { + of_free (ofcb->tab_nb_unknown_symbols); + ofcb->tab_nb_unknown_symbols = NULL; + } + if (ofcb->tab_const_term_of_equ != NULL) + { + for (i = 0; i < ofcb->nb_repair_symbols; i++) + { + if (ofcb->tab_const_term_of_equ[i] != NULL) + { + of_free (ofcb->tab_const_term_of_equ[i]); + ofcb->tab_const_term_of_equ[i] = NULL; + } + } + of_free(ofcb->tab_const_term_of_equ); + } + of_free(ofcb->tmp_tab_symbols); + ofcb->tmp_tab_symbols=NULL; + } +#endif + +#ifdef OF_LDPC_STAIRCASE_ML_DECODING + if (ofcb->index_rows != NULL) + { + of_free (ofcb->index_rows); + ofcb->index_rows = NULL; + } + if (ofcb->index_cols != NULL) + { + of_free (ofcb->index_cols); + ofcb->index_cols = NULL; + } + if (ofcb->pchk_matrix_simplified != NULL) + { + of_mod2sparse_free (ofcb->pchk_matrix_simplified); + of_free(ofcb->pchk_matrix_simplified); + ofcb->pchk_matrix_simplified = NULL; + } + if (ofcb->original_pchkMatrix != NULL) + { + of_mod2sparse_free (ofcb->original_pchkMatrix); + ofcb->original_pchkMatrix = NULL; + } + if (ofcb->pchk_matrix_gauss != NULL) + { + of_mod2sparse_free (ofcb->pchk_matrix_gauss); + ofcb->pchk_matrix_gauss = NULL; + } +#endif +#ifdef OF_DEBUG + if (ofcb->stats_xor != NULL) { + of_print_xor_symbols_statistics(ofcb->stats_xor); + of_free(ofcb->stats_xor); + } + if (ofcb->stats_symbols != NULL) { + of_free(ofcb->stats_symbols); + } +#endif + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_ldpc_staircase_set_fec_parameters (of_ldpc_staircase_cb_t* ofcb, + of_ldpc_parameters_t* params) +{ + of_mod2entry *e; + UINT32 row; + UINT32 seq; + + OF_ENTER_FUNCTION + +#ifdef OF_DEBUG + ofcb->stats_xor = of_calloc(1, sizeof(of_symbol_stats_op_t)); + ofcb->stats_symbols = of_calloc(1, sizeof(of_symbols_stats_t)); +#endif + if (params->N1 < 3) + { + OF_PRINT_ERROR(("of_ldpc_staircase_set_fec_parameters: invalid N1 value (%d), must be at least equal to 3.\n", + params->N1)) + goto error; + } + if ((ofcb->nb_source_symbols = params->nb_source_symbols) > ofcb->max_nb_source_symbols) + { + OF_PRINT_ERROR(("of_ldpc_staircase_set_fec_parameters: ERROR, invalid nb_source_symbols parameter (got %d, maximum is %d)\n", + ofcb->nb_source_symbols, ofcb->max_nb_source_symbols)); + goto error; + } + if ((ofcb->nb_repair_symbols = params->nb_repair_symbols) > ofcb->max_nb_encoding_symbols) + { + /* this test is needed because if the number of repair symbols is + * erroneously < 0, because we are using UINT32, this is transformed + * into a very large integer, which, when added to k, wraps once again + * and the test on nb_total_symbols returns true... */ + OF_PRINT_ERROR(("of_ldpc_staircase_set_fec_parameters: ERROR, invalid number of repair symbols (got %d, maximum number of encoding symbols is %d)\n", + ofcb->nb_repair_symbols, ofcb->max_nb_encoding_symbols)); + goto error; + } + ofcb->nb_total_symbols = ofcb->nb_source_symbols + ofcb->nb_repair_symbols; + if (ofcb->nb_total_symbols > ofcb->max_nb_encoding_symbols) + { + OF_PRINT_ERROR(("of_ldpc_staircase_set_fec_parameters: ERROR, invalid number of encoding symbols (got %d, maximum is %d)\n", + ofcb->nb_total_symbols, ofcb->max_nb_encoding_symbols)); + goto error; + } + ofcb->encoding_symbol_length = params->encoding_symbol_length; + ofcb->prng_seed = params->prng_seed; + ofcb->N1 = params->N1; + OF_TRACE_LVL (1, ("%s: k=%u, n-k=%u, n=%u, symbol_length=%u, PRNG seed=%u, N1=%u\n", __FUNCTION__, + ofcb->nb_source_symbols, ofcb->nb_repair_symbols, ofcb->nb_total_symbols, + ofcb->encoding_symbol_length, ofcb->prng_seed, ofcb->N1)) + /* it's now time to create the parity check matrix! */ + ofcb->pchk_matrix = of_create_pchck_matrix_rfc5170_compliant + (ofcb->nb_repair_symbols, + ofcb->nb_total_symbols, + ofcb->N1, + ofcb->prng_seed, + ofcb); + if (ofcb->pchk_matrix == NULL) + { + OF_PRINT_ERROR(("of_ldpc_staircase_set_fec_parameters : ERROR, parity check matrix can't be created with this parameters..\n")) + goto error; + } +#ifdef IL_SUPPORT + /* print the matrix using the DevIL library */ + of_mod2sparse_print_bitmap(ofcb->pchk_matrix); +#else + //of_mod2sparse_matrix_stats(stdout,ofcb->pchk_matrix,ofcb->nb_source_symbols, ofcb->nb_repair_symbols); +#endif +//#define PRINT_LDGM_VARIANT /* enable this constant to get a trace of the identity version of H */ +#if defined(OF_DEBUG) && defined(PRINT_LDGM_VARIANT) && defined(IL_SUPPORT) + { + /* + * calculate and plot the identity variant, H_id, where the staircase is replaced by an identity. + * This is only for curiosity/research purposes. DO NOT use it otherwise. + */ + of_mod2dense *dm = NULL; + + dm = of_mod2dense_allocate(ofcb->nb_repair_symbols, ofcb->nb_total_symbols, NULL); + of_mod2sparse_to_dense(ofcb->pchk_matrix, dm); + for (row = 0; row < ofcb->nb_repair_symbols - 1; row++) + { + of_mod2dense_xor_rows(dm, row, row + 1); + } + of_mod2dense_print_bitmap(dm); + of_mod2dense_density(dm); + of_mod2dense_free(dm, NULL); + } +#endif + + if ((ofcb->encoding_symbols_tab = (void**) of_calloc (ofcb->nb_total_symbols, sizeof (void*))) == NULL) { + goto no_mem; + } +#ifdef OF_USE_DECODER + if (ofcb->codec_type & OF_DECODER) + { + ofcb->tab_nb_unknown_symbols = (UINT16*) + of_calloc (ofcb->nb_repair_symbols, sizeof (UINT16)); + ofcb->tab_const_term_of_equ = (void**) + of_calloc (ofcb->nb_repair_symbols, sizeof (void*)); + ofcb->tab_nb_equ_for_repair = (UINT16*) + of_calloc (ofcb->nb_repair_symbols, sizeof (UINT16)); + ofcb->tab_nb_enc_symbols_per_equ = (UINT16*) + of_calloc (ofcb->nb_repair_symbols, sizeof (UINT16)); + if (ofcb->tab_nb_unknown_symbols == NULL || ofcb->tab_const_term_of_equ == NULL || + ofcb->tab_nb_equ_for_repair == NULL || ofcb->tab_nb_enc_symbols_per_equ == NULL) { + goto no_mem; + } + // and update the various tables now + for (row = 0; row < ofcb->nb_repair_symbols; row++) + { + for (e = of_mod2sparse_first_in_row (ofcb->pchk_matrix, row); + !of_mod2sparse_at_end (e); + e = of_mod2sparse_next_in_row (e)) + { + ofcb->tab_nb_enc_symbols_per_equ[row]++; + ofcb->tab_nb_unknown_symbols[row]++; + } + } + for (seq = ofcb->nb_source_symbols; seq < (ofcb->nb_total_symbols); seq++) + { + for (e = of_mod2sparse_first_in_col (ofcb->pchk_matrix, of_get_symbol_col ((of_cb_t*)ofcb, seq)); + !of_mod2sparse_at_end (e); + e = of_mod2sparse_next_in_col (e)) + { + ofcb->tab_nb_equ_for_repair[seq - ofcb->nb_source_symbols]++; + } + } + ofcb->tmp_tab_symbols = (void**)of_malloc(sizeof(void*)*ofcb->nb_total_symbols); + } +#endif //OF_USE_DECODER + ofcb->nb_source_symbol_ready = 0; // Number of source symbols ready + ofcb->nb_repair_symbol_ready = 0; // Number of parity symbols ready + //ofcb->nb_non_dup_symbols_recvd = 0;// Number of non-duplicated symbols received +#ifdef OF_LDPC_STAIRCASE_ML_DECODING + ofcb->index_rows = NULL; // Indirection index to access initial m_chekValues array + ofcb->index_cols = NULL; // Indirection index to access initial symbol array + ofcb->remain_cols = 0; // Nb of non empty remaining cols in the future simplified matrix + ofcb->remain_rows = 0; // Nb of non empty remaining rows in the future simplified matrix + ofcb->pchk_matrix_simplified = NULL; // Simplified Parity Check Matrix in sparse mode format + ofcb->original_pchkMatrix = NULL; + ofcb->pchk_matrix_gauss = NULL; // Parity Check matrix in sparse mode format. This matrix + // is also used as a generator matrix in LDGM-* modes + ofcb->dec_step = 0; // Current step in the Gauss Elimination algorithm + ofcb->threshold_simplification = 0; // threshold (number of symbols) above which we + // run the Gauss Elimination algorithm +#endif +#ifdef OF_USE_DECODER + /* + * with LDPC-Staircase, if N1 is even, the last repair symbol is often null (if the code rate + * is above a certain threshold), so pretend we received it since we already know its value. + */ + if (ofcb->codec_type & OF_DECODER) + { + bool is_null; /* is last repair symbol null? */ + + if (of_ldpc_staircase_get_control_parameter(ofcb, OF_CRTL_LDPC_STAIRCASE_IS_LAST_SYMBOL_NULL, + (void*)&is_null, sizeof(is_null)) != OF_STATUS_OK) { + OF_PRINT_ERROR(("%s: ERROR: of_ldpc_staircase_get_control_parameter() failed\n", __FUNCTION__)) + goto error; + } + if (is_null) + { + /* + * since the last repair symbol is known to be null, pretent we received it. + */ + void *null_symbol; /* that's the null repair symbol */ + + if ((null_symbol = of_calloc(1, ofcb->encoding_symbol_length)) == NULL) + { + goto no_mem; + } + OF_TRACE_LVL(1, ("%s: last repair is null, pretend we received it\n", __FUNCTION__)) + if (of_ldpc_staircase_decode_with_new_symbol (ofcb, null_symbol, ofcb->nb_total_symbols - 1) + != OF_STATUS_OK) + { + OF_PRINT_ERROR(("%s: ERROR: of_ldpc_staircase_decode_with_new_symbol() failed\n", __FUNCTION__)) + goto error; + } + } + } +#endif //OF_USE_DECODER + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +no_mem: + OF_PRINT_ERROR(("out of memory\n")); +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + + +of_status_t of_ldpc_staircase_set_callback_functions (of_ldpc_staircase_cb_t* ofcb, + void* (*decoded_source_symbol_callback) (void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi), /* encoding symbol ID in {k..n-1} */ + void* context_4_callback) +{ + OF_ENTER_FUNCTION + ofcb->decoded_source_symbol_callback = decoded_source_symbol_callback; + ofcb->decoded_repair_symbol_callback = decoded_repair_symbol_callback; + ofcb->context_4_callback = context_4_callback; + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +#ifdef OF_USE_ENCODER + +of_status_t of_ldpc_staircase_build_repair_symbol (of_ldpc_staircase_cb_t* ofcb, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build) +{ + of_mod2entry *e; + UINT32 col_to_build; + UINT32 esi; + void *to_add_buf; + void *parity_symbol; + OF_ENTER_FUNCTION + if (esi_of_symbol_to_build < ofcb->nb_source_symbols || esi_of_symbol_to_build >= ofcb->nb_total_symbols) + { + OF_PRINT_ERROR(("of_ldpc_staircase_build_repair_symbol: Error, bad esi of encoding symbol (%d)\n", esi_of_symbol_to_build)) + goto error; + } + parity_symbol = encoding_symbols_tab[esi_of_symbol_to_build]; + memset (parity_symbol, 0, ofcb->encoding_symbol_length); + col_to_build = of_get_symbol_col ((of_cb_t*)ofcb, esi_of_symbol_to_build); + e = of_mod2sparse_first_in_row (ofcb->pchk_matrix, col_to_build); + while (!of_mod2sparse_at_end (e)) + { + // paritySymbol_index in {0.. n-k-1} range, so this test is ok + if (e->col != col_to_build) + { + // don't add paritySymbol to itself + esi = of_get_symbol_esi ((of_cb_t*)ofcb, e->col); + to_add_buf = (void*) encoding_symbols_tab[esi]; + if (to_add_buf == NULL) + { + OF_PRINT_ERROR(("symbol %d is not allocated\n", esi)); + goto error; + } +#ifdef OF_DEBUG + of_add_to_symbol (parity_symbol, to_add_buf, ofcb->encoding_symbol_length,&(ofcb->stats_xor->nb_xor_for_IT)); +#else + of_add_to_symbol (parity_symbol, to_add_buf, ofcb->encoding_symbol_length); +#endif + } + e = of_mod2sparse_next_in_row (e); + } + OF_TRACE_LVL (1, ("%s: repair symbol (esi=%d) built\n", __FUNCTION__, esi_of_symbol_to_build)) + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + +#endif //OF_USE_ENCODER + + +#ifdef OF_USE_DECODER + +of_status_t of_ldpc_staircase_decode_with_new_symbol (of_ldpc_staircase_cb_t* ofcb, + void* new_symbol, + UINT32 new_symbol_esi) +{ + OF_ENTER_FUNCTION + return of_linear_binary_code_decode_with_new_symbol((of_linear_binary_code_cb_t*)ofcb, new_symbol, new_symbol_esi); +} + + +of_status_t of_ldpc_staircase_set_available_symbols (of_ldpc_staircase_cb_t* ofcb, + void* const encoding_symbols_tab[]) +{ + UINT32 i; + + OF_ENTER_FUNCTION + for (i = 0; i < ofcb->nb_total_symbols; i++) + { + if (encoding_symbols_tab[i] == NULL) + { + continue; + } + /* use the decode_with_new_symbol function */ + of_linear_binary_code_decode_with_new_symbol((of_linear_binary_code_cb_t*)ofcb, encoding_symbols_tab[i], i); + /* NB: this approach is a little bit sub-optimal with LDPC codes, as symbols are submit for IT decoding in sequence. + * We should consider randomizing this order. */ + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_ldpc_staircase_finish_decoding (of_ldpc_staircase_cb_t* ofcb) +{ + OF_ENTER_FUNCTION +#ifdef OF_LDPC_STAIRCASE_ML_DECODING + return of_linear_binary_code_finish_decoding_with_ml ((of_linear_binary_code_cb_t*)ofcb); +#else + return OF_STATUS_ERROR; +#endif +} + + +bool of_ldpc_staircase_is_decoding_complete (of_ldpc_staircase_cb_t* ofcb) +{ + for (; ofcb->first_non_decoded < ofcb->nb_source_symbols; ofcb->first_non_decoded++) + { + if (ofcb->encoding_symbols_tab[ofcb->first_non_decoded] == NULL) + { + OF_TRACE_LVL (1, ("decoding not complete (%u source symbols ready, %u expected)\n", + ofcb->nb_source_symbol_ready, ofcb->nb_source_symbols)) + //ASSERT(ofcb->nb_source_symbol_ready < ofcb->nb_source_symbols); + return false; + } + } + OF_TRACE_LVL (1, ("decoding is complete\n")) + //ASSERT(ofcb->nb_source_symbol_ready == ofcb->nb_source_symbols); + return true; +} + + +of_status_t of_ldpc_staircase_get_source_symbols_tab (of_ldpc_staircase_cb_t* ofcb, + void* source_symbols_tab[]) +{ + OF_ENTER_FUNCTION + /* copy the internal table containing the pointers to all source symbols into the table provided by the caller */ + memcpy (source_symbols_tab, ofcb->encoding_symbols_tab, sizeof (void *) * ofcb->nb_source_symbols); + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +#endif //OF_USE_DECODER + +of_status_t of_ldpc_staircase_set_control_parameter (of_ldpc_staircase_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length) +{ + OF_PRINT_ERROR(("of_ldpc_staircase_set_control_parameter: ERROR, not implemented...\n")) + return OF_STATUS_ERROR; +} + + +of_status_t of_ldpc_staircase_get_control_parameter (of_ldpc_staircase_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length) +{ + OF_ENTER_FUNCTION + switch (type) { + case OF_CTRL_GET_MAX_K: + if (value == NULL || length != sizeof(UINT32)) { + OF_PRINT_ERROR(("%s: OF_CTRL_GET_MAX_K ERROR: null value or bad length (got %d, expected %ld)\n", + __FUNCTION__, length, sizeof(UINT32))) + goto error; + } + *(UINT32*)value = ofcb->max_nb_source_symbols; + OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_K (%d)\n", __FUNCTION__, *(UINT32*)value)) + break; + + case OF_CTRL_GET_MAX_N: + if (value == NULL || length != sizeof(UINT32)) { + OF_PRINT_ERROR(("%s: OF_CTRL_GET_MAX_N ERROR: null value or bad length (got %d, expected %ld)\n", + __FUNCTION__, length, sizeof(UINT32))) + goto error; + } + *(UINT32*)value = ofcb->max_nb_encoding_symbols; + OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_N (%d)\n", __FUNCTION__, *(UINT32*)value)) + break; + + case OF_CRTL_LDPC_STAIRCASE_IS_LAST_SYMBOL_NULL: + if (ofcb->extra_entries_added_in_pchk == true) + { + /* the parity check matrix does not have exactly N1 "1s" per column, so the + * last repair symbol will not be NULL in general. */ + *(bool*)value = false; + OF_TRACE_LVL(1, ("%s: OF_CRTL_LDPC_STAIRCASE_IS_LAST_SYMBOL_NULL (false) (extra entries added in pchk)\n", __FUNCTION__)) + } + else + { + /* there are exacly N1 "1s" per column, so if this number if even, the last + * repair symbol is known to be always NULL, no matter the value of the source + * symbols. */ + *(bool*)value = ((ofcb->N1 & 0x1) == 0) ? true : false; + OF_TRACE_LVL(1, ("%s: OF_CRTL_LDPC_STAIRCASE_IS_LAST_SYMBOL_NULL (%d)\n", __FUNCTION__, *(bool*)value)) + } + break; + + default: + OF_PRINT_ERROR(("%s: unknown type (%d)\n", __FUNCTION__, type)) + goto error; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + +#endif /* #ifdef OF_USE_LDPC_STAIRCASE_CODEC */ diff --git a/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase_api.h b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase_api.h new file mode 100644 index 0000000..bb427ac --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase_api.h @@ -0,0 +1,82 @@ +/* $Id: of_ldpc_staircase_api.h 72 2012-04-13 13:27:26Z detchart $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + +#ifndef OF_CODEC_STABLE_LDPC_STAIRCASE_API +#define OF_CODEC_STABLE_LDPC_STAIRCASE_API + + +#include "../../lib_common/of_types.h" + +/** + * @struct of_ldpc_parameters_t + * @brief LDPC-Staircase stable codec specific FEC parameter structure. + * + * This structure contains the pieces of information required to initialize a codec instance, + * using the of_set_fec_parameters() function. + */ +typedef struct of_ldpc_parameters +{ + UINT32 nb_source_symbols; /* must be 1st item */ + UINT32 nb_repair_symbols; /* must be 2nd item */ + UINT32 encoding_symbol_length; /* must be 3rd item */ + /* + * FEC codec id specific attributes follow... + */ + INT32 prng_seed; + UINT8 N1; +} of_ldpc_parameters_t; + + +/** + * Control parameters for of_set_control_parameter()/of_get_control_parameter() functions: + * - range {0 .. 1023} inclusive are for generic parameters; + * - range {1024 .. above} inclusive are for code/codec specific parameters (and different + * codecs can re-use the same value); + * The "void * value" type depends on the type. + */ + +/** + * Ask the OF library if the last repair symbol of an LDPC-Staircase code is equal to zero + * or not. This is used for various optimizations (e.g. it's useless to transmit a symbol + * that is known to be null). This call returns 1 if the property is true (i.e. the last + * repair symbol is actually NULL), 0 otherwise. + * Argument: bool + */ +#define OF_CRTL_LDPC_STAIRCASE_IS_LAST_SYMBOL_NULL 1024 + + +#endif /* OF_CODEC_STABLE_LDPC_SCSTAIRCASE_API */ + +#endif /*#ifdef OF_USE_LDPC_STAIRCASE_CODEC */ diff --git a/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase_pchk.c b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase_pchk.c new file mode 100644 index 0000000..7e3c3ec --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/ldpc_staircase/of_ldpc_staircase_pchk.c @@ -0,0 +1,181 @@ +/* $Id: of_ldpc_staircase_pchk.c 184 2014-07-15 09:42:57Z roca $ */ +/* + * The contents of this directory and its sub-directories are + * Copyright (c) 1995-2003 by Radford M. Neal + * + * Permission is granted for anyone to copy, use, modify, or distribute these + * programs and accompanying documents for any purpose, provided this copyright + * notice is retained and prominently displayed, along with a note saying + * that the original programs are available from Radford Neal's web page, and + * note is made of any changes made to these programs. These programs and + * documents are distributed without any warranty, express or implied. As the + * programs were written for research purposes only, they have not been tested + * to the degree that would be advisable in any important application. All use + * of these programs is entirely at the user's own risk. + */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2011 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "of_ldpc_includes.h" +#ifdef OF_USE_LDPC_STAIRCASE_CODEC + + +/* RFC5170 compliant fonction. DO NOT MODIFY */ +of_mod2sparse* of_create_pchck_matrix_rfc5170_compliant (UINT32 nb_rows, + UINT32 nb_cols, + UINT32 left_degree, + UINT32 seed, + of_ldpc_staircase_cb_t *ofcb) +{ + OF_ENTER_FUNCTION + of_mod2entry *e; + UINT32 added, uneven; + INT32 i, j, k; + INT32 t; /* left limit within the list of possible choices u[] */ + UINT32 *u; /* table used to have a homogeneous 1 distrib. */ + of_mod2sparse *pchkMatrix = NULL; + UINT32 skipCols = 0; // avoid warning + UINT32 nbDataCols = 0; // avoid warning + + skipCols = nb_rows; + nbDataCols = nb_cols - skipCols; + /* a few sanity checks... */ + if (left_degree > nb_rows) + { + OF_PRINT_ERROR(("number of 1s per column (i.e. N1=%d parameter) is greater than total number of rows (i.e. n-k=%d)\n", + left_degree, nb_rows)); + OF_EXIT_FUNCTION + return NULL; + } + of_rfc5170_srand (seed); + pchkMatrix = of_mod2sparse_allocate (nb_rows, nb_cols); + /* create the initial version of the parity check matrix. */ + /* evenboth make method only */ + u = (UINT32*) of_calloc (left_degree * nbDataCols, sizeof * u); + /* initialize a list of possible choices to guarantee a homogeneous "1" distribution */ + for (k = left_degree * nbDataCols - 1; k >= 0; k--) + { + u[k] = k % nb_rows; + } + uneven = 0; + t = 0; /* left limit within the list of possible choices, u[] */ + for (j = skipCols; j < nb_cols; j++) + { + /* for each source symbol column */ + for (k = 0; k < left_degree; k++) + { + /* add left_degree "1s" */ + /* check that valid available choices remain */ + for (i = t; i < left_degree * nbDataCols && of_mod2sparse_find (pchkMatrix, u[i], j); i++) + ; + + if (i < left_degree * nbDataCols) + { + /* choose one index within the list of possible choices */ + do + { + i = t + of_rfc5170_rand (left_degree * nbDataCols - t); + } + while (of_mod2sparse_find (pchkMatrix, u[i], j)); + of_mod2sparse_insert (pchkMatrix, u[i], j); + /* replace with u[t] which has never been chosen */ + u[i] = u[t]; + t++; + } + else + { + /* no choice left, choose one randomly. + * This happens if we're not lucky and if in the remaining possible + * choices, for instance for the last source symbol, the same row + * appears several times. */ + uneven += 1; + do + { + i = of_rfc5170_rand (nb_rows); + } + while (of_mod2sparse_find (pchkMatrix, i, j)); + of_mod2sparse_insert (pchkMatrix, i, j); + } + } + } + if (uneven > 0 && of_verbosity >= 1) + { + OF_PRINT_LVL(1, ("%s: Had to place %d checks in rows unevenly\n", __FUNCTION__, uneven)) + } + of_free (u); /* VR: added */ + /* Add extra bits to avoid rows with less than two checks. */ + added = 0; + for (i = 0; i < nb_rows; i++) + { + e = of_mod2sparse_first_in_row (pchkMatrix, i); + if (of_mod2sparse_at_end (e)) + { + j = (of_rfc5170_rand (nbDataCols)) + skipCols; + e = of_mod2sparse_insert (pchkMatrix, i, j); + added ++; + } + e = of_mod2sparse_first_in_row (pchkMatrix, i); + if (of_mod2sparse_at_end (of_mod2sparse_next_in_row (e)) && nbDataCols > 1) + { + do + { + j = (of_rfc5170_rand (nbDataCols)) + skipCols; + } + while (j == of_mod2sparse_col (e)); + of_mod2sparse_insert (pchkMatrix, i, j); + added ++; + } + } + if (added >= 1) + { + ofcb->extra_entries_added_in_pchk = 1; + OF_TRACE_LVL(1,("%s: Added %d extra bit-checks to make row Hamming weight at least two\n", __FUNCTION__, added)); + } + else + { + ofcb->extra_entries_added_in_pchk = 0; /* nothing added, there are exactly N1 entries per column. */ + } + /* finally, create the staircase */ + of_mod2sparse_insert (pchkMatrix, 0, 0); /* 1st row */ + for (i = 1; i < nb_rows; i++) + { + /* for all other rows */ + /* identity */ + of_mod2sparse_insert (pchkMatrix, i, i); + /* staircase */ + of_mod2sparse_insert (pchkMatrix, i, i - 1); + } + OF_EXIT_FUNCTION + return pchkMatrix; +} + +#endif /* #ifdef OF_USE_LDPC_STAIRCASE_CODEC */ diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_codec_profile.h b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_codec_profile.h new file mode 100644 index 0000000..e56bf63 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_codec_profile.h @@ -0,0 +1,48 @@ +/* $Id: of_codec_profile.h 72 2012-04-13 13:27:26Z detchart $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + + + +/****** GENERAL SETUP OPTIONS; EDIT AS APPROPRIATE ****************************/ + +#define OF_USE_REED_SOLOMON_CODEC + +/** + * Default maximum number of source and encoding symbols for this codec. + * This value depends in particular on the Finite Field size used (here GF(2^8)). + * To this limit, codec implementation details might add other limits (e.g. if + * the ESI values are stored in UINT16 instead of UINT32...). + */ +#define OF_REED_SOLOMON_MAX_NB_SOURCE_SYMBOLS_DEFAULT 255 +#define OF_REED_SOLOMON_MAX_NB_ENCODING_SYMBOLS_DEFAULT 255 + diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8.c b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8.c new file mode 100755 index 0000000..de24ed0 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8.c @@ -0,0 +1,1112 @@ +/* $Id: of_reed-solomon_gf_2_8.c 2 2011-03-02 11:01:37Z detchart $ */ +/* + * fec.c -- forward error correction based on Vandermonde matrices + * 980624 + * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it) + * + * Portions derived from code by Phil Karn (karn@ka9q.ampr.org), + * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari + * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ +#include "of_reed-solomon_gf_2_8_includes.h" + +#ifdef OF_USE_REED_SOLOMON_CODEC + +/* VR: added for WIN CE support */ +#ifdef _WIN32_WCE +#define bzero(to,sz) memset((to), 0, (sz)) + +#define bcmp(a,b,sz) memcmp((a), (b), (sz)) +#endif /* WIN32_WCE */ + +/* + * compatibility stuff + */ +#if defined(WIN32) /* but also for others, e.g. sun... */ +#define NEED_BCOPY +#define bcmp(a,b,n) memcmp(a,b,n) +#endif + +#ifdef NEED_BCOPY +#define bcopy(s, d, siz) memcpy((d), (s), (siz)) +#define bzero(d, siz) memset((d), '\0', (siz)) +#endif + +#ifndef UINT32 +#define UINT32 unsigned long +#endif + +/* + * stuff used for testing purposes only + */ + +#ifdef TICK /* VR: avoid a warning under Solaris */ +#undef TICK +#endif + +//#define TEST +#ifdef TEST /* { */ + +#define DEB(x) x +#define DDB(x) x +#define OF_RS_DEBUG 4 /* minimal debugging */ +#if defined(WIN32) +#include +struct timeval +{ + unsigned long ticks; +}; +#define gettimeofday(x, dummy) { (x)->ticks = clock() ; } +#define DIFF_T(a,b) (1+ 1000000*(a.ticks - b.ticks) / CLOCKS_PER_SEC ) +typedef unsigned long UINT32 ; +typedef unsigned short u_short ; +#else /* typically, unix systems */ +#include +#define DIFF_T(a,b) \ + (1+ 1000000*(a.tv_sec - b.tv_sec) + (a.tv_usec - b.tv_usec) ) +#endif + +#define TICK(t) \ + {struct timeval x ; \ + gettimeofday(&x, NULL) ; \ + t = x.tv_usec + 1000000* (x.tv_sec & 0xff ) ; \ + } +#define TOCK(t) \ + { UINT32 t1 ; TICK(t1) ; \ + if (t1 < t) t = 256000000 + t1 - t ; \ + else t = t1 - t ; \ + if (t == 0) t = 1 ;} + +UINT32 ticks[10]; /* vars for timekeeping */ + +#else /* } { */ + +#define DEB(x) +#define DDB(x) +#define TICK(x) +#define TOCK(x) + +#endif /* } TEST */ + + +/* + * You should not need to change anything beyond this point. + * The first part of the file implements linear algebra in GF. + * + * gf is the type used to store an element of the Galois Field. + * Must constain at least GF_BITS bits. + * + * Note: unsigned char will work up to GF(256) but int seems to run + * faster on the Pentium. We use int whenever have to deal with an + * index, since they are generally faster. + */ +#if (GF_BITS < 2 && GF_BITS >16) +#error "GF_BITS must be 2 .. 16" +#endif +/*#if (GF_BITS <= 8) +typedef unsigned char gf; +#else +typedef unsigned short gf; +#endif*/ + +#define GF_SIZE ((1 << GF_BITS) - 1) /* powers of \alpha */ + +/* + * Primitive polynomials - see Lin & Costello, Appendix A, + * and Lee & Messerschmitt, p. 453. + */ +static const char *of_rs_allPp[] = /* GF_BITS polynomial */ +{ + NULL, /* 0 no code */ + NULL, /* 1 no code */ + "111", /* 2 1+x+x^2 */ + "1101", /* 3 1+x+x^3 */ + "11001", /* 4 1+x+x^4 */ + "101001", /* 5 1+x^2+x^5 */ + "1100001", /* 6 1+x+x^6 */ + "10010001", /* 7 1 + x^3 + x^7 */ + "101110001", /* 8 1+x^2+x^3+x^4+x^8 */ + "1000100001", /* 9 1+x^4+x^9 */ + "10010000001", /* 10 1+x^3+x^10 */ + "101000000001", /* 11 1+x^2+x^11 */ + "1100101000001", /* 12 1+x+x^4+x^6+x^12 */ + "11011000000001", /* 13 1+x+x^3+x^4+x^13 */ + "110000100010001", /* 14 1+x+x^6+x^10+x^14 */ + "1100000000000001", /* 15 1+x+x^15 */ + "11010000000010001" /* 16 1+x+x^3+x^12+x^16 */ +}; + + +/* + * To speed up computations, we have tables for logarithm, exponent + * and inverse of a number. If GF_BITS <= 8, we use a table for + * multiplication as well (it takes 64K, no big deal even on a PDA, + * especially because it can be pre-initialized an put into a ROM!), + * otherwhise we use a table of logarithms. + * In any case the macro of_gf_mul(x,y) takes care of multiplications. + */ + +static gf of_rs_gf_exp[2*GF_SIZE]; /* index->poly form conversion table */ +static int of_rs_gf_log[GF_SIZE + 1]; /* Poly->index form conversion table */ +static gf of_rs_inverse[GF_SIZE+1]; /* inverse of field elem. */ +/* inv[\alpha**i]=\alpha**(GF_SIZE-i-1) */ + +/* + * modnn(x) computes x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1, + * without a slow divide. + */ +static gf +of_modnn (INT32 x) +{ + while (x >= GF_SIZE) + { + x -= GF_SIZE; + x = (x >> GF_BITS) + (x & GF_SIZE); + } + return x; +} + +#define SWAP(a,b,t) {t tmp; tmp=a; a=b; b=tmp;} + +/* + * of_gf_mul(x,y) multiplies two numbers. If GF_BITS<=8, it is much + * faster to use a multiplication table. + * + * USE_GF_MULC, GF_MULC0(c) and GF_ADDMULC(x) can be used when multiplying + * many numbers by the same constant. In this case the first + * call sets the constant, and others perform the multiplications. + * A value related to the multiplication is held in a local variable + * declared with USE_GF_MULC . See usage in addmul1(). + */ +#if (GF_BITS <= 8) +static gf of_gf_mul_table[GF_SIZE + 1][GF_SIZE + 1]; + +#define of_gf_mul(x,y) of_gf_mul_table[x][y] + +#define USE_GF_MULC register gf * __gf_mulc_ +#define GF_MULC0(c) __gf_mulc_ = of_gf_mul_table[c] +#define GF_ADDMULC(dst, x) dst ^= __gf_mulc_[x] +#if GF_BITS <8 +#define GF_ADDMULC_COMPACT(dst,x) { gf tmp=x>>4;gf _dst1=dst>>4;_dst1^=__gf_mulc_[tmp]; tmp = x & 0x0F;gf _dst2=dst & 0x0F;_dst2 ^= __gf_mulc_[tmp]; dst = _dst1<<4 | _dst2; } +#else +#define GF_ADDMULC_COMPACT(dst,x) { GF_ADDMULC(dst, x);} +#endif + +static void +of_rs_init_mul_table() +{ + OF_ENTER_FUNCTION + int i, j; + for (i = 0; i < GF_SIZE + 1; i++) + for (j = 0; j < GF_SIZE + 1; j++) + of_gf_mul_table[i][j] = of_rs_gf_exp[of_modnn (of_rs_gf_log[i] + of_rs_gf_log[j]) ] ; + + for (j = 0; j < GF_SIZE + 1; j++) + of_gf_mul_table[0][j] = of_gf_mul_table[j][0] = 0; + OF_EXIT_FUNCTION +} +#else /* GF_BITS > 8 */ +static inline gf +of_gf_mul (x, y) +{ + if ( (x) == 0 || (y) == 0) + return 0; + + return of_rs_gf_exp[of_rs_gf_log[x] + of_rs_gf_log[y] ] ; +} +#define of_rs_init_mul_table() + +#define USE_GF_MULC register gf * __gf_mulc_ +#define GF_MULC0(c) __gf_mulc_ = &of_rs_gf_exp[ of_rs_gf_log[c] ] +#define GF_ADDMULC(dst, x) { if (x) dst ^= __gf_mulc_[ of_rs_gf_log[x] ] ; } +#endif + +/* + * Generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m] + * Lookup tables: + * index->polynomial form gf_exp[] contains j= \alpha^i; + * polynomial form -> index form gf_log[ j = \alpha^i ] = i + * \alpha=x is the primitive element of GF(2^m) + * + * For efficiency, gf_exp[] has size 2*GF_SIZE, so that a simple + * multiplication of two numbers can be resolved without calling modnn + */ + +/* + * i use malloc so many times, it is easier to put checks all in + * one place. + */ +static void * +of_my_malloc (INT32 sz, const char *err_string) +{ + OF_ENTER_FUNCTION + void *p = malloc (sz); + if (p == NULL) + { + OF_PRINT_ERROR (("-- malloc failure allocation %s\n", err_string)) + OF_EXIT_FUNCTION + return NULL; + } + OF_EXIT_FUNCTION + return p ; +} + +#define NEW_GF_MATRIX(rows, cols) \ + (gf *)of_my_malloc(rows * cols * sizeof(gf), " ## __LINE__ ## " ) + +/* + * initialize the data structures used for computations in GF. + */ +static void +of_generate_gf (void) +{ + OF_ENTER_FUNCTION + INT32 i; + gf mask; + const char *Pp = of_rs_allPp[GF_BITS] ; + + mask = 1; /* x ** 0 = 1 */ + of_rs_gf_exp[GF_BITS] = 0; /* will be updated at the end of the 1st loop */ + /* + * first, generate the (polynomial representation of) powers of \alpha, + * which are stored in gf_exp[i] = \alpha ** i . + * At the same time build gf_log[gf_exp[i]] = i . + * The first GF_BITS powers are simply bits shifted to the left. + */ + for (i = 0; i < GF_BITS; i++, mask <<= 1) + { + of_rs_gf_exp[i] = mask; + of_rs_gf_log[of_rs_gf_exp[i]] = i; + /* + * If Pp[i] == 1 then \alpha ** i occurs in poly-repr + * gf_exp[GF_BITS] = \alpha ** GF_BITS + */ + if (Pp[i] == '1') + of_rs_gf_exp[GF_BITS] ^= mask; + } + /* + * now gf_exp[GF_BITS] = \alpha ** GF_BITS is complete, so can als + * compute its inverse. + */ + of_rs_gf_log[of_rs_gf_exp[GF_BITS]] = GF_BITS; + /* + * Poly-repr of \alpha ** (i+1) is given by poly-repr of + * \alpha ** i shifted left one-bit and accounting for any + * \alpha ** GF_BITS term that may occur when poly-repr of + * \alpha ** i is shifted. + */ + mask = 1 << (GF_BITS - 1) ; + for (i = GF_BITS + 1; i < GF_SIZE; i++) + { + if (of_rs_gf_exp[i - 1] >= mask) + of_rs_gf_exp[i] = of_rs_gf_exp[GF_BITS] ^ ( (of_rs_gf_exp[i - 1] ^ mask) << 1); + else + of_rs_gf_exp[i] = of_rs_gf_exp[i - 1] << 1; + of_rs_gf_log[of_rs_gf_exp[i]] = i; + } + /* + * log(0) is not defined, so use a special value + */ + of_rs_gf_log[0] = GF_SIZE ; + /* set the extended gf_exp values for fast multiply */ + for (i = 0 ; i < GF_SIZE ; i++) + of_rs_gf_exp[i + GF_SIZE] = of_rs_gf_exp[i] ; + + /* + * again special cases. 0 has no inverse. This used to + * be initialized to GF_SIZE, but it should make no difference + * since noone is supposed to read from here. + */ + of_rs_inverse[0] = 0 ; + of_rs_inverse[1] = 1; + for (i = 2; i <= GF_SIZE; i++) + of_rs_inverse[i] = of_rs_gf_exp[GF_SIZE-of_rs_gf_log[i]]; + OF_EXIT_FUNCTION +} + +/* + * Various linear algebra operations that I often use. + */ + +/* + * addmul() computes dst[] = dst[] + c * src[] + * This is used often, so better optimize it! Currently the loop is + * unrolled 16 times, a good value for 486 and pentium-class machines. + * The case c=0 is also optimized, whereas c=1 is not. These + * calls are unfrequent in my typical apps so I did not bother. + */ +#define addmul(dst, src, c, sz) \ + if (c != 0) of_addmul1(dst, src, c, sz) + + + +#if defined (__LP64__) || (__WORDSIZE == 64) // { +#define UNROLL 16 /* loop unrolling, must be equal to 16 in code below */ +static void +of_addmul1 (gf *dst1, gf *src1, gf c, int sz) +{ + USE_GF_MULC ; + register gf *dst = dst1, *src = src1 ; + + gf *lim = &dst[sz - UNROLL + 1] ; + UINT64 tmp; + UINT64 *dst_64 = (UINT64*)dst1; + GF_MULC0 (c) ; + /* with 64-bit CPUs, unroll the loop and work on two 64-bit words at a time. */ + for (; dst < lim ; dst += UNROLL, src += UNROLL) + { + + tmp = ((UINT64)__gf_mulc_[src[0]]) | ((UINT64)__gf_mulc_[src[1]]<<8) | ((UINT64)__gf_mulc_[src[2]]<<16) | + ((UINT64)__gf_mulc_[src[3]]<<24) | ((UINT64)__gf_mulc_[src[4]]<<32) | ((UINT64)__gf_mulc_[src[5]]<<40) | + ((UINT64)__gf_mulc_[src[6]]<<48) | ((UINT64)__gf_mulc_[src[7]]<<56) ; + *dst_64 ^= tmp; + dst_64++; + + tmp = ((UINT64)__gf_mulc_[src[8]]) | ((UINT64)__gf_mulc_[src[9]]<<8) | ((UINT64)__gf_mulc_[src[10]]<<16) | + ((UINT64)__gf_mulc_[src[11]]<<24) | ((UINT64)__gf_mulc_[src[12]]<<32) | ((UINT64)__gf_mulc_[src[13]]<<40) | + ((UINT64)__gf_mulc_[src[14]]<<48) | ((UINT64)__gf_mulc_[src[15]]<<56) ; + *dst_64 ^= tmp; + dst_64++; + } + lim += UNROLL - 1 ; + for (; dst < lim; dst++, src++) /* final components */ + GF_ADDMULC (*dst , *src); +} + +#else // ! (__LP64__) || (__WORDSIZE == 64) + +#define UNROLL 16 /* loop unrolling. Value must be one of {1, 4, 8, 16}. + * However, operations remain on the basis of bytes with GF(2^^8). */ +static void +of_addmul1 (gf *dst1, gf *src1, gf c, int sz) +{ + USE_GF_MULC ; + register gf *dst = dst1, *src = src1 ; + + gf *lim = &dst[sz - UNROLL + 1] ; + GF_MULC0 (c) ; +#if (UNROLL > 1) /* unrolling by 8/16 is quite effective on the pentium */ + for (; dst < lim ; dst += UNROLL, src += UNROLL) + { + GF_ADDMULC (dst[0] , src[0]); + GF_ADDMULC (dst[1] , src[1]); + GF_ADDMULC (dst[2] , src[2]); + GF_ADDMULC (dst[3] , src[3]); +#if (UNROLL > 4) + GF_ADDMULC (dst[4] , src[4]); + GF_ADDMULC (dst[5] , src[5]); + GF_ADDMULC (dst[6] , src[6]); + GF_ADDMULC (dst[7] , src[7]); +#endif +#if (UNROLL > 8) + GF_ADDMULC (dst[8] , src[8]); + GF_ADDMULC (dst[9] , src[9]); + GF_ADDMULC (dst[10] , src[10]); + GF_ADDMULC (dst[11] , src[11]); + GF_ADDMULC (dst[12] , src[12]); + GF_ADDMULC (dst[13] , src[13]); + GF_ADDMULC (dst[14] , src[14]); + GF_ADDMULC (dst[15] , src[15]); +#endif + } +#endif + lim += UNROLL - 1 ; + for (; dst < lim; dst++, src++) /* final components */ + GF_ADDMULC (*dst , *src); +} + +#endif //defined (__LP64__) || (__WORDSIZE == 64) + +/* + * computes C = AB where A is n*k, B is k*m, C is n*m + */ +static void +of_matmul (gf *a, gf *b, gf *c, int n, int k, int m) +{ + OF_ENTER_FUNCTION + int row, col, i ; + + for (row = 0; row < n ; row++) + { + for (col = 0; col < m ; col++) + { + gf *pa = &a[ row * k ]; + gf *pb = &b[ col ]; + gf acc = 0 ; + for (i = 0; i < k ; i++, pa++, pb += m) + acc ^= of_gf_mul (*pa, *pb) ; + c[ row * m + col ] = acc ; + } + } + OF_EXIT_FUNCTION +} + +#ifdef OF_RS_DEBUG +/* + * returns 1 if the square matrix is identiy + * (only for test) + */ +/* +static int +is_identity(gf *m, int k) +{ + int row, col ; + for (row=0; row 1) + { +// PRINT_ERR((mcl_stderr, "singular matrix\n")) + goto fail ; + } + } + } + } + if (icol == -1) + { +// PRINT_ERR((mcl_stderr, "XXX pivot not found!\n")) + goto fail ; + } +found_piv: + ++ (ipiv[icol]) ; + /* + * swap rows irow and icol, so afterwards the diagonal + * element will be correct. Rarely done, not worth + * optimizing. + */ + if (irow != icol) + { + for (ix = 0 ; ix < k ; ix++) + { + SWAP (src[irow*k + ix], src[icol*k + ix], gf) ; + } + } + indxr[col] = irow ; + indxc[col] = icol ; + pivot_row = &src[icol*k] ; + c = pivot_row[icol] ; + if (c == 0) + { + OF_PRINT_ERROR(("singular matrix 2\n")) + goto fail ; + } + if (c != 1) + { + /* otherwhise this is a NOP */ + /* + * this is done often , but optimizing is not so + * fruitful, at least in the obvious ways (unrolling) + */ + DEB (pivswaps++ ;) + c = of_rs_inverse[ c ] ; + pivot_row[icol] = 1 ; + for (ix = 0 ; ix < k ; ix++) + pivot_row[ix] = of_gf_mul (c, pivot_row[ix]); + } + /* + * from all rows, remove multiples of the selected row + * to zero the relevant entry (in fact, the entry is not zero + * because we know it must be zero). + * (Here, if we know that the pivot_row is the identity, + * we can optimize the addmul). + */ + id_row[icol] = 1; + if (bcmp (pivot_row, id_row, k*sizeof (gf)) != 0) + { + for (p = src, ix = 0 ; ix < k ; ix++, p += k) + { + if (ix != icol) + { + c = p[icol] ; + p[icol] = 0 ; + addmul (p, pivot_row, c, k); + } + } + } + id_row[icol] = 0; + } /* done all columns */ + for (col = k - 1 ; col >= 0 ; col--) + { + if (indxr[col] < 0 || indxr[col] >= k) + OF_PRINT_ERROR(("AARGH, indxr[col] %d\n", indxr[col])) + else + if (indxc[col] < 0 || indxc[col] >= k) + OF_PRINT_ERROR(( "AARGH, indxc[col] %d\n", indxc[col])) + else + if (indxr[col] != indxc[col]) + { + for (row = 0 ; row < k ; row++) + { + SWAP (src[row*k + indxr[col]], src[row*k + indxc[col]], gf) ; + } + } + } + error = 0 ; +fail: + free (indxc); + free (indxr); + free (ipiv); + free (id_row); + free (temp_row); + OF_EXIT_FUNCTION + return error ; +} + +/* + * fast code for inverting a vandermonde matrix. + * XXX NOTE: It assumes that the matrix + * is not singular and _IS_ a vandermonde matrix. Only uses + * the second column of the matrix, containing the p_i's. + * + * Algorithm borrowed from "Numerical recipes in C" -- sec.2.8, but + * largely revised for my purposes. + * p = coefficients of the matrix (p_i) + * q = values of the polynomial (known) + */ + +int +of_invert_vdm (gf *src, int k) +{ + OF_ENTER_FUNCTION + int i, j, row, col ; + gf *b, *c, *p; + gf t, xx ; + + if (k == 1) /* degenerate case, matrix must be p^0 = 1 */ + return 0 ; + /* + * c holds the coefficient of P(x) = Prod (x - p_i), i=0..k-1 + * b holds the coefficient for the matrix inversion + */ + c = NEW_GF_MATRIX (1, k); + b = NEW_GF_MATRIX (1, k); + + p = NEW_GF_MATRIX (1, k); + + for (j = 1, i = 0 ; i < k ; i++, j += k) + { + c[i] = 0 ; + p[i] = src[j] ; /* p[i] */ + } + /* + * construct coeffs. recursively. We know c[k] = 1 (implicit) + * and start P_0 = x - p_0, then at each stage multiply by + * x - p_i generating P_i = x P_{i-1} - p_i P_{i-1} + * After k steps we are done. + */ + c[k-1] = p[0] ; /* really -p(0), but x = -x in GF(2^m) */ + for (i = 1 ; i < k ; i++) + { + gf p_i = p[i] ; /* see above comment */ + for (j = k - 1 - (i - 1) ; j < k - 1 ; j++) + c[j] ^= of_gf_mul (p_i, c[j+1]) ; + c[k-1] ^= p_i ; + } + + for (row = 0 ; row < k ; row++) + { + /* + * synthetic division etc. + */ + xx = p[row] ; + t = 1 ; + b[k-1] = 1 ; /* this is in fact c[k] */ + for (i = k - 2 ; i >= 0 ; i--) + { + b[i] = c[i+1] ^ of_gf_mul (xx, b[i+1]) ; + t = of_gf_mul (xx, t) ^ b[i] ; + } + for (col = 0 ; col < k ; col++) + src[col*k + row] = of_gf_mul (of_rs_inverse[t], b[col]); + } + free (c) ; + free (b) ; + free (p) ; + OF_EXIT_FUNCTION + return 0 ; +} + +static int of_rs_initialized = 0 ; +/* static */ +void /* VR: removed static */ +of_rs_init() +{ + OF_ENTER_FUNCTION + TICK (ticks[0]); + of_generate_gf(); + TOCK (ticks[0]); + DDB (printf("generate_gf took %ldus\n", ticks[0]);) + TICK (ticks[0]); + of_rs_init_mul_table(); + TOCK (ticks[0]); + DDB (printf("init_mul_table took %ldus\n", ticks[0]);) + of_rs_initialized = 1 ; + OF_EXIT_FUNCTION +} + +/* + * This section contains the proper FEC encoding/decoding routines. + * The encoding matrix is computed starting with a Vandermonde matrix, + * and then transforming it into a systematic matrix. + */ + +#define FEC_MAGIC 0xFECC0DEC + +struct fec_parms +{ + UINT32 magic ; + INT32 k, n ; /* parameters of the code */ + gf *enc_matrix ; +} ; + + +#define CPLUSPLUS_COMPATIBLE /* VR: added */ +#ifdef CPLUSPLUS_COMPATIBLE +void of_rs_free (void *p_vp) +#else +void of_rs_free (struct fec_parms *p) +#endif /* CPLUSPLUS_COMPATIBLE */ +{ + OF_ENTER_FUNCTION +#ifdef CPLUSPLUS_COMPATIBLE + struct fec_parms *p = (struct fec_parms *) p_vp; /* VR */ +#endif /* CPLUSPLUS_COMPATIBLE */ + if (p == NULL) //|| + //p->magic != ( ( (FEC_MAGIC ^ p->k) ^ p->n) ^ (int)(p->enc_matrix)) ) { + //p->magic != (( (FEC_MAGIC ^ p->k) ^ p->n) ^ (UINT32) (p->enc_matrix))) + { + OF_PRINT_ERROR (("bad parameters to fec_free\n")) + return ; + } + free (p->enc_matrix); + free (p); + OF_EXIT_FUNCTION +} + +/* + * create a new encoder, returning a descriptor. This contains k,n and + * the encoding matrix. + */ +#if 0 /* VR: changed as it creates problems with C++ compilers */ +struct fec_parms * +#else +void * +#endif +of_rs_new (UINT32 k, UINT32 n) +{ + OF_ENTER_FUNCTION + INT32 row, col ; + gf *p, *tmp_m ; + + struct fec_parms *retval ; + + if (of_rs_initialized == 0) + of_rs_init(); + + if (k > GF_SIZE + 1 || n > GF_SIZE + 1 || k > n) + { + OF_PRINT_ERROR(( "Invalid parameters k %d n %d GF_SIZE %d\n", + k, n, GF_SIZE)) + OF_EXIT_FUNCTION + return NULL ; + } + retval = (struct fec_parms*) of_my_malloc (sizeof (struct fec_parms), "new_code"); + retval->k = k ; + retval->n = n ; + retval->enc_matrix = NEW_GF_MATRIX (n, k); + /* cast the pointer (a 64 bit integer on LP64 systems) to uintptr_t first, and then + * truncate it to keep only the lowest 32 bits. Works the same on both 32 bit and 64 + * bit systems */ + //retval->magic = ( ( FEC_MAGIC ^ k) ^ n) ^ (int)(retval->enc_matrix) ; + retval->magic = ( (FEC_MAGIC ^ k) ^ n) ^ ((uintptr_t)(retval->enc_matrix) & 0xFFFFFFFF); + tmp_m = NEW_GF_MATRIX (n, k); + /* + * fill the matrix with powers of field elements, starting from 0. + * The first row is special, cannot be computed with exp. table. + */ + tmp_m[0] = 1 ; + for (col = 1; col < k ; col++) + tmp_m[col] = 0 ; + for (p = tmp_m + k, row = 0; row < n - 1 ; row++, p += k) + { + for (col = 0 ; col < k ; col ++) + p[col] = of_rs_gf_exp[of_modnn (row*col) ]; + } + + /* + * quick code to build systematic matrix: invert the top + * k*k vandermonde matrix, multiply right the bottom n-k rows + * by the inverse, and construct the identity matrix at the top. + */ + TICK (ticks[3]); + of_invert_vdm (tmp_m, k); /* much faster than invert_mat */ + of_matmul (tmp_m + k*k, tmp_m, retval->enc_matrix + k*k, n - k, k, k); + /* + * the upper matrix is I so do not bother with a slow multiply + */ + bzero (retval->enc_matrix, k*k*sizeof (gf)); + for (p = retval->enc_matrix, col = 0 ; col < k ; col++, p += k + 1) + *p = 1 ; + free (tmp_m); + TOCK (ticks[3]); + + DDB (printf( "--- %ld us to build encoding matrix\n", ticks[3]);) + //DEB (pr_matrix (retval->enc_matrix, n, k, "encoding_matrix");) + OF_EXIT_FUNCTION +#if 0 /* VR: changed as it creates problems with C++ compilers */ + return retval ; +#else + return (void*) retval ; +#endif +} + +/* + * of_rs_encode accepts as input pointers to n data packets of size sz, + * and produces as output a packet pointed to by fec, computed + * with index "index". + */ +/* + * VR: changed for C++ compilers who don't accept diff in parameters... + * Use a definition that matches prototype in fec.h + */ +#define CPLUSPLUS_COMPATIBLE /* VR: added */ +#ifdef CPLUSPLUS_COMPATIBLE +of_status_t +of_rs_encode (void *code_vp, void **src_vp, void *fec_vp, int index, int sz) +#else +of_status_t +of_rs_encode (struct fec_parms *code, gf *src[], gf *fec, int index, int sz) +#endif +{ + OF_ENTER_FUNCTION +#ifdef CPLUSPLUS_COMPATIBLE + struct fec_parms *code = (struct fec_parms*) code_vp; /* VR */ + gf **src = (gf**) src_vp; /* VR */ + gf *fec = (gf*) fec_vp; /* VR */ +#endif /* CPLUSPLUS_COMPATIBLE */ + int i, k = code->k ; + gf *p ; + + if (GF_BITS > 8) + sz /= 2 ; + + if (index < k) + bcopy (src[index], fec, sz*sizeof (gf)) ; + else if (index < code->n) + { + p = & (code->enc_matrix[index*k]); + bzero (fec, sz*sizeof (gf)); + for (i = 0; i < k ; i++) + addmul (fec, src[i], p[i], sz) ; + return OF_STATUS_OK; + } + else + { + OF_PRINT_ERROR (("Invalid index %d (max %d)\n", index, code->n - 1)) + } + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + +/* + * shuffle move src packets in their position + */ +static int +of_shuffle (gf *pkt[], int index[], int k) +{ + OF_ENTER_FUNCTION + int i; + + for (i = 0 ; i < k ;) + { + if (index[i] >= k || index[i] == i) + i++ ; + else + { + /* + * put pkt in the right position (first check for conflicts). + */ + int c = index[i] ; + + if (index[c] == c) + { + DEB (printf("\nshuffle, error at %d\n", i);) + OF_EXIT_FUNCTION + return 1 ; + } + SWAP (index[i], index[c], int) ; + SWAP (pkt[i], pkt[c], gf *) ; + } + } + DEB ( /* just test that it works... */ + for (i = 0 ; i < k ; i++) + { + if (index[i] < k && index[i] != i) + { + printf("shuffle: after\n"); + for (i = 0; i < k ; i++) + printf ("%3d ", index[i]); + printf ("\n"); + OF_EXIT_FUNCTION + return 1 ; + } + } + ) + OF_EXIT_FUNCTION + return 0 ; +} + + +/* + * build_decode_matrix constructs the encoding matrix given the + * indexes. The matrix must be already allocated as + * a vector of k*k elements, in row-major order + */ +static gf * +of_build_decode_matrix (struct fec_parms *code, gf *pkt[], int index[]) +{ + OF_ENTER_FUNCTION + int i , k = code->k ; + gf *p, *matrix = NEW_GF_MATRIX (k, k); + + TICK (ticks[9]); + for (i = 0, p = matrix ; i < k ; i++, p += k) + { +#if 1 /* this is simply an optimization, not very useful indeed */ + if (index[i] < k) + { + bzero (p, k*sizeof (gf)); + p[i] = 1 ; + } + else +#endif + if (index[i] < code->n) + bcopy (& (code->enc_matrix[index[i]*k]), p, k*sizeof (gf)); + else + { + OF_PRINT_ERROR ( ("decode: invalid index %d (max %d)\n", + index[i], code->n - 1)) + free (matrix); + OF_EXIT_FUNCTION + return NULL ; + } + } + TICK (ticks[9]); + if (of_invert_mat (matrix, k)) + { + free (matrix); + matrix = NULL ; + } + TOCK (ticks[9]); + OF_EXIT_FUNCTION + return matrix ; +} + +/* + * of_rs_decode receives as input a vector of packets, the indexes of + * packets, and produces the correct vector as output. + * + * Input: + * code: pointer to code descriptor + * pkt: pointers to received packets. They are modified + * to store the output packets (in place) + * index: pointer to packet indexes (modified but not updated upon return) + * sz: size of each packet + */ +/* + * VR: changed for C++ compilers who don't accept diff in parameters... + * Use a definition that matches prototype in fec.h + */ +#define CPLUSPLUS_COMPATIBLE /* VR: added */ +#ifdef CPLUSPLUS_COMPATIBLE +of_status_t +of_rs_decode (void *code_vp, void **pkt_vp, int index[], int sz) +#else +int +of_rs_decode (struct fec_parms *code, gf *pkt[], int index[], int sz) +#endif +{ + OF_ENTER_FUNCTION +#ifdef CPLUSPLUS_COMPATIBLE + struct fec_parms *code = (struct fec_parms*) code_vp; /* VR */ + gf **pkt = (gf**) pkt_vp; /* VR */ +#endif /* CPLUSPLUS_COMPATIBLE */ + gf *m_dec ; + gf **new_pkt ; + int row, col, k = code->k ; + + if (GF_BITS > 8) + sz /= 2 ; + + if (of_shuffle (pkt, index, k)) + { + /* error if true */ + OF_EXIT_FUNCTION + return OF_STATUS_ERROR ; + } + m_dec = of_build_decode_matrix (code, pkt, index); + + if (m_dec == NULL) + { + OF_EXIT_FUNCTION + return OF_STATUS_ERROR ; /* error */ + } + /* + * do the actual decoding + */ + new_pkt = (gf **) of_my_malloc (k * sizeof (gf *), "new pkt pointers"); + for (row = 0 ; row < k ; row++) + { + if (index[row] >= k) + { + new_pkt[row] = (gf *) of_my_malloc (sz * sizeof (gf), "new pkt buffer"); + bzero (new_pkt[row], sz * sizeof (gf)) ; + for (col = 0 ; col < k ; col++) + { + addmul (new_pkt[row], pkt[col], m_dec[row*k + col], sz) ; + } + } + } + /* + * move pkts to their final destination + * Warning: this function does not update the index[] table to contain + * the actual reconstructed packet index. + */ + for (row = 0 ; row < k ; row++) + { + if (index[row] >= k) + { + bcopy (new_pkt[row], pkt[row], sz*sizeof (gf)); + free (new_pkt[row]); + } + } + free (new_pkt); + free (m_dec); + + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + +/*********** end of FEC code -- beginning of test code ************/ + +#if defined(TEST) /* || OF_RS_DEBUG*/ +void +test_gf() +{ + OF_ENTER_FUNCTION + int i ; + /* + * test gf tables. Sufficiently tested... + */ + for (i = 0; i <= GF_SIZE; i++) + { + if (of_rs_gf_exp[of_rs_gf_log[i]] != i) + OF_PRINT_ERROR(("bad exp/log i %d log %d exp(log) %d\n", + i, of_rs_gf_log[i], of_rs_gf_exp[of_rs_gf_log[i]])) + + if (i != 0 && of_gf_mul (i, of_rs_inverse[i]) != 1) + OF_PRINT_ERROR(( "bad mul/inv i %d inv %d i*inv(i) %d\n", + i, of_rs_inverse[i], of_gf_mul (i, of_rs_inverse[i]))) + if (of_gf_mul (0, i) != 0) + OF_PRINT_ERROR(("bad mul table 0,%d\n", i)) + if (of_gf_mul (i, 0) != 0) + OF_PRINT_ERROR(("bad mul table %d,0\n", i)) + } + OF_EXIT_FUNCTION +} +#endif /* TEST */ + +#endif //#ifdef OF_USE_REED_SOLOMON_CODEC diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8.h b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8.h new file mode 100644 index 0000000..8fa95bb --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8.h @@ -0,0 +1,308 @@ +/* $Id: of_reed-solomon_gf_2_8.h 72 2012-04-13 13:27:26Z detchart $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifdef OF_USE_REED_SOLOMON_CODEC + +#ifndef OF_REED_SOLOMON_GF_2_8_H +#define OF_REED_SOLOMON_GF_2_8_H + +/* + * The following parameter defines how many bits are used for + * field elements. The code supports any value from 2 to 16 + * but fastest operation is achieved with 8 bit elements + * This is the only parameter you may want to change. + */ +#ifndef GF_BITS +#define GF_BITS 8 /* code over GF(2**GF_BITS) - change to suit */ +#endif + +#define GF_SIZE ((1 << GF_BITS) - 1) /* powers of \alpha */ + + +/** + * Reed-Solomon stable codec specific control block structure. + */ +typedef struct of_rs_cb +{ + of_codec_id_t codec_id; /* must begin with fec_codec_id */ + of_codec_type_t codec_type; /* must be 2nd item */ + /* + * FEC codec id specific attributes follow... + */ + UINT32 nb_source_symbols; /** k parameter (AKA code dimension). */ + UINT32 nb_repair_symbols; /** r = n - k parameter. */ + UINT32 nb_encoding_symbols; /** n parameter (AKA code length). */ + /** Maximum number of source symbols supported by this codec for practical reasons. */ + UINT32 max_nb_source_symbols; + /** Maximum number of encoding symbols supported by this codec for practical reasons. */ + UINT32 max_nb_encoding_symbols; + UINT32 encoding_symbol_length; /** symbol length. */ + + void *rs_cb; /** Reed-Solomon internal codec control block */ + +#ifdef OF_USE_DECODER + /* + * decoder specific variables. + */ + /** + * Table of available source and repair symbols. This table is ordered, no matter + * the symbol arrival order. + */ + void ** available_symbols_tab; + /** Number of available source and repair symbols. This is the number of entries in + * the available_symbols_tab tables. */ + UINT32 nb_available_symbols; + /** Number of available source symbols. */ + UINT32 nb_available_source_symbols; + bool decoding_finished; /** true as soon as decoding completed. */ +#endif /* OF_USE_DECODER */ + + + /** callbacks for this codec. */ + void* (*decoded_source_symbol_callback) (void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi); /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi); /* encoding symbol ID in {0..k-1} */ + void* context_4_callback; + +} of_rs_cb_t; + + +/* + * API function prototypes. + */ + /** + * This function create the codec instance for the Reed-Solomon codec. + * + * @fn of_status_t of_rs_create_codec_instance (of_rs_cb_t** of_cb) + * @brief create a Reed-Solomon codec instance + * @param of_cb (IN/OUT) address of the pointer to a Reed-Solomon codec control block. This pointer is updated + * by this function. + * In case of success, it points to a session structure allocated by the + * library. In case of failure it points to NULL. + * @return Error status. The ofcb pointer is updated according to the success return + * status. + */ +of_status_t of_rs_create_codec_instance (of_rs_cb_t** of_cb); + +/** + * This function releases all the internal resources used by this FEC codec instance. + * None of the source symbol buffers will be free'ed by this function, even those decoded by + * the library if any, regardless of whether a callback has been registered or not. It's the + * responsibility of the caller to free them. + * + * @fn of_status_t of_rs_release_codec_instance (of_rs_cb_t* ofcb) + * @brief release all resources used by the codec + * @param ofcb (IN) Pointer to the control block. + * @return Error status. + */ +of_status_t of_rs_release_codec_instance (of_rs_cb_t* ofcb); + +/** + * + * @fn of_status_t of_rs_set_fec_parameters (of_rs_cb_t* ofcb, of_rs_parameters_t* params) + * @brief set all the FEC codec parameters (e.g. k, n, or symbol size) + * @param ofcb (IN) Pointer to the control block. + * @param params (IN) pointer to a structure containing the FEC parameters associated to + * a specific FEC codec. + * @return Error status. + */ +of_status_t of_rs_set_fec_parameters (of_rs_cb_t* ofcb, + of_rs_parameters_t* params); + +/** + * @fn of_status_t of_rs_set_callback_functions (of_rs_cb_t *ofcb,void* (*decoded_source_symbol_callback) + * (void *context,UINT32 size,UINT32 esi), void* (*decoded_repair_symbol_callback) + * (void *context,UINT32 size,UINT32 esi),void* context_4_callback) + * @brief set various callbock functions (see header of_open_fec_api.h) + * @param ofcb (IN) Pointer to the session. + * + * @param decoded_source_symbol_callback + * (IN) Pointer to the function, within the application, that + * needs to be called each time a source symbol is decoded. + * If this callback is not initialized, the symbol is managed + * internally. + * + * @param decoded_repair_symbol_callback + * (IN) Pointer to the function, within the application, that + * needs to be called each time a repair symbol is decoded. + * If this callback is not initialized, the symbol is managed + * internally. + * + * @param context_4_callback (IN) Pointer to the application-specific context that will be + * passed to the callback function (if any). This context is not + * interpreted by this function. + * + * @return Completion status (LDPC_OK or LDPC_ERROR). + */ +of_status_t of_rs_set_callback_functions (of_rs_cb_t* ofcb, + void* (*decoded_source_symbol_callback) (void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* context_4_callback); + +#ifdef OF_USE_ENCODER +/** + * @fn of_status_t of_rs_build_repair_symbol (of_rs_cb_t* ofcb, void* encoding_symbols_tab[], UINT32 esi_of_symbol_to_build) + * @brief build a repair symbol (encoder only) + * @param ofcb (IN) Pointer to the session. + * @param encoding_symbols_tab (IN/OUT) table of source and repair symbols. + * The entry for the repair symbol to build can either point + * to a buffer allocated by the application, or let to NULL + * meaning that of_build_repair_symbol will allocate memory. + * @param esi_of_symbol_to_build + * (IN) encoding symbol ID of the repair symbol to build in + * {k..n-1} + * @return Error status. + */ +of_status_t of_rs_build_repair_symbol (of_rs_cb_t* ofcb, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build); +#endif //OF_USE_ENCODER + +#ifdef OF_USE_DECODER +/** + * @fn of_status_t of_rs_decode_with_new_symbol (of_rs_cb_t* ofcb, void* const new_symbol_buf, UINT32 new_symbol_esi) + * @brief (try to) decode with a newly received symbol + * @param ofcb (IN) Pointer to the session. + * @param new_symbol (IN) Pointer to the encoding symbol now available (i.e. a new + * symbol received by the application, or a decoded symbol in case + * of a recursive call). + * @param new_symbol_esi (IN) Encoding symbol ID of the newly symbol available, in {0..n-1}. + * @return Error status (NB: this function does not return OF_STATUS_FAILURE). + */ +of_status_t of_rs_decode_with_new_symbol (of_rs_cb_t* ofcb, + void* new_symbol, + UINT32 new_symbol_esi); + +/** + * @fn of_status_t of_rs_set_available_symbols (of_rs_cb_t* ofcb, void* const encoding_symbols_tab[]); + * @brief inform the decoder of all the available (received) symbols + * @param ofcb (IN) Pointer to the session. + * @param encoding_symbols_tab (IN) Pointer to the available encoding symbols table. To each + * available symbol the corresponding entry in the table must point + * to the associated buffer. Entries set to NULL are interpreted as + * corresponding to erased symbols. + * @return Error status. + */ +of_status_t of_rs_set_available_symbols (of_rs_cb_t* ofcb, + void* const encoding_symbols_tab[]); + +/** + * @fn of_status_t of_rs_finish_decoding (of_rs_cb_t* ofcb) + * @brief finish decoding with available symbols + * @param ofcb (IN) Pointer to the session. + * @return Error status. Returns OF_STATUS_FAILURE if decoding failed, or + * OF_STATUS_OK if decoding succeeded, or OF_STATUS_*_ERROR in case + * of (fatal) error. + */ +of_status_t of_rs_finish_decoding (of_rs_cb_t* ofcb); + +/** + * @fn bool of_rs_is_decoding_complete (of_rs_cb_t* ofcb) + * @brief check if decoding is finished + * @param ofcb (IN) Pointer to the session. + * @return Boolean. Warning, this is one of the very functions of the library that + * does not return an error status. + */ +bool of_rs_is_decoding_complete (of_rs_cb_t* ofcb); + +/** + * @fn of_status_t of_rs_get_source_symbols_tab (of_rs_cb_t* ofcb, void* source_symbols_tab[]) + * @brief get the table of available source symbols (after decoding) + * @param ofcb (IN) Pointer to the session. + * @param source_symbols_tab (IN/OUT) table, that will be filled by the library and returned + * to the application. + * @return Error status. + */ +of_status_t of_rs_get_source_symbols_tab (of_rs_cb_t* ofcb, + void* source_symbols_tab[]); + +#endif //OF_USE_DECODER + +/** + * @fn of_status_t of_rs_set_control_parameter (of_rs_cb_t* ofcb,UINT32 type,void* value,UINT32 length) + * @brief set a specific FEC parameter + * @param ofcb (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID specific. + * @param value (IN) Pointer to the value of the parameter. The type of the object pointed + * is FEC codec ID specific. + * @param length (IN) length of pointer + * @return Error status. + */ +of_status_t of_rs_set_control_parameter (of_rs_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length); + +/** + * @fn of_status_t of_rs_get_control_parameter (of_rs_cb_t* ofcb,UINT32 type,void* value,UINT32 length) + * @brief get a specific FEC parameter + * @param ofcb (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID specific. + * @param value (IN/OUT) Pointer to the value of the parameter. The type of the object + * pointed is FEC codec ID specific. This function updates the value object + * accordingly. The application, who knows the FEC codec ID, is responsible + * to allocating the approriate object pointed by the value pointer. + * @param length (IN) length of pointer + * @return Error status. + */ +of_status_t of_rs_get_control_parameter (of_rs_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length); + + +/* + * Internal Reed-Solomon codec function prototypes. + */ + +void of_rs_free (void *p) ; + +void * of_rs_new (UINT32 k, UINT32 n) ; + +void of_rs_init (void) ; + +of_status_t of_rs_encode (void *code, void **src, void *dst, int index, int sz) ; + +of_status_t of_rs_decode (void *code, void **pkt, int index[], int sz) ; + + +#endif /* OF_REED_SOLOMON_GF_2_8_H */ + +#endif //#ifdef OF_USE_REED_SOLOMON_CODEC diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8_api.c b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8_api.c new file mode 100644 index 0000000..153278e --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8_api.c @@ -0,0 +1,530 @@ +/* $Id: of_reed-solomon_gf_2_8_api.c 186 2014-07-16 07:17:53Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2011 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "of_reed-solomon_gf_2_8_includes.h" + +#ifdef OF_USE_REED_SOLOMON_CODEC + + +bool of_rs_is_source_symbol (of_rs_cb_t* ofcb, + UINT32 new_symbol_esi) +{ + if (new_symbol_esi < ofcb->nb_source_symbols) + return true; + else + return false; +} + + +bool of_rs_is_repair_symbol (of_rs_cb_t* ofcb, + UINT32 new_symbol_esi) +{ + if (new_symbol_esi < ofcb->nb_source_symbols) + return false; + else + return true; +} + + +of_status_t of_rs_create_codec_instance (of_rs_cb_t** of_cb) +{ + of_codec_type_t codec_type; /* temporary value */ + of_rs_cb_t *cb; + + OF_ENTER_FUNCTION + cb = (of_rs_cb_t*) of_realloc (*of_cb, sizeof (of_rs_cb_t)); + *of_cb = cb; + /* realloc does not initialize the additional buffer space, so do that manually, + * then re-initialize a few parameters */ + codec_type = cb->codec_type; + memset(cb, 0, sizeof(*cb)); + cb->codec_type = codec_type; + cb->codec_id = OF_CODEC_REED_SOLOMON_GF_2_8_STABLE; + cb->max_nb_source_symbols = OF_REED_SOLOMON_MAX_NB_SOURCE_SYMBOLS_DEFAULT; /* init it immediately... */ + cb->max_nb_encoding_symbols = OF_REED_SOLOMON_MAX_NB_ENCODING_SYMBOLS_DEFAULT; /* init it immediately... */ + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_rs_release_codec_instance (of_rs_cb_t* ofcb) +{ + OF_ENTER_FUNCTION + UINT32 i; + if (ofcb->rs_cb != NULL) + { + of_rs_free (ofcb->rs_cb); + ofcb->rs_cb = NULL; + } +#ifdef OF_USE_DECODER + if (ofcb->available_symbols_tab != NULL) + { + of_free(ofcb->available_symbols_tab); + ofcb->available_symbols_tab = NULL; + } +#endif /* OF_USE_DECODER */ + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_rs_set_fec_parameters (of_rs_cb_t* ofcb, + of_rs_parameters_t* params) +{ + OF_ENTER_FUNCTION + if ((ofcb->nb_source_symbols = params->nb_source_symbols) > ofcb->max_nb_source_symbols) { + OF_PRINT_ERROR(("of_rs_set_fec_parameters: ERROR, invalid nb_source_symbols parameter (got %d, maximum is %d)", + ofcb->nb_source_symbols, ofcb->max_nb_source_symbols)); + goto error; + } + ofcb->nb_source_symbols = params->nb_source_symbols; + ofcb->nb_repair_symbols = params->nb_repair_symbols; + ofcb->encoding_symbol_length = params->encoding_symbol_length; + ofcb->nb_encoding_symbols = ofcb->nb_source_symbols + ofcb->nb_repair_symbols; +#ifdef OF_USE_DECODER + ofcb->available_symbols_tab = (void**) of_calloc (ofcb->nb_encoding_symbols, sizeof (void*)); + ofcb->nb_available_symbols = 0; + ofcb->nb_available_source_symbols = 0; +#endif /* OF_USE_DECODER */ + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + + +of_status_t of_rs_set_callback_functions (of_rs_cb_t* ofcb, + void* (*decoded_source_symbol_callback) (void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* context_4_callback) +{ + ofcb->decoded_source_symbol_callback = decoded_source_symbol_callback; + ofcb->decoded_repair_symbol_callback = decoded_repair_symbol_callback; + ofcb->context_4_callback = context_4_callback; + if (ofcb->decoded_repair_symbol_callback != NULL) + { + OF_PRINT_ERROR(("of_rs_set_callback_functions: Warning, the decoded repair symbol callback is never called with Reed-Solomon codes, since those repair symbols are never decoded\n")) + } + return OF_STATUS_OK; +} + + +#ifdef OF_USE_ENCODER +of_status_t of_rs_build_repair_symbol (of_rs_cb_t* ofcb, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build) +{ + OF_ENTER_FUNCTION + if (esi_of_symbol_to_build < ofcb->nb_source_symbols || esi_of_symbol_to_build >= ofcb->nb_encoding_symbols) + { + OF_PRINT_ERROR(("of_rs_build_repair_symbol: Error, bad esi of encoding symbol (%d)", + esi_of_symbol_to_build)) + goto error; + } + if (encoding_symbols_tab[esi_of_symbol_to_build] == NULL) + { + if ((encoding_symbols_tab[esi_of_symbol_to_build] = of_calloc (1, ofcb->encoding_symbol_length)) == NULL) + { + OF_PRINT_ERROR(("of_rs_build_repair_symbol: Error, no memory\n")) + goto error; + } + } + if (ofcb->rs_cb == NULL) + { + /* this is the first time we do an encoding for this codec instance, so initialize + * the Reed-Solomon internal codec */ + ofcb->rs_cb = of_rs_new (ofcb->nb_source_symbols, ofcb->nb_encoding_symbols); + if (ofcb->rs_cb == NULL) + { + OF_PRINT_ERROR(("of_rs_build_repair_symbol: Error, of_rs_new failed")) + goto error; + } + } + if (of_rs_encode(ofcb->rs_cb, + encoding_symbols_tab, + encoding_symbols_tab[esi_of_symbol_to_build], + esi_of_symbol_to_build, + ofcb->encoding_symbol_length) != OF_STATUS_OK) + { + OF_PRINT_ERROR(("of_rs_build_repair_symbol: Error, of_rs_encode failed")) + goto error; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} +#endif //OF_USE_ENCODER + + +#ifdef OF_USE_DECODER +of_status_t of_rs_decode_with_new_symbol (of_rs_cb_t* ofcb, + void* new_symbol, + UINT32 new_symbol_esi) +{ + OF_ENTER_FUNCTION + if (ofcb->decoding_finished) + { + OF_TRACE_LVL(2, ("of_rs_decode_with_new_symbol: decoding already done\n")); + return OF_STATUS_OK; + } + if (ofcb->available_symbols_tab[new_symbol_esi] != NULL) + { + /* duplicated symbol, ignore */ + OF_TRACE_LVL(2, ("of_rs_decode_with_new_symbol: symbol (esi=%d) duplicated\n", new_symbol_esi)); + goto end; + } + ofcb->available_symbols_tab[new_symbol_esi] = new_symbol; + ofcb->nb_available_symbols++; + if (new_symbol_esi < ofcb->nb_source_symbols) + { + /* remember a new source symbol is available */ + ofcb->nb_available_source_symbols++; + } + + if (ofcb->nb_available_source_symbols == ofcb->nb_source_symbols) + { + /* we received all the k source symbols, so it's finished */ + ofcb->decoding_finished = true; + OF_TRACE_LVL(2, ("of_rs_decode_with_new_symbol: done, all source symbols have been received\n")); + OF_EXIT_FUNCTION + return OF_STATUS_OK; + } + if (ofcb->nb_available_symbols >= ofcb->nb_source_symbols) + { + /* we received a sufficient number of symbols, so let's decode */ + if (of_rs_finish_decoding(ofcb) != OF_STATUS_OK) + { + OF_PRINT_ERROR(("of_rs_decode_with_new_symbol: Error, of_rs_decode failure\n")) + goto error; + } + ASSERT(ofcb->decoding_finished == true); + OF_TRACE_LVL(2, ("of_rs_decode_with_new_symbol: done, decoding successful\n")); + OF_EXIT_FUNCTION + return OF_STATUS_OK; + } +end: + OF_TRACE_LVL(2, ("of_rs_decode_with_new_symbol: okay, but not yet finished\n")); + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + + +of_status_t of_rs_set_available_symbols (of_rs_cb_t* ofcb, + void* const encoding_symbols_tab[]) +{ + UINT32 i; + + OF_ENTER_FUNCTION + ofcb->nb_available_symbols = 0; + ofcb->nb_available_source_symbols = 0; + for (i = 0; i < ofcb->nb_encoding_symbols; i++) + { + if ((ofcb->available_symbols_tab[i] = encoding_symbols_tab[i]) == NULL) + { + continue; + } + if (i < ofcb->nb_source_symbols) + { + ofcb->nb_available_source_symbols++; + } + ofcb->nb_available_symbols++; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_rs_finish_decoding (of_rs_cb_t* ofcb) +{ + UINT32 k; + UINT32 n; + char *tmp_buf[GF_SIZE]; /* copy available source/repair symbol buffers here... */ + int tmp_esi[GF_SIZE]; /* ...and their esi here. In fact we only need k entries + * in these tables, but in order to avoid using malloc (time + * consumming), we use an automatic table of maximum size for + * both tmp_buf[] and tmp_esi[]. */ + INT32 tmp_idx; /* index in tmp_buf[] and tmp_esi[] tabs */ + char *large_buf = NULL; /* single large buffer where to copy all source/repair symbols */ + UINT32 off; /* offset, in unit of characters, in large_buf */ + void **ass_buf; /* tmp pointer to the current source symbol entry in + * available_symbols_tab[] */ + UINT32 ass_esi; /* corresponding available source symbol ESI */ + void **ars_buf; /* tmp pointer to the current repair symbol entry in + * available_symbols_tab[] */ + UINT32 ars_esi; /* corresponding available repair symbol ESI */ + + OF_ENTER_FUNCTION + if (ofcb->decoding_finished) + { + return OF_STATUS_OK; + } + k = ofcb->nb_source_symbols; + n = ofcb->nb_encoding_symbols; + if (ofcb->nb_available_symbols < k) + { + OF_PRINT_ERROR(("of_rs_finish_decoding: Error, nb received symbols < nb source symbols\n")) + OF_EXIT_FUNCTION + return OF_STATUS_FAILURE; + } + if (ofcb->nb_available_source_symbols == k) + { + /* we received all the k source symbols, so it's finished */ + ofcb->decoding_finished = true; + OF_EXIT_FUNCTION + return OF_STATUS_OK; + } + /* + * Copy available source and repair symbols in a single large buffer first. + * NB: this is required by the current FEC codec which modifies + * the tmp_buf buffers!!! + */ + large_buf = (char *) of_malloc(k * ofcb->encoding_symbol_length); + if (large_buf == NULL) + { + goto no_mem; + } + /* Then remember the location of each symbol buffer */ + for (tmp_idx = 0, off = 0; tmp_idx < k; tmp_idx++, off += ofcb->encoding_symbol_length) { + tmp_buf[tmp_idx] = large_buf + off; + } + tmp_idx = 0; /* index in tmp_buf and tmp_esi tables */ + /* + * Copy all the available source symbols (it's essential for decoding speed purposes) and + * a sufficient number of repair symbols to the tmp_buf array. Copy data as well in the + * large_buf buffer. + * Because of of_rs_decode internal details, we put source symbols at their right location + * and fill in the gaps (i.e. erased source symbols) with repair symbols. + */ + ass_esi = 0; + ars_esi = k; + ass_buf = ofcb->available_symbols_tab; + ars_buf = ofcb->available_symbols_tab + k; + for (tmp_idx = 0; tmp_idx < k; tmp_idx++) + { + if (*ass_buf == NULL) + { + /* this source symbol is not available, replace it with a repair */ + while (*ars_buf == NULL) + { + ars_esi++; + ars_buf++; + } + OF_TRACE_LVL(2, ("of_rs_finish_decoding: copy repair with esi=%d in tmp_buf[%d]\n", + ars_esi, tmp_idx)) + memcpy(tmp_buf[tmp_idx], *ars_buf, ofcb->encoding_symbol_length); + tmp_esi[tmp_idx] = ars_esi; + ars_esi++; + ars_buf++; + } + else + { + OF_TRACE_LVL(2, ("of_rs_finish_decoding: copy source with esi=%d in tmp_buf[%d]\n", + ars_esi, tmp_idx)) + memcpy(tmp_buf[tmp_idx], *ass_buf, ofcb->encoding_symbol_length); + tmp_esi[tmp_idx] = ass_esi; + } + ass_esi++; + ass_buf++; + } +#if 0 + for (tmp_idx = 0; tmp_idx < k; tmp_idx++) + { + OF_TRACE_LVL(2, ("Before of_rs_decode: esi=%d, k=%d, tmp_idx=%d\n", tmp_esi[tmp_idx], k, tmp_idx)) + } +#endif + /* + * Let's decode now. + * Create a context first, decode, then release this context. + */ + ofcb->rs_cb = of_rs_new (ofcb->nb_source_symbols, ofcb->nb_encoding_symbols); + if (of_rs_decode (ofcb->rs_cb, (void**)tmp_buf, (int*)tmp_esi, ofcb->encoding_symbol_length) != OF_STATUS_OK) + { + OF_PRINT_ERROR(("of_rs_finish_decoding: Error, of_rs_decode failure\n")) + goto error; + } + of_rs_free (ofcb->rs_cb); + ofcb->rs_cb = NULL; + ofcb->decoding_finished = true; +#if 0 + for (tmp_idx = 0; tmp_idx < k; tmp_idx++) + { + OF_TRACE_LVL(2, ("After of_rs_decode: esi=%d, k=%d, tmp_idx=%d\n", tmp_esi[tmp_idx], k, tmp_idx)) + } +#endif + /* + * finally update the source_symbols_tab table with the decoded source symbols. + */ + for (tmp_idx = 0; tmp_idx < k; tmp_idx++) + { + ASSERT(tmp_idx < k); + ass_buf = &(ofcb->available_symbols_tab[tmp_idx]); + if (*ass_buf != NULL) + { + /* nothing to do, this source symbol has already been received. */ + continue; + } + /* + * This is a new, decoded source symbol. + * First copy it into a permanent buffer. + * Call either the associated callback or allocate memory, and then + * copy the symbol content in it. + */ + if (ofcb->decoded_source_symbol_callback != NULL) + { + *ass_buf = ofcb->decoded_source_symbol_callback (ofcb->context_4_callback, + ofcb->encoding_symbol_length, tmp_idx); + } + else + { + *ass_buf = (void *) of_malloc (ofcb->encoding_symbol_length); + } + if (*ass_buf == NULL) + { + goto no_mem; + } + memcpy(*ass_buf, tmp_buf[tmp_idx], ofcb->encoding_symbol_length); + OF_TRACE_LVL(2, ("of_rs_finish_decoding: decoded source symbol esi=%d from tmp_buf[%d]\n", + tmp_idx, tmp_idx)) + } + of_free(large_buf); + OF_EXIT_FUNCTION + return OF_STATUS_OK; +no_mem: + OF_PRINT_ERROR(("of_rs_finish_decoding: out of memory.\n")) + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + + +bool of_rs_is_decoding_complete (of_rs_cb_t* ofcb) +{ + OF_ENTER_FUNCTION + OF_EXIT_FUNCTION + return ofcb->decoding_finished; +} + + +of_status_t of_rs_get_source_symbols_tab (of_rs_cb_t* ofcb, + void* source_symbols_tab[]) +{ + OF_ENTER_FUNCTION + if (of_rs_is_decoding_complete(ofcb) == false) + { + OF_PRINT_ERROR(("of_rs_get_source_symbols_tab: Error, decoding not complete.\n")) + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; + } +#if 0 + UINT32 i; + for (i = 0; i < ofcb->nb_source_symbols; i++) + { + if (source_symbols_tab[i] == NULL) + { + source_symbols_tab[i] = ofcb->available_symbols_tab[i]; + } + } +#else + memcpy(source_symbols_tab, ofcb->available_symbols_tab, ofcb->nb_source_symbols * sizeof(void*)); +#endif + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +#endif //OF_USE_DECODER + +of_status_t of_rs_set_control_parameter (of_rs_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length) +{ + OF_PRINT_ERROR(("of_rs_set_control_parameter: ERROR, not implemented...\n")) + return OF_STATUS_ERROR; +} + + +of_status_t of_rs_get_control_parameter (of_rs_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length) +{ + OF_ENTER_FUNCTION + switch (type) { + case OF_CTRL_GET_MAX_K: + if (value == NULL || length != sizeof(UINT32)) { + OF_PRINT_ERROR(("%s: OF_CTRL_GET_MAX_K ERROR: null value or bad length (got %d, expected %ld)\n", + __FUNCTION__, length, sizeof(UINT32))) + goto error; + } + *(UINT32*)value = ofcb->max_nb_source_symbols; + OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_K (%d)\n", __FUNCTION__, *(UINT32*)value)) + break; + + case OF_CTRL_GET_MAX_N: + if (value == NULL || length != sizeof(UINT32)) { + OF_PRINT_ERROR(("%s: OF_CTRL_GET_MAX_N ERROR: null value or bad length (got %d, expected %ld)\n", + __FUNCTION__, length, sizeof(UINT32))) + goto error; + } + *(UINT32*)value = ofcb->max_nb_encoding_symbols; + OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_N (%d)\n", __FUNCTION__, *(UINT32*)value)) + break; + + default: + OF_PRINT_ERROR(("%s: unknown type (%d)\n", __FUNCTION__, type)) + goto error; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + +#endif //#ifdef OF_USE_REED_SOLOMON_CODEC diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8_api.h b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8_api.h new file mode 100755 index 0000000..647dd5b --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8_api.h @@ -0,0 +1,59 @@ +/* $Id: of_reed-solomon_gf_2_8_api.h 72 2012-04-13 13:27:26Z detchart $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifdef OF_USE_REED_SOLOMON_CODEC + +#ifndef OF_REED_SOLOMON_GF_2_8_API_H +#define OF_REED_SOLOMON_GF_2_8_API_H + + +/** + * \struct of_rs_parameters_t + * \brief Reed-Solomon stable codec specific FEC parameter structure. + * This structure contains the pieces of information required to initialize a codec instance, + * using the of_set_fec_parameters() function. + */ +typedef struct of_rs_parameters +{ + UINT32 nb_source_symbols; /* must be 1st item */ + UINT32 nb_repair_symbols; /* must be 2nd item */ + UINT32 encoding_symbol_length; /* must be 3rd item */ + /* + * FEC codec id specific attributes follow... + */ + +} of_rs_parameters_t; + +#endif /* OF_REED_SOLOMON_GF_2_8_API_H */ + +#endif //#ifdef OF_USE_REED_SOLOMON_CODEC \ No newline at end of file diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8_includes.h b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8_includes.h new file mode 100644 index 0000000..9b281b3 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_8/of_reed-solomon_gf_2_8_includes.h @@ -0,0 +1,57 @@ +/* $Id: of_reed-solomon_gf_2_8_includes.h 189 2014-07-16 08:53:50Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef OF_REED_SOLOMON_INCLUDES_H +#define OF_REED_SOLOMON_INCLUDES_H + +#include +#include +#include +#include + +#include "../../lib_common/of_openfec_api.h" + +/* + * the remaining includes will only be considered if of_codec_profile.h is + * included above by of_openfec_api.h => of_openfec_profile.h + */ +#ifdef OF_USE_REED_SOLOMON_CODEC + +#include "../../lib_common/linear_binary_codes_utils/of_linear_binary_code.h" + +#include "of_reed-solomon_gf_2_8_api.h" +#include "of_reed-solomon_gf_2_8.h" + +#endif //OF_USE_REED_SOLOMON_CODEC +#endif //OF_REED_SOLOMON_INCLUDES_H + diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_4.c b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_4.c new file mode 100644 index 0000000..1eb4cf6 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_4.c @@ -0,0 +1,413 @@ +/* $Id: algebra_2_4.c 185 2014-07-15 09:57:16Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it) + * + * Portions derived from code by Phil Karn (karn@ka9q.ampr.org), + * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari + * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ +#include "algebra_2_4.h" + +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + +#define UNROLL 16 +#define USE_GF_MULC register gf * __gf_mulc_ +#define GF_MULC0(c) __gf_mulc_ = (gf*)of_gf_2_4_mul_table[c] +#define GF_OPT_MULC0(c) __gf_mulc_ = (gf*)of_gf_2_4_opt_mul_table[c] +#define GF_ADDMULC(dst, x) {dst ^= __gf_mulc_[x];} +#define GF_ADDMULC_COMPACT(dst,x) {dst = (dst>>4 ^ __gf_mulc_[x>>4])<<4 |(dst & 0x0F ^ __gf_mulc_[x & 0x0F]); } + +/* + * addmul() computes dst[] = dst[] + c * src[] + * This is used often, so better optimize it! Currently the loop is + * unrolled 16 times, a good value for 486 and pentium-class machines. + * The case c=0 is also optimized, whereas c=1 is not. These + * calls are unfrequent in my typical apps so I did not bother. + */ + +/* + * of_galois_field_2_4_addmul1() computes dst[] = dst[] + c * src[] when src and dst + * both point to vectors where each GF(2^4) element is stored in an unsigned char. + * This is used for matrix operations where no source/repair symbol is involved. + */ +void of_galois_field_2_4_addmul1(gf *dst1, gf *src1, gf c, int sz) +{ + USE_GF_MULC ; + register gf *dst = dst1, *src = src1 ; + gf *lim = &dst[sz - UNROLL + 1] ; +#if ((defined (__LP64__) || (__WORDSIZE == 64)) && !defined (OF_RS_2M_USE_32BITS)) + UINT64 tmp; + UINT64 *dst_64 = (UINT64*)dst1; +#else + UINT32 tmp; + UINT32 *dst_32 = (UINT32*)dst1; +#endif + GF_MULC0 (c) ; + +#if (UNROLL > 1) /* unrolling by 16 is quite effective on the pentium */ + for (; dst < lim ;dst += UNROLL, src += UNROLL) + { +#if ((defined (__LP64__) || (__WORDSIZE == 64)) && !defined (OF_RS_2M_USE_32BITS)) + /* perform 64-bit operations for improved performances on 64-bit systems */ + tmp = ((UINT64)__gf_mulc_[src[0]]) | ((UINT64)__gf_mulc_[src[1]]<<8) | ((UINT64)__gf_mulc_[src[2]]<<16) | + ((UINT64)__gf_mulc_[src[3]]<<24) | ((UINT64)__gf_mulc_[src[4]]<<32) | ((UINT64)__gf_mulc_[src[5]]<<40) | + ((UINT64)__gf_mulc_[src[6]]<<48) | ((UINT64)__gf_mulc_[src[7]]<<56) ; + *dst_64 ^= tmp; + dst_64++; + tmp = ((UINT64)__gf_mulc_[src[8]]) | ((UINT64)__gf_mulc_[src[9]]<<8) | ((UINT64)__gf_mulc_[src[10]]<<16) | + ((UINT64)__gf_mulc_[src[11]]<<24) | ((UINT64)__gf_mulc_[src[12]]<<32) | ((UINT64)__gf_mulc_[src[13]]<<40) | + ((UINT64)__gf_mulc_[src[14]]<<48) | ((UINT64)__gf_mulc_[src[15]]<<56) ; + *dst_64 ^= tmp; + dst_64++; +#else + /* otherwise perform 32-bit operations on 32-bit systems */ + tmp = ((UINT32)__gf_mulc_[src[0]]) | ((UINT32)__gf_mulc_[src[1]]<<8) | ((UINT32)__gf_mulc_[src[2]]<<16) | + ((UINT32)__gf_mulc_[src[3]]<<24); + *dst_32 ^= tmp; + dst_32++; + tmp = ((UINT32)__gf_mulc_[src[4]]) | ((UINT32)__gf_mulc_[src[5]]<<8) | ((UINT32)__gf_mulc_[src[6]]<<16) | + ((UINT32)__gf_mulc_[src[7]]<<24); + *dst_32 ^= tmp; + dst_32++; + tmp = ((UINT32)__gf_mulc_[src[8]]) | ((UINT32)__gf_mulc_[src[9]]<<8) | ((UINT32)__gf_mulc_[src[10]]<<16) | + ((UINT32)__gf_mulc_[src[11]]<<24); + *dst_32 ^= tmp; + dst_32++; + tmp = ((UINT32)__gf_mulc_[src[12]]) | ((UINT32)__gf_mulc_[src[13]]<<8) | ((UINT32)__gf_mulc_[src[14]]<<16) | + ((UINT32)__gf_mulc_[src[15]]<<24); + *dst_32 ^= tmp; + dst_32++; +#endif + } +#endif + lim += UNROLL - 1 ; + for (; dst < lim; dst++, src++) { + /* final components, since sz is not necessarily a multiple of UNROLL */ + GF_ADDMULC (*dst , *src); + } +} + + +/* + * of_galois_field_2_4_addmul1_compact() computes dst[] = dst[] + c * src[] when src and dst + * both point to vectors where each GF(2^4) element is actually stored in 4-bits. + * Said differently, there are two elements per byte. + * This is used for matrix operations where source/repair symbols are involved (encoding + * and decoding). + * This function has been optimized so that two elements are accessed each time, and the + * mulc table works on two elements at a time. This is a highly effective solution which + * warrants high performances. + */ +void of_galois_field_2_4_addmul1_compact (gf *dst1, gf *src1, gf c, int sz) +{ + USE_GF_MULC ; + register gf *dst = dst1, *src = src1 ; + gf *lim = &dst[sz - UNROLL + 1] ; +#if ((defined (__LP64__) || (__WORDSIZE == 64)) && !defined (OF_RS_2M_USE_32BITS)) + UINT64 tmp; + UINT64 *dst_64 = (UINT64*)dst1; +#else + UINT32 tmp; + UINT32 *dst_32 = (UINT32*)dst1; +#endif + GF_OPT_MULC0(c); + +#if (UNROLL > 1) /* unrolling by 16 is quite effective on the pentium */ + for (; dst < lim ;dst += UNROLL, src += UNROLL) + { +#if ((defined (__LP64__) || (__WORDSIZE == 64)) && !defined (OF_RS_2M_USE_32BITS)) + /* perform 64-bit operations for improved performances on 64-bit systems */ + tmp = ((UINT64)__gf_mulc_[src[0]]) | ((UINT64)__gf_mulc_[src[1]]<<8) | ((UINT64)__gf_mulc_[src[2]]<<16) | + ((UINT64)__gf_mulc_[src[3]]<<24) | ((UINT64)__gf_mulc_[src[4]]<<32) | ((UINT64)__gf_mulc_[src[5]]<<40) | + ((UINT64)__gf_mulc_[src[6]]<<48) | ((UINT64)__gf_mulc_[src[7]]<<56) ; + *dst_64 ^= tmp; + dst_64++; + tmp = ((UINT64)__gf_mulc_[src[8]]) | ((UINT64)__gf_mulc_[src[9]]<<8) | ((UINT64)__gf_mulc_[src[10]]<<16) | + ((UINT64)__gf_mulc_[src[11]]<<24) | ((UINT64)__gf_mulc_[src[12]]<<32) | ((UINT64)__gf_mulc_[src[13]]<<40) | + ((UINT64)__gf_mulc_[src[14]]<<48) | ((UINT64)__gf_mulc_[src[15]]<<56) ; + *dst_64 ^= tmp; + dst_64++; +#else + /* otherwise perform 32-bit operations on 32-bit systems */ + tmp = ((UINT32)__gf_mulc_[src[0]]) | ((UINT32)__gf_mulc_[src[1]]<<8) | ((UINT32)__gf_mulc_[src[2]]<<16) | + ((UINT32)__gf_mulc_[src[3]]<<24); + *dst_32 ^= tmp; + dst_32++; + tmp = ((UINT32)__gf_mulc_[src[4]]) | ((UINT32)__gf_mulc_[src[5]]<<8) | ((UINT32)__gf_mulc_[src[6]]<<16) | + ((UINT32)__gf_mulc_[src[7]]<<24); + *dst_32 ^= tmp; + dst_32++; + tmp = ((UINT32)__gf_mulc_[src[8]]) | ((UINT32)__gf_mulc_[src[9]]<<8) | ((UINT32)__gf_mulc_[src[10]]<<16) | + ((UINT32)__gf_mulc_[src[11]]<<24); + *dst_32 ^= tmp; + dst_32++; + tmp = ((UINT32)__gf_mulc_[src[12]]) | ((UINT32)__gf_mulc_[src[13]]<<8) | ((UINT32)__gf_mulc_[src[14]]<<16) | + ((UINT32)__gf_mulc_[src[15]]<<24); + *dst_32 ^= tmp; + dst_32++; +#endif + } +#endif + lim += UNROLL - 1 ; + for (; dst < lim; dst++, src++) { + /* final components, since sz is not necessarily a multiple of UNROLL */ + GF_ADDMULC_COMPACT (*dst , *src); + } +} + + +/* + * computes C = AB where A is n*k, B is k*m, C is n*m + */ +void of_galois_field_2_4_matmul (gf *a, gf *b, gf *c, int n, int k, int m) { + OF_ENTER_FUNCTION + int row, col, i ; + + for (row = 0; row < n ; row++) + { + for (col = 0; col < m ; col++) + { + gf *pa = &a[ row * k ]; + gf *pb = &b[ col ]; + gf acc = 0 ; + for (i = 0; i < k ; i++, pa++, pb += m) + acc ^= of_gf_2_4_mul_table[*pa][ *pb] ; + c[ row * m + col ] = acc ; + } + } + OF_EXIT_FUNCTION +} + + +int of_galois_field_2_4_invert_mat (of_galois_field_code_cb_t* ofcb, gf *src, int k) { + OF_ENTER_FUNCTION + gf c, *p ; + int irow, icol, row, col, i, ix ; + + int error = 1 ; + int *indxc = (int*) of_malloc (k * sizeof (int)); + int *indxr = (int*) of_malloc (k * sizeof (int)); + int *ipiv = (int*) of_malloc (k * sizeof (int)); + gf *id_row = (gf*) of_malloc (1 * k * sizeof(gf)); + gf *temp_row = (gf*) of_malloc (1 * k * sizeof(gf)); + + bzero (id_row, k*sizeof (gf)); + /* + * ipiv marks elements already used as pivots. + */ + for (i = 0; i < k ; i++) + ipiv[i] = 0 ; + + for (col = 0; col < k ; col++) + { + gf *pivot_row ; + /* + * Zeroing column 'col', look for a non-zero element. + * First try on the diagonal, if it fails, look elsewhere. + */ + irow = icol = -1 ; + if (ipiv[col] != 1 && src[col*k + col] != 0) + { + irow = col ; + icol = col ; + goto found_piv ; + } + for (row = 0 ; row < k ; row++) + { + if (ipiv[row] != 1) + { + for (ix = 0 ; ix < k ; ix++) + { + if (ipiv[ix] == 0) + { + if (src[row*k + ix] != 0) + { + irow = row ; + icol = ix ; + goto found_piv ; + } + } + else + if (ipiv[ix] > 1) + { + // PRINT_ERR((mcl_stderr, "singular matrix\n")) + goto fail ; + } + } + } + } + if (icol == -1) + { + // PRINT_ERR((mcl_stderr, "XXX pivot not found!\n")) + goto fail ; + } + found_piv: + ++ (ipiv[icol]) ; + /* + * swap rows irow and icol, so afterwards the diagonal + * element will be correct. Rarely done, not worth + * optimizing. + */ + if (irow != icol) + { + for (ix = 0 ; ix < k ; ix++) + { + SWAP (src[irow*k + ix], src[icol*k + ix], gf) ; + } + } + indxr[col] = irow ; + indxc[col] = icol ; + pivot_row = &src[icol*k] ; + c = pivot_row[icol] ; + if (c == 0) + { + OF_PRINT_ERROR(("singular matrix 2\n")) + goto fail ; + } + if (c != 1) + { + /* otherwhise this is a NOP */ + /* + * this is done often , but optimizing is not so + * fruitful, at least in the obvious ways (unrolling) + */ + c = of_gf_2_4_inv[ c ] ; + pivot_row[icol] = 1 ; + for (ix = 0 ; ix < k ; ix++) + pivot_row[ix] = of_gf_2_4_mul_table[c][ pivot_row[ix]]; + } + /* + * from all rows, remove multiples of the selected row + * to zero the relevant entry (in fact, the entry is not zero + * because we know it must be zero). + * (Here, if we know that the pivot_row is the identity, + * we can optimize the addmul). + */ + id_row[icol] = 1; + if (bcmp (pivot_row, id_row, k*sizeof (gf)) != 0) + { + for (p = src, ix = 0 ; ix < k ; ix++, p += k) + { + if (ix != icol) + { + c = p[icol] ; + p[icol] = 0 ; + if (c != 0) + of_galois_field_2_4_addmul1 (p, pivot_row, c, k); + } + } + } + id_row[icol] = 0; + } /* done all columns */ + for (col = k - 1 ; col >= 0 ; col--) + { + if (indxr[col] < 0 || indxr[col] >= k) + OF_PRINT_ERROR(("AARGH, indxr[col] %d\n", indxr[col])) + else + if (indxc[col] < 0 || indxc[col] >= k) + OF_PRINT_ERROR(( "AARGH, indxc[col] %d\n", indxc[col])) + else + if (indxr[col] != indxc[col]) + { + for (row = 0 ; row < k ; row++) + { + SWAP (src[row*k + indxr[col]], src[row*k + indxc[col]], gf) ; + } + } + } + error = 0 ; +fail: + of_free (indxc); + of_free (indxr); + of_free (ipiv); + of_free (id_row); + of_free (temp_row); + OF_EXIT_FUNCTION + return error ; +} + +int of_galois_field_2_4_invert_vdm (of_galois_field_code_cb_t* ofcb, gf *src, int k) { + OF_ENTER_FUNCTION + int i, j, row, col ; + gf *b, *c, *p; + gf t, xx ; + + if (k == 1) /* degenerate case, matrix must be p^0 = 1 */ + return 0 ; + /* + * c holds the coefficient of P(x) = Prod (x - p_i), i=0..k-1 + * b holds the coefficient for the matrix inversion + */ + c = (gf*) of_malloc(1 * k * sizeof(gf)); + b = (gf*) of_malloc(1 * k * sizeof(gf)); + p = (gf*) of_malloc(1 * k * sizeof(gf)); + + for (j = 1, i = 0 ; i < k ; i++, j += k) + { + c[i] = 0 ; + p[i] = src[j] ; /* p[i] */ + } + /* + * construct coeffs. recursively. We know c[k] = 1 (implicit) + * and start P_0 = x - p_0, then at each stage multiply by + * x - p_i generating P_i = x P_{i-1} - p_i P_{i-1} + * After k steps we are done. + */ + c[k-1] = p[0] ; /* really -p(0), but x = -x in GF(2^m) */ + for (i = 1 ; i < k ; i++) + { + gf p_i = p[i] ; /* see above comment */ + for (j = k - 1 - (i - 1) ; j < k - 1 ; j++) + c[j] ^= of_gf_2_4_mul_table[p_i][ c[j+1]] ; + c[k-1] ^= p_i ; + } + + for (row = 0 ; row < k ; row++) + { + /* + * synthetic division etc. + */ + xx = p[row] ; + t = 1 ; + b[k-1] = 1 ; /* this is in fact c[k] */ + for (i = k - 2 ; i >= 0 ; i--) + { + b[i] = c[i+1] ^ of_gf_2_4_mul_table[xx][ b[i+1]] ; + t = of_gf_2_4_mul_table[xx][ t] ^ b[i] ; + } + for (col = 0 ; col < k ; col++) + src[col*k + row] = of_gf_2_4_mul_table [of_gf_2_4_inv[t]][ b[col]]; + } + of_free (c); + of_free (b); + of_free (p); + OF_EXIT_FUNCTION + return 0 ; +} + +#endif diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_4.h b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_4.h new file mode 100644 index 0000000..e076b6a --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_4.h @@ -0,0 +1,114 @@ +/* $Id: algebra_2_4.h 207 2014-12-10 19:47:50Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it) + * + * Portions derived from code by Phil Karn (karn@ka9q.ampr.org), + * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari + * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ + +#ifndef OF_GALOIS_FIELD_ALGEBRA_2_4_H +#define OF_GALOIS_FIELD_ALGEBRA_2_4_H + +#include "../of_reed-solomon_gf_2_m_includes.h" + + +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + + +#define SWAP(a,b,t) {t tmp; tmp=a; a=b; b=tmp;} + +static const gf of_gf_2_4_log[] = {15,0,1,4,2,8,5,10,3,14,9,7,6,13,11,12}; + +static const gf of_gf_2_4_exp[] = {1,2,4,8,3,6,12,11,5,10,7,14,15,13,9,1}; +static const gf of_gf_2_4_inv[] = {0,1,9,14,13,11,7,6,15,2,12,5,10,4,3,8}; +static const gf of_gf_2_4_mul_table[][16]={ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 2, 4, 6, 8, 10, 12, 14, 3, 1, 7, 5, 11, 9, 15, 13}, + {0, 3, 6, 5, 12, 15, 10, 9, 11, 8, 13, 14, 7, 4, 1, 2}, + {0, 4, 8, 12, 3, 7, 11, 15, 6, 2, 14, 10, 5, 1, 13, 9}, + {0, 5, 10, 15, 7, 2, 13, 8, 14, 11, 4, 1, 9, 12, 3, 6}, + {0, 6, 12, 10, 11, 13, 7, 1, 5, 3, 9, 15, 14, 8, 2, 4}, + {0, 7, 14, 9, 15, 8, 1, 6, 13, 10, 3, 4, 2, 5, 12, 11}, + {0, 8, 3, 11, 6, 14, 5, 13, 12, 4, 15, 7, 10, 2, 9, 1}, + {0, 9, 1, 8, 2, 11, 3, 10, 4, 13, 5, 12, 6, 15, 7, 14}, + {0, 10, 7, 13, 14, 4, 9, 3, 15, 5, 8, 2, 1, 11, 6, 12}, + {0, 11, 5, 14, 10, 1, 15, 4, 7, 12, 2, 9, 13, 6, 8, 3}, + {0, 12, 11, 7, 5, 9, 14, 2, 10, 6, 1, 13, 15, 3, 4, 8}, + {0, 13, 9, 4, 1, 12, 8, 5, 2, 15, 11, 6, 3, 14, 10, 7}, + {0, 14, 15, 1, 13, 3, 2, 12, 9, 7, 6, 8, 4, 10, 11, 5}, + {0, 15, 13, 2, 9, 6, 4, 11, 1, 14, 12, 3, 8, 7, 5, 10}}; + +static const gf of_gf_2_4_opt_mul_table[][256] = { + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}, + {0,2,4,6,8,10,12,14,3,1,7,5,11,9,15,13,32,34,36,38,40,42,44,46,35,33,39,37,43,41,47,45,64,66,68,70,72,74,76,78,67,65,71,69,75,73,79,77,96,98,100,102,104,106,108,110,99,97,103,101,107,105,111,109,128,130,132,134,136,138,140,142,131,129,135,133,139,137,143,141,160,162,164,166,168,170,172,174,163,161,167,165,171,169,175,173,192,194,196,198,200,202,204,206,195,193,199,197,203,201,207,205,224,226,228,230,232,234,236,238,227,225,231,229,235,233,239,237,48,50,52,54,56,58,60,62,51,49,55,53,59,57,63,61,16,18,20,22,24,26,28,30,19,17,23,21,27,25,31,29,112,114,116,118,120,122,124,126,115,113,119,117,123,121,127,125,80,82,84,86,88,90,92,94,83,81,87,85,91,89,95,93,176,178,180,182,184,186,188,190,179,177,183,181,187,185,191,189,144,146,148,150,152,154,156,158,147,145,151,149,155,153,159,157,240,242,244,246,248,250,252,254,243,241,247,245,251,249,255,253,208,210,212,214,216,218,220,222,211,209,215,213,219,217,223,221}, + {0,3,6,5,12,15,10,9,11,8,13,14,7,4,1,2,48,51,54,53,60,63,58,57,59,56,61,62,55,52,49,50,96,99,102,101,108,111,106,105,107,104,109,110,103,100,97,98,80,83,86,85,92,95,90,89,91,88,93,94,87,84,81,82,192,195,198,197,204,207,202,201,203,200,205,206,199,196,193,194,240,243,246,245,252,255,250,249,251,248,253,254,247,244,241,242,160,163,166,165,172,175,170,169,171,168,173,174,167,164,161,162,144,147,150,149,156,159,154,153,155,152,157,158,151,148,145,146,176,179,182,181,188,191,186,185,187,184,189,190,183,180,177,178,128,131,134,133,140,143,138,137,139,136,141,142,135,132,129,130,208,211,214,213,220,223,218,217,219,216,221,222,215,212,209,210,224,227,230,229,236,239,234,233,235,232,237,238,231,228,225,226,112,115,118,117,124,127,122,121,123,120,125,126,119,116,113,114,64,67,70,69,76,79,74,73,75,72,77,78,71,68,65,66,16,19,22,21,28,31,26,25,27,24,29,30,23,20,17,18,32,35,38,37,44,47,42,41,43,40,45,46,39,36,33,34}, + {0,4,8,12,3,7,11,15,6,2,14,10,5,1,13,9,64,68,72,76,67,71,75,79,70,66,78,74,69,65,77,73,128,132,136,140,131,135,139,143,134,130,142,138,133,129,141,137,192,196,200,204,195,199,203,207,198,194,206,202,197,193,205,201,48,52,56,60,51,55,59,63,54,50,62,58,53,49,61,57,112,116,120,124,115,119,123,127,118,114,126,122,117,113,125,121,176,180,184,188,179,183,187,191,182,178,190,186,181,177,189,185,240,244,248,252,243,247,251,255,246,242,254,250,245,241,253,249,96,100,104,108,99,103,107,111,102,98,110,106,101,97,109,105,32,36,40,44,35,39,43,47,38,34,46,42,37,33,45,41,224,228,232,236,227,231,235,239,230,226,238,234,229,225,237,233,160,164,168,172,163,167,171,175,166,162,174,170,165,161,173,169,80,84,88,92,83,87,91,95,86,82,94,90,85,81,93,89,16,20,24,28,19,23,27,31,22,18,30,26,21,17,29,25,208,212,216,220,211,215,219,223,214,210,222,218,213,209,221,217,144,148,152,156,147,151,155,159,150,146,158,154,149,145,157,153}, + {0,5,10,15,7,2,13,8,14,11,4,1,9,12,3,6,80,85,90,95,87,82,93,88,94,91,84,81,89,92,83,86,160,165,170,175,167,162,173,168,174,171,164,161,169,172,163,166,240,245,250,255,247,242,253,248,254,251,244,241,249,252,243,246,112,117,122,127,119,114,125,120,126,123,116,113,121,124,115,118,32,37,42,47,39,34,45,40,46,43,36,33,41,44,35,38,208,213,218,223,215,210,221,216,222,219,212,209,217,220,211,214,128,133,138,143,135,130,141,136,142,139,132,129,137,140,131,134,224,229,234,239,231,226,237,232,238,235,228,225,233,236,227,230,176,181,186,191,183,178,189,184,190,187,180,177,185,188,179,182,64,69,74,79,71,66,77,72,78,75,68,65,73,76,67,70,16,21,26,31,23,18,29,24,30,27,20,17,25,28,19,22,144,149,154,159,151,146,157,152,158,155,148,145,153,156,147,150,192,197,202,207,199,194,205,200,206,203,196,193,201,204,195,198,48,53,58,63,55,50,61,56,62,59,52,49,57,60,51,54,96,101,106,111,103,98,109,104,110,107,100,97,105,108,99,102}, + {0,6,12,10,11,13,7,1,5,3,9,15,14,8,2,4,96,102,108,106,107,109,103,97,101,99,105,111,110,104,98,100,192,198,204,202,203,205,199,193,197,195,201,207,206,200,194,196,160,166,172,170,171,173,167,161,165,163,169,175,174,168,162,164,176,182,188,186,187,189,183,177,181,179,185,191,190,184,178,180,208,214,220,218,219,221,215,209,213,211,217,223,222,216,210,212,112,118,124,122,123,125,119,113,117,115,121,127,126,120,114,116,16,22,28,26,27,29,23,17,21,19,25,31,30,24,18,20,80,86,92,90,91,93,87,81,85,83,89,95,94,88,82,84,48,54,60,58,59,61,55,49,53,51,57,63,62,56,50,52,144,150,156,154,155,157,151,145,149,147,153,159,158,152,146,148,240,246,252,250,251,253,247,241,245,243,249,255,254,248,242,244,224,230,236,234,235,237,231,225,229,227,233,239,238,232,226,228,128,134,140,138,139,141,135,129,133,131,137,143,142,136,130,132,32,38,44,42,43,45,39,33,37,35,41,47,46,40,34,36,64,70,76,74,75,77,71,65,69,67,73,79,78,72,66,68}, + {0,7,14,9,15,8,1,6,13,10,3,4,2,5,12,11,112,119,126,121,127,120,113,118,125,122,115,116,114,117,124,123,224,231,238,233,239,232,225,230,237,234,227,228,226,229,236,235,144,151,158,153,159,152,145,150,157,154,147,148,146,149,156,155,240,247,254,249,255,248,241,246,253,250,243,244,242,245,252,251,128,135,142,137,143,136,129,134,141,138,131,132,130,133,140,139,16,23,30,25,31,24,17,22,29,26,19,20,18,21,28,27,96,103,110,105,111,104,97,102,109,106,99,100,98,101,108,107,208,215,222,217,223,216,209,214,221,218,211,212,210,213,220,219,160,167,174,169,175,168,161,166,173,170,163,164,162,165,172,171,48,55,62,57,63,56,49,54,61,58,51,52,50,53,60,59,64,71,78,73,79,72,65,70,77,74,67,68,66,69,76,75,32,39,46,41,47,40,33,38,45,42,35,36,34,37,44,43,80,87,94,89,95,88,81,86,93,90,83,84,82,85,92,91,192,199,206,201,207,200,193,198,205,202,195,196,194,197,204,203,176,183,190,185,191,184,177,182,189,186,179,180,178,181,188,187}, + {0,8,3,11,6,14,5,13,12,4,15,7,10,2,9,1,128,136,131,139,134,142,133,141,140,132,143,135,138,130,137,129,48,56,51,59,54,62,53,61,60,52,63,55,58,50,57,49,176,184,179,187,182,190,181,189,188,180,191,183,186,178,185,177,96,104,99,107,102,110,101,109,108,100,111,103,106,98,105,97,224,232,227,235,230,238,229,237,236,228,239,231,234,226,233,225,80,88,83,91,86,94,85,93,92,84,95,87,90,82,89,81,208,216,211,219,214,222,213,221,220,212,223,215,218,210,217,209,192,200,195,203,198,206,197,205,204,196,207,199,202,194,201,193,64,72,67,75,70,78,69,77,76,68,79,71,74,66,73,65,240,248,243,251,246,254,245,253,252,244,255,247,250,242,249,241,112,120,115,123,118,126,117,125,124,116,127,119,122,114,121,113,160,168,163,171,166,174,165,173,172,164,175,167,170,162,169,161,32,40,35,43,38,46,37,45,44,36,47,39,42,34,41,33,144,152,147,155,150,158,149,157,156,148,159,151,154,146,153,145,16,24,19,27,22,30,21,29,28,20,31,23,26,18,25,17}, + {0,9,1,8,2,11,3,10,4,13,5,12,6,15,7,14,144,153,145,152,146,155,147,154,148,157,149,156,150,159,151,158,16,25,17,24,18,27,19,26,20,29,21,28,22,31,23,30,128,137,129,136,130,139,131,138,132,141,133,140,134,143,135,142,32,41,33,40,34,43,35,42,36,45,37,44,38,47,39,46,176,185,177,184,178,187,179,186,180,189,181,188,182,191,183,190,48,57,49,56,50,59,51,58,52,61,53,60,54,63,55,62,160,169,161,168,162,171,163,170,164,173,165,172,166,175,167,174,64,73,65,72,66,75,67,74,68,77,69,76,70,79,71,78,208,217,209,216,210,219,211,218,212,221,213,220,214,223,215,222,80,89,81,88,82,91,83,90,84,93,85,92,86,95,87,94,192,201,193,200,194,203,195,202,196,205,197,204,198,207,199,206,96,105,97,104,98,107,99,106,100,109,101,108,102,111,103,110,240,249,241,248,242,251,243,250,244,253,245,252,246,255,247,254,112,121,113,120,114,123,115,122,116,125,117,124,118,127,119,126,224,233,225,232,226,235,227,234,228,237,229,236,230,239,231,238}, + {0,10,7,13,14,4,9,3,15,5,8,2,1,11,6,12,160,170,167,173,174,164,169,163,175,165,168,162,161,171,166,172,112,122,119,125,126,116,121,115,127,117,120,114,113,123,118,124,208,218,215,221,222,212,217,211,223,213,216,210,209,219,214,220,224,234,231,237,238,228,233,227,239,229,232,226,225,235,230,236,64,74,71,77,78,68,73,67,79,69,72,66,65,75,70,76,144,154,151,157,158,148,153,147,159,149,152,146,145,155,150,156,48,58,55,61,62,52,57,51,63,53,56,50,49,59,54,60,240,250,247,253,254,244,249,243,255,245,248,242,241,251,246,252,80,90,87,93,94,84,89,83,95,85,88,82,81,91,86,92,128,138,135,141,142,132,137,131,143,133,136,130,129,139,134,140,32,42,39,45,46,36,41,35,47,37,40,34,33,43,38,44,16,26,23,29,30,20,25,19,31,21,24,18,17,27,22,28,176,186,183,189,190,180,185,179,191,181,184,178,177,187,182,188,96,106,103,109,110,100,105,99,111,101,104,98,97,107,102,108,192,202,199,205,206,196,201,195,207,197,200,194,193,203,198,204}, + {0,11,5,14,10,1,15,4,7,12,2,9,13,6,8,3,176,187,181,190,186,177,191,180,183,188,178,185,189,182,184,179,80,91,85,94,90,81,95,84,87,92,82,89,93,86,88,83,224,235,229,238,234,225,239,228,231,236,226,233,237,230,232,227,160,171,165,174,170,161,175,164,167,172,162,169,173,166,168,163,16,27,21,30,26,17,31,20,23,28,18,25,29,22,24,19,240,251,245,254,250,241,255,244,247,252,242,249,253,246,248,243,64,75,69,78,74,65,79,68,71,76,66,73,77,70,72,67,112,123,117,126,122,113,127,116,119,124,114,121,125,118,120,115,192,203,197,206,202,193,207,196,199,204,194,201,205,198,200,195,32,43,37,46,42,33,47,36,39,44,34,41,45,38,40,35,144,155,149,158,154,145,159,148,151,156,146,153,157,150,152,147,208,219,213,222,218,209,223,212,215,220,210,217,221,214,216,211,96,107,101,110,106,97,111,100,103,108,98,105,109,102,104,99,128,139,133,142,138,129,143,132,135,140,130,137,141,134,136,131,48,59,53,62,58,49,63,52,55,60,50,57,61,54,56,51}, + {0,12,11,7,5,9,14,2,10,6,1,13,15,3,4,8,192,204,203,199,197,201,206,194,202,198,193,205,207,195,196,200,176,188,187,183,181,185,190,178,186,182,177,189,191,179,180,184,112,124,123,119,117,121,126,114,122,118,113,125,127,115,116,120,80,92,91,87,85,89,94,82,90,86,81,93,95,83,84,88,144,156,155,151,149,153,158,146,154,150,145,157,159,147,148,152,224,236,235,231,229,233,238,226,234,230,225,237,239,227,228,232,32,44,43,39,37,41,46,34,42,38,33,45,47,35,36,40,160,172,171,167,165,169,174,162,170,166,161,173,175,163,164,168,96,108,107,103,101,105,110,98,106,102,97,109,111,99,100,104,16,28,27,23,21,25,30,18,26,22,17,29,31,19,20,24,208,220,219,215,213,217,222,210,218,214,209,221,223,211,212,216,240,252,251,247,245,249,254,242,250,246,241,253,255,243,244,248,48,60,59,55,53,57,62,50,58,54,49,61,63,51,52,56,64,76,75,71,69,73,78,66,74,70,65,77,79,67,68,72,128,140,139,135,133,137,142,130,138,134,129,141,143,131,132,136}, + {0,13,9,4,1,12,8,5,2,15,11,6,3,14,10,7,208,221,217,212,209,220,216,213,210,223,219,214,211,222,218,215,144,157,153,148,145,156,152,149,146,159,155,150,147,158,154,151,64,77,73,68,65,76,72,69,66,79,75,70,67,78,74,71,16,29,25,20,17,28,24,21,18,31,27,22,19,30,26,23,192,205,201,196,193,204,200,197,194,207,203,198,195,206,202,199,128,141,137,132,129,140,136,133,130,143,139,134,131,142,138,135,80,93,89,84,81,92,88,85,82,95,91,86,83,94,90,87,32,45,41,36,33,44,40,37,34,47,43,38,35,46,42,39,240,253,249,244,241,252,248,245,242,255,251,246,243,254,250,247,176,189,185,180,177,188,184,181,178,191,187,182,179,190,186,183,96,109,105,100,97,108,104,101,98,111,107,102,99,110,106,103,48,61,57,52,49,60,56,53,50,63,59,54,51,62,58,55,224,237,233,228,225,236,232,229,226,239,235,230,227,238,234,231,160,173,169,164,161,172,168,165,162,175,171,166,163,174,170,167,112,125,121,116,113,124,120,117,114,127,123,118,115,126,122,119}, + {0,14,15,1,13,3,2,12,9,7,6,8,4,10,11,5,224,238,239,225,237,227,226,236,233,231,230,232,228,234,235,229,240,254,255,241,253,243,242,252,249,247,246,248,244,250,251,245,16,30,31,17,29,19,18,28,25,23,22,24,20,26,27,21,208,222,223,209,221,211,210,220,217,215,214,216,212,218,219,213,48,62,63,49,61,51,50,60,57,55,54,56,52,58,59,53,32,46,47,33,45,35,34,44,41,39,38,40,36,42,43,37,192,206,207,193,205,195,194,204,201,199,198,200,196,202,203,197,144,158,159,145,157,147,146,156,153,151,150,152,148,154,155,149,112,126,127,113,125,115,114,124,121,119,118,120,116,122,123,117,96,110,111,97,109,99,98,108,105,103,102,104,100,106,107,101,128,142,143,129,141,131,130,140,137,135,134,136,132,138,139,133,64,78,79,65,77,67,66,76,73,71,70,72,68,74,75,69,160,174,175,161,173,163,162,172,169,167,166,168,164,170,171,165,176,190,191,177,189,179,178,188,185,183,182,184,180,186,187,181,80,94,95,81,93,83,82,92,89,87,86,88,84,90,91,85}, + {0,15,13,2,9,6,4,11,1,14,12,3,8,7,5,10,240,255,253,242,249,246,244,251,241,254,252,243,248,247,245,250,208,223,221,210,217,214,212,219,209,222,220,211,216,215,213,218,32,47,45,34,41,38,36,43,33,46,44,35,40,39,37,42,144,159,157,146,153,150,148,155,145,158,156,147,152,151,149,154,96,111,109,98,105,102,100,107,97,110,108,99,104,103,101,106,64,79,77,66,73,70,68,75,65,78,76,67,72,71,69,74,176,191,189,178,185,182,180,187,177,190,188,179,184,183,181,186,16,31,29,18,25,22,20,27,17,30,28,19,24,23,21,26,224,239,237,226,233,230,228,235,225,238,236,227,232,231,229,234,192,207,205,194,201,198,196,203,193,206,204,195,200,199,197,202,48,63,61,50,57,54,52,59,49,62,60,51,56,55,53,58,128,143,141,130,137,134,132,139,129,142,140,131,136,135,133,138,112,127,125,114,121,118,116,123,113,126,124,115,120,119,117,122,80,95,93,82,89,86,84,91,81,94,92,83,88,87,85,90,160,175,173,162,169,166,164,171,161,174,172,163,168,167,165,170} +}; + + +/* + * addmul() computes dst[] = dst[] + c * src[] + */ +void of_galois_field_2_4_addmul1(gf *dst1, gf *src1, gf c, int sz); + +/* + * of_galois_field_2_4_addmul1_compact() computes dst[] = dst[] + c * src[] when src and dst + * both point to vectors where each GF(2^4) element is actually stored in 4-bits. + * Said differently, there are two elements per byte. + * This is used for matrix operations where source/repair symbols are involved (encoding + * and decoding). + * This function has been optimized so that two elements are accessed each time, and the + * mulc table works on two elements at a time. This is a highly effective solution which + * warrants high performances. + */ +void of_galois_field_2_4_addmul1_compact (gf *dst1, gf *src1, gf c, int sz); + +/* + * computes C = AB where A is n*k, B is k*m, C is n*m + */ +void of_galois_field_2_4_matmul (gf *a, gf *b, gf *c, int n, int k, int m); +int of_galois_field_2_4_invert_mat (of_galois_field_code_cb_t* ofcb, gf *src, int k); +int of_galois_field_2_4_invert_vdm (of_galois_field_code_cb_t* ofcb, gf *src, int k); + +#endif //OF_USE_GALOIS_FIELD_CODES_UTILS + +#endif //OF_GALOIS_FIELD_ALGEBRA_2_4_H diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_8.c b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_8.c new file mode 100644 index 0000000..bbbef94 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_8.c @@ -0,0 +1,329 @@ +/* $Id: algebra_2_8.c 185 2014-07-15 09:57:16Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it) + * + * Portions derived from code by Phil Karn (karn@ka9q.ampr.org), + * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari + * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ +#include "algebra_2_8.h" + +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + +#define UNROLL 16 +#define USE_GF_MULC register gf * __gf_mulc_ +#define GF_MULC0(c) __gf_mulc_ = (gf*)of_gf_2_8_mul_table[c] +#define GF_ADDMULC(dst, x) {dst ^= __gf_mulc_[x];} + +/* + * addmul() computes dst[] = dst[] + c * src[] + * This is used often, so better optimize it! Currently the loop is + * unrolled 16 times, a good value for 486 and pentium-class machines. + * The case c=0 is also optimized, whereas c=1 is not. These + * calls are unfrequent in my typical apps so I did not bother. + */ +void of_galois_field_2_8_addmul1(gf *dst1, gf *src1, gf c, int sz) { + USE_GF_MULC ; + register gf *dst = dst1, *src = src1 ; + gf *lim = &dst[sz - UNROLL + 1] ; +#if ((defined (__LP64__) || (__WORDSIZE == 64)) && !defined (OF_RS_2M_USE_32BITS)) + UINT64 tmp; + UINT64 *dst_64 = (UINT64*)dst1; +#else + UINT32 tmp; + UINT32 *dst_32 = (UINT32*)dst1; +#endif + GF_MULC0 (c) ; + + +#if (UNROLL > 1) /* unrolling by 8/16 is quite effective on the pentium */ + //for (; dst < lim ; dst += UNROLL, src += UNROLL) + for (; dst < lim ;dst += UNROLL, src += UNROLL) + { +#if ((defined (__LP64__) || (__WORDSIZE == 64)) && !defined (OF_RS_2M_USE_32BITS)) + tmp = ((UINT64)__gf_mulc_[src[0]]) | ((UINT64)__gf_mulc_[src[1]]<<8) | ((UINT64)__gf_mulc_[src[2]]<<16) | + ((UINT64)__gf_mulc_[src[3]]<<24) | ((UINT64)__gf_mulc_[src[4]]<<32) | ((UINT64)__gf_mulc_[src[5]]<<40) | + ((UINT64)__gf_mulc_[src[6]]<<48) | ((UINT64)__gf_mulc_[src[7]]<<56) ; + *dst_64 ^= tmp; + dst_64++; + tmp = ((UINT64)__gf_mulc_[src[8]]) | ((UINT64)__gf_mulc_[src[9]]<<8) | ((UINT64)__gf_mulc_[src[10]]<<16) | + ((UINT64)__gf_mulc_[src[11]]<<24) | ((UINT64)__gf_mulc_[src[12]]<<32) | ((UINT64)__gf_mulc_[src[13]]<<40) | + ((UINT64)__gf_mulc_[src[14]]<<48) | ((UINT64)__gf_mulc_[src[15]]<<56) ; + *dst_64 ^= tmp; + dst_64++; +#else + tmp = ((UINT32)__gf_mulc_[src[0]]) | ((UINT32)__gf_mulc_[src[1]]<<8) | ((UINT32)__gf_mulc_[src[2]]<<16) | + ((UINT32)__gf_mulc_[src[3]]<<24); + *dst_32 ^= tmp; + dst_32++; + tmp = ((UINT32)__gf_mulc_[src[4]]) | ((UINT32)__gf_mulc_[src[5]]<<8) | ((UINT32)__gf_mulc_[src[6]]<<16) | + ((UINT32)__gf_mulc_[src[7]]<<24); + *dst_32 ^= tmp; + dst_32++; + tmp = ((UINT32)__gf_mulc_[src[8]]) | ((UINT32)__gf_mulc_[src[9]]<<8) | ((UINT32)__gf_mulc_[src[10]]<<16) | + ((UINT32)__gf_mulc_[src[11]]<<24); + *dst_32 ^= tmp; + dst_32++; + tmp = ((UINT32)__gf_mulc_[src[12]]) | ((UINT32)__gf_mulc_[src[13]]<<8) | ((UINT32)__gf_mulc_[src[14]]<<16) | + ((UINT32)__gf_mulc_[src[15]]<<24); + *dst_32 ^= tmp; + dst_32++; +#endif + } +#endif + lim += UNROLL - 1 ; + for (; dst < lim; dst++, src++) /* final components */ + GF_ADDMULC (*dst , *src); +} + +/* + * computes C = AB where A is n*k, B is k*m, C is n*m + */ +void of_galois_field_2_8_matmul (gf *a, gf *b, gf *c, int n, int k, int m) { + OF_ENTER_FUNCTION + int row, col, i ; + + for (row = 0; row < n ; row++) + { + for (col = 0; col < m ; col++) + { + gf *pa = &a[ row * k ]; + gf *pb = &b[ col ]; + gf acc = 0 ; + for (i = 0; i < k ; i++, pa++, pb += m) + acc ^= of_gf_2_8_mul_table[*pa][ *pb] ; + c[ row * m + col ] = acc ; + } + } + OF_EXIT_FUNCTION +} + +int of_galois_field_2_8_invert_mat (of_galois_field_code_cb_t* ofcb, gf *src, int k) { + OF_ENTER_FUNCTION + gf c, *p ; + int irow, icol, row, col, i, ix ; + + int error = 1 ; + int *indxc = (int*) of_malloc (k * sizeof (int)); + int *indxr = (int*) of_malloc (k * sizeof (int)); + int *ipiv = (int*) of_malloc (k * sizeof (int)); + gf *id_row = (gf*) of_malloc (1 * k * sizeof(gf)); + gf *temp_row = (gf*) of_malloc (1 * k * sizeof(gf)); + + bzero (id_row, k*sizeof (gf)); + /* + * ipiv marks elements already used as pivots. + */ + for (i = 0; i < k ; i++) + ipiv[i] = 0 ; + + for (col = 0; col < k ; col++) + { + gf *pivot_row ; + /* + * Zeroing column 'col', look for a non-zero element. + * First try on the diagonal, if it fails, look elsewhere. + */ + irow = icol = -1 ; + if (ipiv[col] != 1 && src[col*k + col] != 0) + { + irow = col ; + icol = col ; + goto found_piv ; + } + for (row = 0 ; row < k ; row++) + { + if (ipiv[row] != 1) + { + for (ix = 0 ; ix < k ; ix++) + { + if (ipiv[ix] == 0) + { + if (src[row*k + ix] != 0) + { + irow = row ; + icol = ix ; + goto found_piv ; + } + } + else if (ipiv[ix] > 1) + { + // PRINT_ERR((mcl_stderr, "singular matrix\n")) + goto fail ; + } + } + } + } + if (icol == -1) + { + // PRINT_ERR((mcl_stderr, "XXX pivot not found!\n")) + goto fail ; + } + found_piv: + ++ (ipiv[icol]) ; + /* + * swap rows irow and icol, so afterwards the diagonal + * element will be correct. Rarely done, not worth + * optimizing. + */ + if (irow != icol) + { + for (ix = 0 ; ix < k ; ix++) + { + SWAP (src[irow*k + ix], src[icol*k + ix], gf) ; + } + } + indxr[col] = irow ; + indxc[col] = icol ; + pivot_row = &src[icol*k] ; + c = pivot_row[icol] ; + if (c == 0) + { + OF_PRINT_ERROR(("singular matrix 2\n")) + goto fail ; + } + if (c != 1) + { + /* otherwhise this is a NOP */ + /* + * this is done often , but optimizing is not so + * fruitful, at least in the obvious ways (unrolling) + */ + c = of_gf_2_8_inv[ c ] ; + pivot_row[icol] = 1 ; + for (ix = 0 ; ix < k ; ix++) + pivot_row[ix] = of_gf_2_8_mul_table[c][ pivot_row[ix]]; + } + /* + * from all rows, remove multiples of the selected row + * to zero the relevant entry (in fact, the entry is not zero + * because we know it must be zero). + * (Here, if we know that the pivot_row is the identity, + * we can optimize the addmul). + */ + id_row[icol] = 1; + if (bcmp (pivot_row, id_row, k*sizeof (gf)) != 0) + { + for (p = src, ix = 0 ; ix < k ; ix++, p += k) + { + if (ix != icol) + { + c = p[icol] ; + p[icol] = 0 ; + if (c != 0) + of_galois_field_2_8_addmul1 (p, pivot_row, c, k); + } + } + } + id_row[icol] = 0; + } /* done all columns */ + for (col = k - 1 ; col >= 0 ; col--) + { + if (indxr[col] < 0 || indxr[col] >= k) + OF_PRINT_ERROR(("AARGH, indxr[col] %d\n", indxr[col])) + else if (indxc[col] < 0 || indxc[col] >= k) + OF_PRINT_ERROR(( "AARGH, indxc[col] %d\n", indxc[col])) + else if (indxr[col] != indxc[col]) + { + for (row = 0 ; row < k ; row++) + { + SWAP (src[row*k + indxr[col]], src[row*k + indxc[col]], gf) ; + } + } + } + error = 0 ; +fail: + of_free (indxc); + of_free (indxr); + of_free (ipiv); + of_free (id_row); + of_free (temp_row); + OF_EXIT_FUNCTION + return error ; +} + +int of_galois_field_2_8_invert_vdm (of_galois_field_code_cb_t* ofcb, gf *src, int k) { + OF_ENTER_FUNCTION + int i, j, row, col ; + gf *b, *c, *p; + gf t, xx ; + + if (k == 1) /* degenerate case, matrix must be p^0 = 1 */ + return 0 ; + /* + * c holds the coefficient of P(x) = Prod (x - p_i), i=0..k-1 + * b holds the coefficient for the matrix inversion + */ + c = (gf*) of_malloc(1 * k * sizeof(gf)); + b = (gf*) of_malloc(1 * k * sizeof(gf)); + p = (gf*) of_malloc(1 * k * sizeof(gf)); + + for (j = 1, i = 0 ; i < k ; i++, j += k) + { + c[i] = 0 ; + p[i] = src[j] ; /* p[i] */ + } + /* + * construct coeffs. recursively. We know c[k] = 1 (implicit) + * and start P_0 = x - p_0, then at each stage multiply by + * x - p_i generating P_i = x P_{i-1} - p_i P_{i-1} + * After k steps we are done. + */ + c[k-1] = p[0] ; /* really -p(0), but x = -x in GF(2^m) */ + for (i = 1 ; i < k ; i++) + { + gf p_i = p[i] ; /* see above comment */ + for (j = k - 1 - (i - 1) ; j < k - 1 ; j++) + c[j] ^= of_gf_2_8_mul_table[p_i][ c[j+1]] ; + c[k-1] ^= p_i ; + } + + for (row = 0 ; row < k ; row++) + { + /* + * synthetic division etc. + */ + xx = p[row] ; + t = 1 ; + b[k-1] = 1 ; /* this is in fact c[k] */ + for (i = k - 2 ; i >= 0 ; i--) + { + b[i] = c[i+1] ^ of_gf_2_8_mul_table[xx][ b[i+1]] ; + t = of_gf_2_8_mul_table[xx][ t] ^ b[i] ; + } + for (col = 0 ; col < k ; col++) + src[col*k + row] = of_gf_2_8_mul_table [of_gf_2_8_inv[t]][ b[col]]; + } + of_free (c); + of_free (b); + of_free (p); + OF_EXIT_FUNCTION + return 0 ; +} + +#endif diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_8.h b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_8.h new file mode 100644 index 0000000..9d0e8ca --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/algebra_2_8.h @@ -0,0 +1,329 @@ +/* $Id: algebra_2_8.h 148 2014-07-08 08:01:56Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (C) 1997-98 Luigi Rizzo (luigi@iet.unipi.it) + * + * Portions derived from code by Phil Karn (karn@ka9q.ampr.org), + * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari + * Thirumoorthy (harit@spectra.eng.hawaii.edu), Aug 1995 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ +#ifndef OF_GALOIS_FIELD_ALGEBRA_2_8_H +#define OF_GALOIS_FIELD_ALGEBRA_2_8_H + +#include "../of_reed-solomon_gf_2_m_includes.h" + + +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + + +#define SWAP(a,b,t) {t tmp; tmp=a; a=b; b=tmp;} + +static const int of_gf_2_8_log[] = {255,0,1,25,2,50,26,198,3,223,51,238,27,104,199,75,4,100,224,14,52,141,239,129,28,193,105,248,200,8,76,113,5,138,101,47,225,36,15,33,53,147,142,218,240,18,130,69,29,181,194,125,106,39,249,185,201,154,9,120,77,228,114,166,6,191,139,98,102,221,48,253,226,152,37,179,16,145,34,136,54,208,148,206,143,150,219,189,241,210,19,92,131,56,70,64,30,66,182,163,195,72,126,110,107,58,40,84,250,133,186,61,202,94,155,159,10,21,121,43,78,212,229,172,115,243,167,87,7,112,192,247,140,128,99,13,103,74,222,237,49,197,254,24,227,165,153,119,38,184,180,124,17,68,146,217,35,32,137,46,55,63,209,91,149,188,207,205,144,135,151,178,220,252,190,97,242,86,211,171,20,42,93,158,132,60,57,83,71,109,65,162,31,45,67,216,183,123,164,118,196,23,73,236,127,12,111,246,108,161,59,82,41,157,85,170,251,96,134,177,187,204,62,90,203,89,95,176,156,169,160,81,11,245,22,235,122,117,44,215,79,174,213,233,230,231,173,232,116,214,244,234,168,80,88,175255,0,1,25,2,50,26,198,3,223,51,238,27,104,199,75,4,100,224,14,52,141,239,129,28,193,105,248,200,8,76,113,5,138,101,47,225,36,15,33,53,147,142,218,240,18,130,69,29,181,194,125,106,39,249,185,201,154,9,120,77,228,114,166,6,191,139,98,102,221,48,253,226,152,37,179,16,145,34,136,54,208,148,206,143,150,219,189,241,210,19,92,131,56,70,64,30,66,182,163,195,72,126,110,107,58,40,84,250,133,186,61,202,94,155,159,10,21,121,43,78,212,229,172,115,243,167,87,7,112,192,247,140,128,99,13,103,74,222,237,49,197,254,24,227,165,153,119,38,184,180,124,17,68,146,217,35,32,137,46,55,63,209,91,149,188,207,205,144,135,151,178,220,252,190,97,242,86,211,171,20,42,93,158,132,60,57,83,71,109,65,162,31,45,67,216,183,123,164,118,196,23,73,236,127,12,111,246,108,161,59,82,41,157,85,170,251,96,134,177,187,204,62,90,203,89,95,176,156,169,160,81,11,245,22,235,122,117,44,215,79,174,213,233,230,231,173,232,116,214,244,234,168,80,88,175}; + +static const gf of_gf_2_8_exp[] = {1,2,4,8,16,32,64,128,29,58,116,232,205,135,19,38,76,152,45,90,180,117,234,201,143,3,6,12,24,48,96,192,157,39,78,156,37,74,148,53,106,212,181,119,238,193,159,35,70,140,5,10,20,40,80,160,93,186,105,210,185,111,222,161,95,190,97,194,153,47,94,188,101,202,137,15,30,60,120,240,253,231,211,187,107,214,177,127,254,225,223,163,91,182,113,226,217,175,67,134,17,34,68,136,13,26,52,104,208,189,103,206,129,31,62,124,248,237,199,147,59,118,236,197,151,51,102,204,133,23,46,92,184,109,218,169,79,158,33,66,132,21,42,84,168,77,154,41,82,164,85,170,73,146,57,114,228,213,183,115,230,209,191,99,198,145,63,126,252,229,215,179,123,246,241,255,227,219,171,75,150,49,98,196,149,55,110,220,165,87,174,65,130,25,50,100,200,141,7,14,28,56,112,224,221,167,83,166,81,162,89,178,121,242,249,239,195,155,43,86,172,69,138,9,18,36,72,144,61,122,244,245,247,243,251,235,203,139,11,22,44,88,176,125,250,233,207,131,27,54,108,216,173,71,142,1}; + +static const gf of_gf_2_8_inv[] = {0,1,142,244,71,167,122,186,173,157,221,152,61,170,93,150,216,114,192,88,224,62,76,102,144,222,85,128,160,131,75,42,108,237,57,81,96,86,44,138,112,208,31,74,38,139,51,110,72,137,111,46,164,195,64,94,80,34,207,169,171,12,21,225,54,95,248,213,146,78,166,4,48,136,43,30,22,103,69,147,56,35,104,140,129,26,37,97,19,193,203,99,151,14,55,65,36,87,202,91,185,196,23,77,82,141,239,179,32,236,47,50,40,209,17,217,233,251,218,121,219,119,6,187,132,205,254,252,27,84,161,29,124,204,228,176,73,49,39,45,83,105,2,245,24,223,68,79,155,188,15,92,11,220,189,148,172,9,199,162,28,130,159,198,52,194,70,5,206,59,13,60,156,8,190,183,135,229,238,107,235,242,191,175,197,100,7,123,149,154,174,182,18,89,165,53,101,184,163,158,210,247,98,90,133,125,168,58,41,113,200,246,249,67,215,214,16,115,118,120,153,10,25,145,20,63,230,240,134,177,226,241,250,116,243,180,109,33,178,106,227,231,181,234,3,143,211,201,66,212,232,117,127,255,126,253}; + +static const gf of_gf_2_8_mul_table[][256] = { + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}, + {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,29,31,25,27,21,23,17,19,13,15,9,11,5,7,1,3,61,63,57,59,53,55,49,51,45,47,41,43,37,39,33,35,93,95,89,91,85,87,81,83,77,79,73,75,69,71,65,67,125,127,121,123,117,119,113,115,109,111,105,107,101,103,97,99,157,159,153,155,149,151,145,147,141,143,137,139,133,135,129,131,189,191,185,187,181,183,177,179,173,175,169,171,165,167,161,163,221,223,217,219,213,215,209,211,205,207,201,203,197,199,193,195,253,255,249,251,245,247,241,243,237,239,233,235,229,231,225,227}, + {0,3,6,5,12,15,10,9,24,27,30,29,20,23,18,17,48,51,54,53,60,63,58,57,40,43,46,45,36,39,34,33,96,99,102,101,108,111,106,105,120,123,126,125,116,119,114,113,80,83,86,85,92,95,90,89,72,75,78,77,68,71,66,65,192,195,198,197,204,207,202,201,216,219,222,221,212,215,210,209,240,243,246,245,252,255,250,249,232,235,238,237,228,231,226,225,160,163,166,165,172,175,170,169,184,187,190,189,180,183,178,177,144,147,150,149,156,159,154,153,136,139,142,141,132,135,130,129,157,158,155,152,145,146,151,148,133,134,131,128,137,138,143,140,173,174,171,168,161,162,167,164,181,182,179,176,185,186,191,188,253,254,251,248,241,242,247,244,229,230,227,224,233,234,239,236,205,206,203,200,193,194,199,196,213,214,211,208,217,218,223,220,93,94,91,88,81,82,87,84,69,70,67,64,73,74,79,76,109,110,107,104,97,98,103,100,117,118,115,112,121,122,127,124,61,62,59,56,49,50,55,52,37,38,35,32,41,42,47,44,13,14,11,8,1,2,7,4,21,22,19,16,25,26,31,28}, + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,29,25,21,17,13,9,5,1,61,57,53,49,45,41,37,33,93,89,85,81,77,73,69,65,125,121,117,113,109,105,101,97,157,153,149,145,141,137,133,129,189,185,181,177,173,169,165,161,221,217,213,209,205,201,197,193,253,249,245,241,237,233,229,225,58,62,50,54,42,46,34,38,26,30,18,22,10,14,2,6,122,126,114,118,106,110,98,102,90,94,82,86,74,78,66,70,186,190,178,182,170,174,162,166,154,158,146,150,138,142,130,134,250,254,242,246,234,238,226,230,218,222,210,214,202,206,194,198,39,35,47,43,55,51,63,59,7,3,15,11,23,19,31,27,103,99,111,107,119,115,127,123,71,67,79,75,87,83,95,91,167,163,175,171,183,179,191,187,135,131,143,139,151,147,159,155,231,227,239,235,247,243,255,251,199,195,207,203,215,211,223,219}, + {0,5,10,15,20,17,30,27,40,45,34,39,60,57,54,51,80,85,90,95,68,65,78,75,120,125,114,119,108,105,102,99,160,165,170,175,180,177,190,187,136,141,130,135,156,153,150,147,240,245,250,255,228,225,238,235,216,221,210,215,204,201,198,195,93,88,87,82,73,76,67,70,117,112,127,122,97,100,107,110,13,8,7,2,25,28,19,22,37,32,47,42,49,52,59,62,253,248,247,242,233,236,227,230,213,208,223,218,193,196,203,206,173,168,167,162,185,188,179,182,133,128,143,138,145,148,155,158,186,191,176,181,174,171,164,161,146,151,152,157,134,131,140,137,234,239,224,229,254,251,244,241,194,199,200,205,214,211,220,217,26,31,16,21,14,11,4,1,50,55,56,61,38,35,44,41,74,79,64,69,94,91,84,81,98,103,104,109,118,115,124,121,231,226,237,232,243,246,249,252,207,202,197,192,219,222,209,212,183,178,189,184,163,166,169,172,159,154,149,144,139,142,129,132,71,66,77,72,83,86,89,92,111,106,101,96,123,126,113,116,23,18,29,24,3,6,9,12,63,58,53,48,43,46,33,36}, + {0,6,12,10,24,30,20,18,48,54,60,58,40,46,36,34,96,102,108,106,120,126,116,114,80,86,92,90,72,78,68,66,192,198,204,202,216,222,212,210,240,246,252,250,232,238,228,226,160,166,172,170,184,190,180,178,144,150,156,154,136,142,132,130,157,155,145,151,133,131,137,143,173,171,161,167,181,179,185,191,253,251,241,247,229,227,233,239,205,203,193,199,213,211,217,223,93,91,81,87,69,67,73,79,109,107,97,103,117,115,121,127,61,59,49,55,37,35,41,47,13,11,1,7,21,19,25,31,39,33,43,45,63,57,51,53,23,17,27,29,15,9,3,5,71,65,75,77,95,89,83,85,119,113,123,125,111,105,99,101,231,225,235,237,255,249,243,245,215,209,219,221,207,201,195,197,135,129,139,141,159,153,147,149,183,177,187,189,175,169,163,165,186,188,182,176,162,164,174,168,138,140,134,128,146,148,158,152,218,220,214,208,194,196,206,200,234,236,230,224,242,244,254,248,122,124,118,112,98,100,110,104,74,76,70,64,82,84,94,88,26,28,22,16,2,4,14,8,42,44,38,32,50,52,62,56}, + {0,7,14,9,28,27,18,21,56,63,54,49,36,35,42,45,112,119,126,121,108,107,98,101,72,79,70,65,84,83,90,93,224,231,238,233,252,251,242,245,216,223,214,209,196,195,202,205,144,151,158,153,140,139,130,133,168,175,166,161,180,179,186,189,221,218,211,212,193,198,207,200,229,226,235,236,249,254,247,240,173,170,163,164,177,182,191,184,149,146,155,156,137,142,135,128,61,58,51,52,33,38,47,40,5,2,11,12,25,30,23,16,77,74,67,68,81,86,95,88,117,114,123,124,105,110,103,96,167,160,169,174,187,188,181,178,159,152,145,150,131,132,141,138,215,208,217,222,203,204,197,194,239,232,225,230,243,244,253,250,71,64,73,78,91,92,85,82,127,120,113,118,99,100,109,106,55,48,57,62,43,44,37,34,15,8,1,6,19,20,29,26,122,125,116,115,102,97,104,111,66,69,76,75,94,89,80,87,10,13,4,3,22,17,24,31,50,53,60,59,46,41,32,39,154,157,148,147,134,129,136,143,162,165,172,171,190,185,176,183,234,237,228,227,246,241,248,255,210,213,220,219,206,201,192,199}, + {0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,29,21,13,5,61,53,45,37,93,85,77,69,125,117,109,101,157,149,141,133,189,181,173,165,221,213,205,197,253,245,237,229,58,50,42,34,26,18,10,2,122,114,106,98,90,82,74,66,186,178,170,162,154,146,138,130,250,242,234,226,218,210,202,194,39,47,55,63,7,15,23,31,103,111,119,127,71,79,87,95,167,175,183,191,135,143,151,159,231,239,247,255,199,207,215,223,116,124,100,108,84,92,68,76,52,60,36,44,20,28,4,12,244,252,228,236,212,220,196,204,180,188,164,172,148,156,132,140,105,97,121,113,73,65,89,81,41,33,57,49,9,1,25,17,233,225,249,241,201,193,217,209,169,161,185,177,137,129,153,145,78,70,94,86,110,102,126,118,14,6,30,22,46,38,62,54,206,198,222,214,238,230,254,246,142,134,158,150,174,166,190,182,83,91,67,75,115,123,99,107,19,27,3,11,51,59,35,43,211,219,195,203,243,251,227,235,147,155,131,139,179,187,163,171}, + {0,9,18,27,36,45,54,63,72,65,90,83,108,101,126,119,144,153,130,139,180,189,166,175,216,209,202,195,252,245,238,231,61,52,47,38,25,16,11,2,117,124,103,110,81,88,67,74,173,164,191,182,137,128,155,146,229,236,247,254,193,200,211,218,122,115,104,97,94,87,76,69,50,59,32,41,22,31,4,13,234,227,248,241,206,199,220,213,162,171,176,185,134,143,148,157,71,78,85,92,99,106,113,120,15,6,29,20,43,34,57,48,215,222,197,204,243,250,225,232,159,150,141,132,187,178,169,160,244,253,230,239,208,217,194,203,188,181,174,167,152,145,138,131,100,109,118,127,64,73,82,91,44,37,62,55,8,1,26,19,201,192,219,210,237,228,255,246,129,136,147,154,165,172,183,190,89,80,75,66,125,116,111,102,17,24,3,10,53,60,39,46,142,135,156,149,170,163,184,177,198,207,212,221,226,235,240,249,30,23,12,5,58,51,40,33,86,95,68,77,114,123,96,105,179,186,161,168,151,158,133,140,251,242,233,224,223,214,205,196,35,42,49,56,7,14,21,28,107,98,121,112,79,70,93,84}, + {0,10,20,30,40,34,60,54,80,90,68,78,120,114,108,102,160,170,180,190,136,130,156,150,240,250,228,238,216,210,204,198,93,87,73,67,117,127,97,107,13,7,25,19,37,47,49,59,253,247,233,227,213,223,193,203,173,167,185,179,133,143,145,155,186,176,174,164,146,152,134,140,234,224,254,244,194,200,214,220,26,16,14,4,50,56,38,44,74,64,94,84,98,104,118,124,231,237,243,249,207,197,219,209,183,189,163,169,159,149,139,129,71,77,83,89,111,101,123,113,23,29,3,9,63,53,43,33,105,99,125,119,65,75,85,95,57,51,45,39,17,27,5,15,201,195,221,215,225,235,245,255,153,147,141,135,177,187,165,175,52,62,32,42,28,22,8,2,100,110,112,122,76,70,88,82,148,158,128,138,188,182,168,162,196,206,208,218,236,230,248,242,211,217,199,205,251,241,239,229,131,137,151,157,171,161,191,181,115,121,103,109,91,81,79,69,35,41,55,61,11,1,31,21,142,132,154,144,166,172,178,184,222,212,202,192,246,252,226,232,46,36,58,48,6,12,18,24,126,116,106,96,86,92,66,72}, + {0,11,22,29,44,39,58,49,88,83,78,69,116,127,98,105,176,187,166,173,156,151,138,129,232,227,254,245,196,207,210,217,125,118,107,96,81,90,71,76,37,46,51,56,9,2,31,20,205,198,219,208,225,234,247,252,149,158,131,136,185,178,175,164,250,241,236,231,214,221,192,203,162,169,180,191,142,133,152,147,74,65,92,87,102,109,112,123,18,25,4,15,62,53,40,35,135,140,145,154,171,160,189,182,223,212,201,194,243,248,229,238,55,60,33,42,27,16,13,6,111,100,121,114,67,72,85,94,233,226,255,244,197,206,211,216,177,186,167,172,157,150,139,128,89,82,79,68,117,126,99,104,1,10,23,28,45,38,59,48,148,159,130,137,184,179,174,165,204,199,218,209,224,235,246,253,36,47,50,57,8,3,30,21,124,119,106,97,80,91,70,77,19,24,5,14,63,52,41,34,75,64,93,86,103,108,113,122,163,168,181,190,143,132,153,146,251,240,237,230,215,220,193,202,110,101,120,115,66,73,84,95,54,61,32,43,26,17,12,7,222,213,200,195,242,249,228,239,134,141,144,155,170,161,188,183}, + {0,12,24,20,48,60,40,36,96,108,120,116,80,92,72,68,192,204,216,212,240,252,232,228,160,172,184,180,144,156,136,132,157,145,133,137,173,161,181,185,253,241,229,233,205,193,213,217,93,81,69,73,109,97,117,121,61,49,37,41,13,1,21,25,39,43,63,51,23,27,15,3,71,75,95,83,119,123,111,99,231,235,255,243,215,219,207,195,135,139,159,147,183,187,175,163,186,182,162,174,138,134,146,158,218,214,194,206,234,230,242,254,122,118,98,110,74,70,82,94,26,22,2,14,42,38,50,62,78,66,86,90,126,114,102,106,46,34,54,58,30,18,6,10,142,130,150,154,190,178,166,170,238,226,246,250,222,210,198,202,211,223,203,199,227,239,251,247,179,191,171,167,131,143,155,151,19,31,11,7,35,47,59,55,115,127,107,103,67,79,91,87,105,101,113,125,89,85,65,77,9,5,17,29,57,53,33,45,169,165,177,189,153,149,129,141,201,197,209,221,249,245,225,237,244,248,236,224,196,200,220,208,148,152,140,128,164,168,188,176,52,56,44,32,4,8,28,16,84,88,76,64,100,104,124,112}, + {0,13,26,23,52,57,46,35,104,101,114,127,92,81,70,75,208,221,202,199,228,233,254,243,184,181,162,175,140,129,150,155,189,176,167,170,137,132,147,158,213,216,207,194,225,236,251,246,109,96,119,122,89,84,67,78,5,8,31,18,49,60,43,38,103,106,125,112,83,94,73,68,15,2,21,24,59,54,33,44,183,186,173,160,131,142,153,148,223,210,197,200,235,230,241,252,218,215,192,205,238,227,244,249,178,191,168,165,134,139,156,145,10,7,16,29,62,51,36,41,98,111,120,117,86,91,76,65,206,195,212,217,250,247,224,237,166,171,188,177,146,159,136,133,30,19,4,9,42,39,48,61,118,123,108,97,66,79,88,85,115,126,105,100,71,74,93,80,27,22,1,12,47,34,53,56,163,174,185,180,151,154,141,128,203,198,209,220,255,242,229,232,169,164,179,190,157,144,135,138,193,204,219,214,245,248,239,226,121,116,99,110,77,64,87,90,17,28,11,6,37,40,63,50,20,25,14,3,32,45,58,55,124,113,102,107,72,69,82,95,196,201,222,211,240,253,234,231,172,161,182,187,152,149,130,143}, + {0,14,28,18,56,54,36,42,112,126,108,98,72,70,84,90,224,238,252,242,216,214,196,202,144,158,140,130,168,166,180,186,221,211,193,207,229,235,249,247,173,163,177,191,149,155,137,135,61,51,33,47,5,11,25,23,77,67,81,95,117,123,105,103,167,169,187,181,159,145,131,141,215,217,203,197,239,225,243,253,71,73,91,85,127,113,99,109,55,57,43,37,15,1,19,29,122,116,102,104,66,76,94,80,10,4,22,24,50,60,46,32,154,148,134,136,162,172,190,176,234,228,246,248,210,220,206,192,83,93,79,65,107,101,119,121,35,45,63,49,27,21,7,9,179,189,175,161,139,133,151,153,195,205,223,209,251,245,231,233,142,128,146,156,182,184,170,164,254,240,226,236,198,200,218,212,110,96,114,124,86,88,74,68,30,16,2,12,38,40,58,52,244,250,232,230,204,194,208,222,132,138,152,150,188,178,160,174,20,26,8,6,44,34,48,62,100,106,120,118,92,82,64,78,41,39,53,59,17,31,13,3,89,87,69,75,97,111,125,115,201,199,213,219,241,255,237,227,185,183,165,171,129,143,157,147}, + {0,15,30,17,60,51,34,45,120,119,102,105,68,75,90,85,240,255,238,225,204,195,210,221,136,135,150,153,180,187,170,165,253,242,227,236,193,206,223,208,133,138,155,148,185,182,167,168,13,2,19,28,49,62,47,32,117,122,107,100,73,70,87,88,231,232,249,246,219,212,197,202,159,144,129,142,163,172,189,178,23,24,9,6,43,36,53,58,111,96,113,126,83,92,77,66,26,21,4,11,38,41,56,55,98,109,124,115,94,81,64,79,234,229,244,251,214,217,200,199,146,157,140,131,174,161,176,191,211,220,205,194,239,224,241,254,171,164,181,186,151,152,137,134,35,44,61,50,31,16,1,14,91,84,69,74,103,104,121,118,46,33,48,63,18,29,12,3,86,89,72,71,106,101,116,123,222,209,192,207,226,237,252,243,166,169,184,183,154,149,132,139,52,59,42,37,8,7,22,25,76,67,82,93,112,127,110,97,196,203,218,213,248,247,230,233,188,179,162,173,128,143,158,145,201,198,215,216,245,250,235,228,177,190,175,160,141,130,147,156,57,54,39,40,5,10,27,20,65,78,95,80,125,114,99,108}, + {0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240,29,13,61,45,93,77,125,109,157,141,189,173,221,205,253,237,58,42,26,10,122,106,90,74,186,170,154,138,250,234,218,202,39,55,7,23,103,119,71,87,167,183,135,151,231,247,199,215,116,100,84,68,52,36,20,4,244,228,212,196,180,164,148,132,105,121,73,89,41,57,9,25,233,249,201,217,169,185,137,153,78,94,110,126,14,30,46,62,206,222,238,254,142,158,174,190,83,67,115,99,19,3,51,35,211,195,243,227,147,131,179,163,232,248,200,216,168,184,136,152,104,120,72,88,40,56,8,24,245,229,213,197,181,165,149,133,117,101,85,69,53,37,21,5,210,194,242,226,146,130,178,162,82,66,114,98,18,2,50,34,207,223,239,255,143,159,175,191,79,95,111,127,15,31,47,63,156,140,188,172,220,204,252,236,28,12,60,44,92,76,124,108,129,145,161,177,193,209,225,241,1,17,33,49,65,81,97,113,166,182,134,150,230,246,198,214,38,54,6,22,102,118,70,86,187,171,155,139,251,235,219,203,59,43,27,11,123,107,91,75}, + {0,17,34,51,68,85,102,119,136,153,170,187,204,221,238,255,13,28,47,62,73,88,107,122,133,148,167,182,193,208,227,242,26,11,56,41,94,79,124,109,146,131,176,161,214,199,244,229,23,6,53,36,83,66,113,96,159,142,189,172,219,202,249,232,52,37,22,7,112,97,82,67,188,173,158,143,248,233,218,203,57,40,27,10,125,108,95,78,177,160,147,130,245,228,215,198,46,63,12,29,106,123,72,89,166,183,132,149,226,243,192,209,35,50,1,16,103,118,69,84,171,186,137,152,239,254,205,220,104,121,74,91,44,61,14,31,224,241,194,211,164,181,134,151,101,116,71,86,33,48,3,18,237,252,207,222,169,184,139,154,114,99,80,65,54,39,20,5,250,235,216,201,190,175,156,141,127,110,93,76,59,42,25,8,247,230,213,196,179,162,145,128,92,77,126,111,24,9,58,43,212,197,246,231,144,129,178,163,81,64,115,98,21,4,55,38,217,200,251,234,157,140,191,174,70,87,100,117,2,19,32,49,206,223,236,253,138,155,168,185,75,90,105,120,15,30,45,60,195,210,225,240,135,150,165,180}, + {0,18,36,54,72,90,108,126,144,130,180,166,216,202,252,238,61,47,25,11,117,103,81,67,173,191,137,155,229,247,193,211,122,104,94,76,50,32,22,4,234,248,206,220,162,176,134,148,71,85,99,113,15,29,43,57,215,197,243,225,159,141,187,169,244,230,208,194,188,174,152,138,100,118,64,82,44,62,8,26,201,219,237,255,129,147,165,183,89,75,125,111,17,3,53,39,142,156,170,184,198,212,226,240,30,12,58,40,86,68,114,96,179,161,151,133,251,233,223,205,35,49,7,21,107,121,79,93,245,231,209,195,189,175,153,139,101,119,65,83,45,63,9,27,200,218,236,254,128,146,164,182,88,74,124,110,16,2,52,38,143,157,171,185,199,213,227,241,31,13,59,41,87,69,115,97,178,160,150,132,250,232,222,204,34,48,6,20,106,120,78,92,1,19,37,55,73,91,109,127,145,131,181,167,217,203,253,239,60,46,24,10,116,102,80,66,172,190,136,154,228,246,192,210,123,105,95,77,51,33,23,5,235,249,207,221,163,177,135,149,70,84,98,112,14,28,42,56,214,196,242,224,158,140,186,168}, + {0,19,38,53,76,95,106,121,152,139,190,173,212,199,242,225,45,62,11,24,97,114,71,84,181,166,147,128,249,234,223,204,90,73,124,111,22,5,48,35,194,209,228,247,142,157,168,187,119,100,81,66,59,40,29,14,239,252,201,218,163,176,133,150,180,167,146,129,248,235,222,205,44,63,10,25,96,115,70,85,153,138,191,172,213,198,243,224,1,18,39,52,77,94,107,120,238,253,200,219,162,177,132,151,118,101,80,67,58,41,28,15,195,208,229,246,143,156,169,186,91,72,125,110,23,4,49,34,117,102,83,64,57,42,31,12,237,254,203,216,161,178,135,148,88,75,126,109,20,7,50,33,192,211,230,245,140,159,170,185,47,60,9,26,99,112,69,86,183,164,145,130,251,232,221,206,2,17,36,55,78,93,104,123,154,137,188,175,214,197,240,227,193,210,231,244,141,158,171,184,89,74,127,108,21,6,51,32,236,255,202,217,160,179,134,149,116,103,82,65,56,43,30,13,155,136,189,174,215,196,241,226,3,16,37,54,79,92,105,122,182,165,144,131,250,233,220,207,46,61,8,27,98,113,68,87}, + {0,20,40,60,80,68,120,108,160,180,136,156,240,228,216,204,93,73,117,97,13,25,37,49,253,233,213,193,173,185,133,145,186,174,146,134,234,254,194,214,26,14,50,38,74,94,98,118,231,243,207,219,183,163,159,139,71,83,111,123,23,3,63,43,105,125,65,85,57,45,17,5,201,221,225,245,153,141,177,165,52,32,28,8,100,112,76,88,148,128,188,168,196,208,236,248,211,199,251,239,131,151,171,191,115,103,91,79,35,55,11,31,142,154,166,178,222,202,246,226,46,58,6,18,126,106,86,66,210,198,250,238,130,150,170,190,114,102,90,78,34,54,10,30,143,155,167,179,223,203,247,227,47,59,7,19,127,107,87,67,104,124,64,84,56,44,16,4,200,220,224,244,152,140,176,164,53,33,29,9,101,113,77,89,149,129,189,169,197,209,237,249,187,175,147,135,235,255,195,215,27,15,51,39,75,95,99,119,230,242,206,218,182,162,158,138,70,82,110,122,22,2,62,42,1,21,41,61,81,69,121,109,161,181,137,157,241,229,217,205,92,72,116,96,12,24,36,48,252,232,212,192,172,184,132,144}, + {0,21,42,63,84,65,126,107,168,189,130,151,252,233,214,195,77,88,103,114,25,12,51,38,229,240,207,218,177,164,155,142,154,143,176,165,206,219,228,241,50,39,24,13,102,115,76,89,215,194,253,232,131,150,169,188,127,106,85,64,43,62,1,20,41,60,3,22,125,104,87,66,129,148,171,190,213,192,255,234,100,113,78,91,48,37,26,15,204,217,230,243,152,141,178,167,179,166,153,140,231,242,205,216,27,14,49,36,79,90,101,112,254,235,212,193,170,191,128,149,86,67,124,105,2,23,40,61,82,71,120,109,6,19,44,57,250,239,208,197,174,187,132,145,31,10,53,32,75,94,97,116,183,162,157,136,227,246,201,220,200,221,226,247,156,137,182,163,96,117,74,95,52,33,30,11,133,144,175,186,209,196,251,238,45,56,7,18,121,108,83,70,123,110,81,68,47,58,5,16,211,198,249,236,135,146,173,184,54,35,28,9,98,119,72,93,158,139,180,161,202,223,224,245,225,244,203,222,181,160,159,138,73,92,99,118,29,8,55,34,172,185,134,147,248,237,210,199,4,17,46,59,80,69,122,111}, + {0,22,44,58,88,78,116,98,176,166,156,138,232,254,196,210,125,107,81,71,37,51,9,31,205,219,225,247,149,131,185,175,250,236,214,192,162,180,142,152,74,92,102,112,18,4,62,40,135,145,171,189,223,201,243,229,55,33,27,13,111,121,67,85,233,255,197,211,177,167,157,139,89,79,117,99,1,23,45,59,148,130,184,174,204,218,224,246,36,50,8,30,124,106,80,70,19,5,63,41,75,93,103,113,163,181,143,153,251,237,215,193,110,120,66,84,54,32,26,12,222,200,242,228,134,144,170,188,207,217,227,245,151,129,187,173,127,105,83,69,39,49,11,29,178,164,158,136,234,252,198,208,2,20,46,56,90,76,118,96,53,35,25,15,109,123,65,87,133,147,169,191,221,203,241,231,72,94,100,114,16,6,60,42,248,238,212,194,160,182,140,154,38,48,10,28,126,104,82,68,150,128,186,172,206,216,226,244,91,77,119,97,3,21,47,57,235,253,199,209,179,165,159,137,220,202,240,230,132,146,168,190,108,122,64,86,52,34,24,14,161,183,141,155,249,239,213,195,17,7,61,43,73,95,101,115}, + {0,23,46,57,92,75,114,101,184,175,150,129,228,243,202,221,109,122,67,84,49,38,31,8,213,194,251,236,137,158,167,176,218,205,244,227,134,145,168,191,98,117,76,91,62,41,16,7,183,160,153,142,235,252,197,210,15,24,33,54,83,68,125,106,169,190,135,144,245,226,219,204,17,6,63,40,77,90,99,116,196,211,234,253,152,143,182,161,124,107,82,69,32,55,14,25,115,100,93,74,47,56,1,22,203,220,229,242,151,128,185,174,30,9,48,39,66,85,108,123,166,177,136,159,250,237,212,195,79,88,97,118,19,4,61,42,247,224,217,206,171,188,133,146,34,53,12,27,126,105,80,71,154,141,180,163,198,209,232,255,149,130,187,172,201,222,231,240,45,58,3,20,113,102,95,72,248,239,214,193,164,179,138,157,64,87,110,121,28,11,50,37,230,241,200,223,186,173,148,131,94,73,112,103,2,21,44,59,139,156,165,178,215,192,249,238,51,36,29,10,111,120,65,86,60,43,18,5,96,119,78,89,132,147,170,189,216,207,246,225,81,70,127,104,13,26,35,52,233,254,199,208,181,162,155,140}, + {0,24,48,40,96,120,80,72,192,216,240,232,160,184,144,136,157,133,173,181,253,229,205,213,93,69,109,117,61,37,13,21,39,63,23,15,71,95,119,111,231,255,215,207,135,159,183,175,186,162,138,146,218,194,234,242,122,98,74,82,26,2,42,50,78,86,126,102,46,54,30,6,142,150,190,166,238,246,222,198,211,203,227,251,179,171,131,155,19,11,35,59,115,107,67,91,105,113,89,65,9,17,57,33,169,177,153,129,201,209,249,225,244,236,196,220,148,140,164,188,52,44,4,28,84,76,100,124,156,132,172,180,252,228,204,212,92,68,108,116,60,36,12,20,1,25,49,41,97,121,81,73,193,217,241,233,161,185,145,137,187,163,139,147,219,195,235,243,123,99,75,83,27,3,43,51,38,62,22,14,70,94,118,110,230,254,214,206,134,158,182,174,210,202,226,250,178,170,130,154,18,10,34,58,114,106,66,90,79,87,127,103,47,55,31,7,143,151,191,167,239,247,223,199,245,237,197,221,149,141,165,189,53,45,5,29,85,77,101,125,104,112,88,64,8,16,56,32,168,176,152,128,200,208,248,224}, + {0,25,50,43,100,125,86,79,200,209,250,227,172,181,158,135,141,148,191,166,233,240,219,194,69,92,119,110,33,56,19,10,7,30,53,44,99,122,81,72,207,214,253,228,171,178,153,128,138,147,184,161,238,247,220,197,66,91,112,105,38,63,20,13,14,23,60,37,106,115,88,65,198,223,244,237,162,187,144,137,131,154,177,168,231,254,213,204,75,82,121,96,47,54,29,4,9,16,59,34,109,116,95,70,193,216,243,234,165,188,151,142,132,157,182,175,224,249,210,203,76,85,126,103,40,49,26,3,28,5,46,55,120,97,74,83,212,205,230,255,176,169,130,155,145,136,163,186,245,236,199,222,89,64,107,114,61,36,15,22,27,2,41,48,127,102,77,84,211,202,225,248,183,174,133,156,150,143,164,189,242,235,192,217,94,71,108,117,58,35,8,17,18,11,32,57,118,111,68,93,218,195,232,241,190,167,140,149,159,134,173,180,251,226,201,208,87,78,101,124,51,42,1,24,21,12,39,62,113,104,67,90,221,196,239,246,185,160,139,146,152,129,170,179,252,229,206,215,80,73,98,123,52,45,6,31}, + {0,26,52,46,104,114,92,70,208,202,228,254,184,162,140,150,189,167,137,147,213,207,225,251,109,119,89,67,5,31,49,43,103,125,83,73,15,21,59,33,183,173,131,153,223,197,235,241,218,192,238,244,178,168,134,156,10,16,62,36,98,120,86,76,206,212,250,224,166,188,146,136,30,4,42,48,118,108,66,88,115,105,71,93,27,1,47,53,163,185,151,141,203,209,255,229,169,179,157,135,193,219,245,239,121,99,77,87,17,11,37,63,20,14,32,58,124,102,72,82,196,222,240,234,172,182,152,130,129,155,181,175,233,243,221,199,81,75,101,127,57,35,13,23,60,38,8,18,84,78,96,122,236,246,216,194,132,158,176,170,230,252,210,200,142,148,186,160,54,44,2,24,94,68,106,112,91,65,111,117,51,41,7,29,139,145,191,165,227,249,215,205,79,85,123,97,39,61,19,9,159,133,171,177,247,237,195,217,242,232,198,220,154,128,174,180,34,56,22,12,74,80,126,100,40,50,28,6,64,90,116,110,248,226,204,214,144,138,164,190,149,143,161,187,253,231,201,211,69,95,113,107,45,55,25,3}, + {0,27,54,45,108,119,90,65,216,195,238,245,180,175,130,153,173,182,155,128,193,218,247,236,117,110,67,88,25,2,47,52,71,92,113,106,43,48,29,6,159,132,169,178,243,232,197,222,234,241,220,199,134,157,176,171,50,41,4,31,94,69,104,115,142,149,184,163,226,249,212,207,86,77,96,123,58,33,12,23,35,56,21,14,79,84,121,98,251,224,205,214,151,140,161,186,201,210,255,228,165,190,147,136,17,10,39,60,125,102,75,80,100,127,82,73,8,19,62,37,188,167,138,145,208,203,230,253,1,26,55,44,109,118,91,64,217,194,239,244,181,174,131,152,172,183,154,129,192,219,246,237,116,111,66,89,24,3,46,53,70,93,112,107,42,49,28,7,158,133,168,179,242,233,196,223,235,240,221,198,135,156,177,170,51,40,5,30,95,68,105,114,143,148,185,162,227,248,213,206,87,76,97,122,59,32,13,22,34,57,20,15,78,85,120,99,250,225,204,215,150,141,160,187,200,211,254,229,164,191,146,137,16,11,38,61,124,103,74,81,101,126,83,72,9,18,63,36,189,166,139,144,209,202,231,252}, + {0,28,56,36,112,108,72,84,224,252,216,196,144,140,168,180,221,193,229,249,173,177,149,137,61,33,5,25,77,81,117,105,167,187,159,131,215,203,239,243,71,91,127,99,55,43,15,19,122,102,66,94,10,22,50,46,154,134,162,190,234,246,210,206,83,79,107,119,35,63,27,7,179,175,139,151,195,223,251,231,142,146,182,170,254,226,198,218,110,114,86,74,30,2,38,58,244,232,204,208,132,152,188,160,20,8,44,48,100,120,92,64,41,53,17,13,89,69,97,125,201,213,241,237,185,165,129,157,166,186,158,130,214,202,238,242,70,90,126,98,54,42,14,18,123,103,67,95,11,23,51,47,155,135,163,191,235,247,211,207,1,29,57,37,113,109,73,85,225,253,217,197,145,141,169,181,220,192,228,248,172,176,148,136,60,32,4,24,76,80,116,104,245,233,205,209,133,153,189,161,21,9,45,49,101,121,93,65,40,52,16,12,88,68,96,124,200,212,240,236,184,164,128,156,82,78,106,118,34,62,26,6,178,174,138,150,194,222,250,230,143,147,183,171,255,227,199,219,111,115,87,75,31,3,39,59}, + {0,29,58,39,116,105,78,83,232,245,210,207,156,129,166,187,205,208,247,234,185,164,131,158,37,56,31,2,81,76,107,118,135,154,189,160,243,238,201,212,111,114,85,72,27,6,33,60,74,87,112,109,62,35,4,25,162,191,152,133,214,203,236,241,19,14,41,52,103,122,93,64,251,230,193,220,143,146,181,168,222,195,228,249,170,183,144,141,54,43,12,17,66,95,120,101,148,137,174,179,224,253,218,199,124,97,70,91,8,21,50,47,89,68,99,126,45,48,23,10,177,172,139,150,197,216,255,226,38,59,28,1,82,79,104,117,206,211,244,233,186,167,128,157,235,246,209,204,159,130,165,184,3,30,57,36,119,106,77,80,161,188,155,134,213,200,239,242,73,84,115,110,61,32,7,26,108,113,86,75,24,5,34,63,132,153,190,163,240,237,202,215,53,40,15,18,65,92,123,102,221,192,231,250,169,180,147,142,248,229,194,223,140,145,182,171,16,13,42,55,100,121,94,67,178,175,136,149,198,219,252,225,90,71,96,125,46,51,20,9,127,98,69,88,11,22,49,44,151,138,173,176,227,254,217,196}, + {0,30,60,34,120,102,68,90,240,238,204,210,136,150,180,170,253,227,193,223,133,155,185,167,13,19,49,47,117,107,73,87,231,249,219,197,159,129,163,189,23,9,43,53,111,113,83,77,26,4,38,56,98,124,94,64,234,244,214,200,146,140,174,176,211,205,239,241,171,181,151,137,35,61,31,1,91,69,103,121,46,48,18,12,86,72,106,116,222,192,226,252,166,184,154,132,52,42,8,22,76,82,112,110,196,218,248,230,188,162,128,158,201,215,245,235,177,175,141,147,57,39,5,27,65,95,125,99,187,165,135,153,195,221,255,225,75,85,119,105,51,45,15,17,70,88,122,100,62,32,2,28,182,168,138,148,206,208,242,236,92,66,96,126,36,58,24,6,172,178,144,142,212,202,232,246,161,191,157,131,217,199,229,251,81,79,109,115,41,55,21,11,104,118,84,74,16,14,44,50,152,134,164,186,224,254,220,194,149,139,169,183,237,243,209,207,101,123,89,71,29,3,33,63,143,145,179,173,247,233,203,213,127,97,67,93,7,25,59,37,114,108,78,80,10,20,54,40,130,156,190,160,250,228,198,216}, + {0,31,62,33,124,99,66,93,248,231,198,217,132,155,186,165,237,242,211,204,145,142,175,176,21,10,43,52,105,118,87,72,199,216,249,230,187,164,133,154,63,32,1,30,67,92,125,98,42,53,20,11,86,73,104,119,210,205,236,243,174,177,144,143,147,140,173,178,239,240,209,206,107,116,85,74,23,8,41,54,126,97,64,95,2,29,60,35,134,153,184,167,250,229,196,219,84,75,106,117,40,55,22,9,172,179,146,141,208,207,238,241,185,166,135,152,197,218,251,228,65,94,127,96,61,34,3,28,59,36,5,26,71,88,121,102,195,220,253,226,191,160,129,158,214,201,232,247,170,181,148,139,46,49,16,15,82,77,108,115,252,227,194,221,128,159,190,161,4,27,58,37,120,103,70,89,17,14,47,48,109,114,83,76,233,246,215,200,149,138,171,180,168,183,150,137,212,203,234,245,80,79,110,113,44,51,18,13,69,90,123,100,57,38,7,24,189,162,131,156,193,222,255,224,111,112,81,78,19,12,45,50,151,136,169,182,235,244,213,202,130,157,188,163,254,225,192,223,122,101,68,91,6,25,56,39}, + {0,32,64,96,128,160,192,224,29,61,93,125,157,189,221,253,58,26,122,90,186,154,250,218,39,7,103,71,167,135,231,199,116,84,52,20,244,212,180,148,105,73,41,9,233,201,169,137,78,110,14,46,206,238,142,174,83,115,19,51,211,243,147,179,232,200,168,136,104,72,40,8,245,213,181,149,117,85,53,21,210,242,146,178,82,114,18,50,207,239,143,175,79,111,15,47,156,188,220,252,28,60,92,124,129,161,193,225,1,33,65,97,166,134,230,198,38,6,102,70,187,155,251,219,59,27,123,91,205,237,141,173,77,109,13,45,208,240,144,176,80,112,16,48,247,215,183,151,119,87,55,23,234,202,170,138,106,74,42,10,185,153,249,217,57,25,121,89,164,132,228,196,36,4,100,68,131,163,195,227,3,35,67,99,158,190,222,254,30,62,94,126,37,5,101,69,165,133,229,197,56,24,120,88,184,152,248,216,31,63,95,127,159,191,223,255,2,34,66,98,130,162,194,226,81,113,17,49,209,241,145,177,76,108,12,44,204,236,140,172,107,75,43,11,235,203,171,139,118,86,54,22,246,214,182,150}, + {0,33,66,99,132,165,198,231,21,52,87,118,145,176,211,242,42,11,104,73,174,143,236,205,63,30,125,92,187,154,249,216,84,117,22,55,208,241,146,179,65,96,3,34,197,228,135,166,126,95,60,29,250,219,184,153,107,74,41,8,239,206,173,140,168,137,234,203,44,13,110,79,189,156,255,222,57,24,123,90,130,163,192,225,6,39,68,101,151,182,213,244,19,50,81,112,252,221,190,159,120,89,58,27,233,200,171,138,109,76,47,14,214,247,148,181,82,115,16,49,195,226,129,160,71,102,5,36,77,108,15,46,201,232,139,170,88,121,26,59,220,253,158,191,103,70,37,4,227,194,161,128,114,83,48,17,246,215,180,149,25,56,91,122,157,188,223,254,12,45,78,111,136,169,202,235,51,18,113,80,183,150,245,212,38,7,100,69,162,131,224,193,229,196,167,134,97,64,35,2,240,209,178,147,116,85,54,23,207,238,141,172,75,106,9,40,218,251,152,185,94,127,28,61,177,144,243,210,53,20,119,86,164,133,230,199,32,1,98,67,155,186,217,248,31,62,93,124,142,175,204,237,10,43,72,105}, + {0,34,68,102,136,170,204,238,13,47,73,107,133,167,193,227,26,56,94,124,146,176,214,244,23,53,83,113,159,189,219,249,52,22,112,82,188,158,248,218,57,27,125,95,177,147,245,215,46,12,106,72,166,132,226,192,35,1,103,69,171,137,239,205,104,74,44,14,224,194,164,134,101,71,33,3,237,207,169,139,114,80,54,20,250,216,190,156,127,93,59,25,247,213,179,145,92,126,24,58,212,246,144,178,81,115,21,55,217,251,157,191,70,100,2,32,206,236,138,168,75,105,15,45,195,225,135,165,208,242,148,182,88,122,28,62,221,255,153,187,85,119,17,51,202,232,142,172,66,96,6,36,199,229,131,161,79,109,11,41,228,198,160,130,108,78,40,10,233,203,173,143,97,67,37,7,254,220,186,152,118,84,50,16,243,209,183,149,123,89,63,29,184,154,252,222,48,18,116,86,181,151,241,211,61,31,121,91,162,128,230,196,42,8,110,76,175,141,235,201,39,5,99,65,140,174,200,234,4,38,64,98,129,163,197,231,9,43,77,111,150,180,210,240,30,60,90,120,155,185,223,253,19,49,87,117}, + {0,35,70,101,140,175,202,233,5,38,67,96,137,170,207,236,10,41,76,111,134,165,192,227,15,44,73,106,131,160,197,230,20,55,82,113,152,187,222,253,17,50,87,116,157,190,219,248,30,61,88,123,146,177,212,247,27,56,93,126,151,180,209,242,40,11,110,77,164,135,226,193,45,14,107,72,161,130,231,196,34,1,100,71,174,141,232,203,39,4,97,66,171,136,237,206,60,31,122,89,176,147,246,213,57,26,127,92,181,150,243,208,54,21,112,83,186,153,252,223,51,16,117,86,191,156,249,218,80,115,22,53,220,255,154,185,85,118,19,48,217,250,159,188,90,121,28,63,214,245,144,179,95,124,25,58,211,240,149,182,68,103,2,33,200,235,142,173,65,98,7,36,205,238,139,168,78,109,8,43,194,225,132,167,75,104,13,46,199,228,129,162,120,91,62,29,244,215,178,145,125,94,59,24,241,210,183,148,114,81,52,23,254,221,184,155,119,84,49,18,251,216,189,158,108,79,42,9,224,195,166,133,105,74,47,12,229,198,163,128,102,69,32,3,234,201,172,143,99,64,37,6,239,204,169,138}, + {0,36,72,108,144,180,216,252,61,25,117,81,173,137,229,193,122,94,50,22,234,206,162,134,71,99,15,43,215,243,159,187,244,208,188,152,100,64,44,8,201,237,129,165,89,125,17,53,142,170,198,226,30,58,86,114,179,151,251,223,35,7,107,79,245,209,189,153,101,65,45,9,200,236,128,164,88,124,16,52,143,171,199,227,31,59,87,115,178,150,250,222,34,6,106,78,1,37,73,109,145,181,217,253,60,24,116,80,172,136,228,192,123,95,51,23,235,207,163,135,70,98,14,42,214,242,158,186,247,211,191,155,103,67,47,11,202,238,130,166,90,126,18,54,141,169,197,225,29,57,85,113,176,148,248,220,32,4,104,76,3,39,75,111,147,183,219,255,62,26,118,82,174,138,230,194,121,93,49,21,233,205,161,133,68,96,12,40,212,240,156,184,2,38,74,110,146,182,218,254,63,27,119,83,175,139,231,195,120,92,48,20,232,204,160,132,69,97,13,41,213,241,157,185,246,210,190,154,102,66,46,10,203,239,131,167,91,127,19,55,140,168,196,224,28,56,84,112,177,149,249,221,33,5,105,77}, + {0,37,74,111,148,177,222,251,53,16,127,90,161,132,235,206,106,79,32,5,254,219,180,145,95,122,21,48,203,238,129,164,212,241,158,187,64,101,10,47,225,196,171,142,117,80,63,26,190,155,244,209,42,15,96,69,139,174,193,228,31,58,85,112,181,144,255,218,33,4,107,78,128,165,202,239,20,49,94,123,223,250,149,176,75,110,1,36,234,207,160,133,126,91,52,17,97,68,43,14,245,208,191,154,84,113,30,59,192,229,138,175,11,46,65,100,159,186,213,240,62,27,116,81,170,143,224,197,119,82,61,24,227,198,169,140,66,103,8,45,214,243,156,185,29,56,87,114,137,172,195,230,40,13,98,71,188,153,246,211,163,134,233,204,55,18,125,88,150,179,220,249,2,39,72,109,201,236,131,166,93,120,23,50,252,217,182,147,104,77,34,7,194,231,136,173,86,115,28,57,247,210,189,152,99,70,41,12,168,141,226,199,60,25,118,83,157,184,215,242,9,44,67,102,22,51,92,121,130,167,200,237,35,6,105,76,183,146,253,216,124,89,54,19,232,205,162,135,73,108,3,38,221,248,151,178}, + {0,38,76,106,152,190,212,242,45,11,97,71,181,147,249,223,90,124,22,48,194,228,142,168,119,81,59,29,239,201,163,133,180,146,248,222,44,10,96,70,153,191,213,243,1,39,77,107,238,200,162,132,118,80,58,28,195,229,143,169,91,125,23,49,117,83,57,31,237,203,161,135,88,126,20,50,192,230,140,170,47,9,99,69,183,145,251,221,2,36,78,104,154,188,214,240,193,231,141,171,89,127,21,51,236,202,160,134,116,82,56,30,155,189,215,241,3,37,79,105,182,144,250,220,46,8,98,68,234,204,166,128,114,84,62,24,199,225,139,173,95,121,19,53,176,150,252,218,40,14,100,66,157,187,209,247,5,35,73,111,94,120,18,52,198,224,138,172,115,85,63,25,235,205,167,129,4,34,72,110,156,186,208,246,41,15,101,67,177,151,253,219,159,185,211,245,7,33,75,109,178,148,254,216,42,12,102,64,197,227,137,175,93,123,17,55,232,206,164,130,112,86,60,26,43,13,103,65,179,149,255,217,6,32,74,108,158,184,210,244,113,87,61,27,233,207,165,131,92,122,16,54,196,226,136,174}, + {0,39,78,105,156,187,210,245,37,2,107,76,185,158,247,208,74,109,4,35,214,241,152,191,111,72,33,6,243,212,189,154,148,179,218,253,8,47,70,97,177,150,255,216,45,10,99,68,222,249,144,183,66,101,12,43,251,220,181,146,103,64,41,14,53,18,123,92,169,142,231,192,16,55,94,121,140,171,194,229,127,88,49,22,227,196,173,138,90,125,20,51,198,225,136,175,161,134,239,200,61,26,115,84,132,163,202,237,24,63,86,113,235,204,165,130,119,80,57,30,206,233,128,167,82,117,28,59,106,77,36,3,246,209,184,159,79,104,1,38,211,244,157,186,32,7,110,73,188,155,242,213,5,34,75,108,153,190,215,240,254,217,176,151,98,69,44,11,219,252,149,178,71,96,9,46,180,147,250,221,40,15,102,65,145,182,223,248,13,42,67,100,95,120,17,54,195,228,141,170,122,93,52,19,230,193,168,143,21,50,91,124,137,174,199,224,48,23,126,89,172,139,226,197,203,236,133,162,87,112,25,62,238,201,160,135,114,85,60,27,129,166,207,232,29,58,83,116,164,131,234,205,56,31,118,81}, + {0,40,80,120,160,136,240,216,93,117,13,37,253,213,173,133,186,146,234,194,26,50,74,98,231,207,183,159,71,111,23,63,105,65,57,17,201,225,153,177,52,28,100,76,148,188,196,236,211,251,131,171,115,91,35,11,142,166,222,246,46,6,126,86,210,250,130,170,114,90,34,10,143,167,223,247,47,7,127,87,104,64,56,16,200,224,152,176,53,29,101,77,149,189,197,237,187,147,235,195,27,51,75,99,230,206,182,158,70,110,22,62,1,41,81,121,161,137,241,217,92,116,12,36,252,212,172,132,185,145,233,193,25,49,73,97,228,204,180,156,68,108,20,60,3,43,83,123,163,139,243,219,94,118,14,38,254,214,174,134,208,248,128,168,112,88,32,8,141,165,221,245,45,5,125,85,106,66,58,18,202,226,154,178,55,31,103,79,151,191,199,239,107,67,59,19,203,227,155,179,54,30,102,78,150,190,198,238,209,249,129,169,113,89,33,9,140,164,220,244,44,4,124,84,2,42,82,122,162,138,242,218,95,119,15,39,255,215,175,135,184,144,232,192,24,48,72,96,229,205,181,157,69,109,21,61}, + {0,41,82,123,164,141,246,223,85,124,7,46,241,216,163,138,170,131,248,209,14,39,92,117,255,214,173,132,91,114,9,32,73,96,27,50,237,196,191,150,28,53,78,103,184,145,234,195,227,202,177,152,71,110,21,60,182,159,228,205,18,59,64,105,146,187,192,233,54,31,100,77,199,238,149,188,99,74,49,24,56,17,106,67,156,181,206,231,109,68,63,22,201,224,155,178,219,242,137,160,127,86,45,4,142,167,220,245,42,3,120,81,113,88,35,10,213,252,135,174,36,13,118,95,128,169,210,251,57,16,107,66,157,180,207,230,108,69,62,23,200,225,154,179,147,186,193,232,55,30,101,76,198,239,148,189,98,75,48,25,112,89,34,11,212,253,134,175,37,12,119,94,129,168,211,250,218,243,136,161,126,87,44,5,143,166,221,244,43,2,121,80,171,130,249,208,15,38,93,116,254,215,172,133,90,115,8,33,1,40,83,122,165,140,247,222,84,125,6,47,240,217,162,139,226,203,176,153,70,111,20,61,183,158,229,204,19,58,65,104,72,97,26,51,236,197,190,151,29,52,79,102,185,144,235,194}, + {0,42,84,126,168,130,252,214,77,103,25,51,229,207,177,155,154,176,206,228,50,24,102,76,215,253,131,169,127,85,43,1,41,3,125,87,129,171,213,255,100,78,48,26,204,230,152,178,179,153,231,205,27,49,79,101,254,212,170,128,86,124,2,40,82,120,6,44,250,208,174,132,31,53,75,97,183,157,227,201,200,226,156,182,96,74,52,30,133,175,209,251,45,7,121,83,123,81,47,5,211,249,135,173,54,28,98,72,158,180,202,224,225,203,181,159,73,99,29,55,172,134,248,210,4,46,80,122,164,142,240,218,12,38,88,114,233,195,189,151,65,107,21,63,62,20,106,64,150,188,194,232,115,89,39,13,219,241,143,165,141,167,217,243,37,15,113,91,192,234,148,190,104,66,60,22,23,61,67,105,191,149,235,193,90,112,14,36,242,216,166,140,246,220,162,136,94,116,10,32,187,145,239,197,19,57,71,109,108,70,56,18,196,238,144,186,33,11,117,95,137,163,221,247,223,245,139,161,119,93,35,9,146,184,198,236,58,16,110,68,69,111,17,59,237,199,185,147,8,34,92,118,160,138,244,222}, + {0,43,86,125,172,135,250,209,69,110,19,56,233,194,191,148,138,161,220,247,38,13,112,91,207,228,153,178,99,72,53,30,9,34,95,116,165,142,243,216,76,103,26,49,224,203,182,157,131,168,213,254,47,4,121,82,198,237,144,187,106,65,60,23,18,57,68,111,190,149,232,195,87,124,1,42,251,208,173,134,152,179,206,229,52,31,98,73,221,246,139,160,113,90,39,12,27,48,77,102,183,156,225,202,94,117,8,35,242,217,164,143,145,186,199,236,61,22,107,64,212,255,130,169,120,83,46,5,36,15,114,89,136,163,222,245,97,74,55,28,205,230,155,176,174,133,248,211,2,41,84,127,235,192,189,150,71,108,17,58,45,6,123,80,129,170,215,252,104,67,62,21,196,239,146,185,167,140,241,218,11,32,93,118,226,201,180,159,78,101,24,51,54,29,96,75,154,177,204,231,115,88,37,14,223,244,137,162,188,151,234,193,16,59,70,109,249,210,175,132,85,126,3,40,63,20,105,66,147,184,197,238,122,81,44,7,214,253,128,171,181,158,227,200,25,50,79,100,240,219,166,141,92,119,10,33}, + {0,44,88,116,176,156,232,196,125,81,37,9,205,225,149,185,250,214,162,142,74,102,18,62,135,171,223,243,55,27,111,67,233,197,177,157,89,117,1,45,148,184,204,224,36,8,124,80,19,63,75,103,163,143,251,215,110,66,54,26,222,242,134,170,207,227,151,187,127,83,39,11,178,158,234,198,2,46,90,118,53,25,109,65,133,169,221,241,72,100,16,60,248,212,160,140,38,10,126,82,150,186,206,226,91,119,3,47,235,199,179,159,220,240,132,168,108,64,52,24,161,141,249,213,17,61,73,101,131,175,219,247,51,31,107,71,254,210,166,138,78,98,22,58,121,85,33,13,201,229,145,189,4,40,92,112,180,152,236,192,106,70,50,30,218,246,130,174,23,59,79,99,167,139,255,211,144,188,200,228,32,12,120,84,237,193,181,153,93,113,5,41,76,96,20,56,252,208,164,136,49,29,105,69,129,173,217,245,182,154,238,194,6,42,94,114,203,231,147,191,123,87,35,15,165,137,253,209,21,57,77,97,216,244,128,172,104,68,48,28,95,115,7,43,239,195,183,155,34,14,122,86,146,190,202,230}, + {0,45,90,119,180,153,238,195,117,88,47,2,193,236,155,182,234,199,176,157,94,115,4,41,159,178,197,232,43,6,113,92,201,228,147,190,125,80,39,10,188,145,230,203,8,37,82,127,35,14,121,84,151,186,205,224,86,123,12,33,226,207,184,149,143,162,213,248,59,22,97,76,250,215,160,141,78,99,20,57,101,72,63,18,209,252,139,166,16,61,74,103,164,137,254,211,70,107,28,49,242,223,168,133,51,30,105,68,135,170,221,240,172,129,246,219,24,53,66,111,217,244,131,174,109,64,55,26,3,46,89,116,183,154,237,192,118,91,44,1,194,239,152,181,233,196,179,158,93,112,7,42,156,177,198,235,40,5,114,95,202,231,144,189,126,83,36,9,191,146,229,200,11,38,81,124,32,13,122,87,148,185,206,227,85,120,15,34,225,204,187,150,140,161,214,251,56,21,98,79,249,212,163,142,77,96,23,58,102,75,60,17,210,255,136,165,19,62,73,100,167,138,253,208,69,104,31,50,241,220,171,134,48,29,106,71,132,169,222,243,175,130,245,216,27,54,65,108,218,247,128,173,110,67,52,25}, + {0,46,92,114,184,150,228,202,109,67,49,31,213,251,137,167,218,244,134,168,98,76,62,16,183,153,235,197,15,33,83,125,169,135,245,219,17,63,77,99,196,234,152,182,124,82,32,14,115,93,47,1,203,229,151,185,30,48,66,108,166,136,250,212,79,97,19,61,247,217,171,133,34,12,126,80,154,180,198,232,149,187,201,231,45,3,113,95,248,214,164,138,64,110,28,50,230,200,186,148,94,112,2,44,139,165,215,249,51,29,111,65,60,18,96,78,132,170,216,246,81,127,13,35,233,199,181,155,158,176,194,236,38,8,122,84,243,221,175,129,75,101,23,57,68,106,24,54,252,210,160,142,41,7,117,91,145,191,205,227,55,25,107,69,143,161,211,253,90,116,6,40,226,204,190,144,237,195,177,159,85,123,9,39,128,174,220,242,56,22,100,74,209,255,141,163,105,71,53,27,188,146,224,206,4,42,88,118,11,37,87,121,179,157,239,193,102,72,58,20,222,240,130,172,120,86,36,10,192,238,156,178,21,59,73,103,173,131,241,223,162,140,254,208,26,52,70,104,207,225,147,189,119,89,43,5}, + {0,47,94,113,188,147,226,205,101,74,59,20,217,246,135,168,202,229,148,187,118,89,40,7,175,128,241,222,19,60,77,98,137,166,215,248,53,26,107,68,236,195,178,157,80,127,14,33,67,108,29,50,255,208,161,142,38,9,120,87,154,181,196,235,15,32,81,126,179,156,237,194,106,69,52,27,214,249,136,167,197,234,155,180,121,86,39,8,160,143,254,209,28,51,66,109,134,169,216,247,58,21,100,75,227,204,189,146,95,112,1,46,76,99,18,61,240,223,174,129,41,6,119,88,149,186,203,228,30,49,64,111,162,141,252,211,123,84,37,10,199,232,153,182,212,251,138,165,104,71,54,25,177,158,239,192,13,34,83,124,151,184,201,230,43,4,117,90,242,221,172,131,78,97,16,63,93,114,3,44,225,206,191,144,56,23,102,73,132,171,218,245,17,62,79,96,173,130,243,220,116,91,42,5,200,231,150,185,219,244,133,170,103,72,57,22,190,145,224,207,2,45,92,115,152,183,198,233,36,11,122,85,253,210,163,140,65,110,31,48,82,125,12,35,238,193,176,159,55,24,105,70,139,164,213,250}, + {0,48,96,80,192,240,160,144,157,173,253,205,93,109,61,13,39,23,71,119,231,215,135,183,186,138,218,234,122,74,26,42,78,126,46,30,142,190,238,222,211,227,179,131,19,35,115,67,105,89,9,57,169,153,201,249,244,196,148,164,52,4,84,100,156,172,252,204,92,108,60,12,1,49,97,81,193,241,161,145,187,139,219,235,123,75,27,43,38,22,70,118,230,214,134,182,210,226,178,130,18,34,114,66,79,127,47,31,143,191,239,223,245,197,149,165,53,5,85,101,104,88,8,56,168,152,200,248,37,21,69,117,229,213,133,181,184,136,216,232,120,72,24,40,2,50,98,82,194,242,162,146,159,175,255,207,95,111,63,15,107,91,11,59,171,155,203,251,246,198,150,166,54,6,86,102,76,124,44,28,140,188,236,220,209,225,177,129,17,33,113,65,185,137,217,233,121,73,25,41,36,20,68,116,228,212,132,180,158,174,254,206,94,110,62,14,3,51,99,83,195,243,163,147,247,199,151,167,55,7,87,103,106,90,10,58,170,154,202,250,208,224,176,128,16,32,112,64,77,125,45,29,141,189,237,221}, + {0,49,98,83,196,245,166,151,149,164,247,198,81,96,51,2,55,6,85,100,243,194,145,160,162,147,192,241,102,87,4,53,110,95,12,61,170,155,200,249,251,202,153,168,63,14,93,108,89,104,59,10,157,172,255,206,204,253,174,159,8,57,106,91,220,237,190,143,24,41,122,75,73,120,43,26,141,188,239,222,235,218,137,184,47,30,77,124,126,79,28,45,186,139,216,233,178,131,208,225,118,71,20,37,39,22,69,116,227,210,129,176,133,180,231,214,65,112,35,18,16,33,114,67,212,229,182,135,165,148,199,246,97,80,3,50,48,1,82,99,244,197,150,167,146,163,240,193,86,103,52,5,7,54,101,84,195,242,161,144,203,250,169,152,15,62,109,92,94,111,60,13,154,171,248,201,252,205,158,175,56,9,90,107,105,88,11,58,173,156,207,254,121,72,27,42,189,140,223,238,236,221,142,191,40,25,74,123,78,127,44,29,138,187,232,217,219,234,185,136,31,46,125,76,23,38,117,68,211,226,177,128,130,179,224,209,70,119,36,21,32,17,66,115,228,213,134,183,181,132,215,230,113,64,19,34}, + {0,50,100,86,200,250,172,158,141,191,233,219,69,119,33,19,7,53,99,81,207,253,171,153,138,184,238,220,66,112,38,20,14,60,106,88,198,244,162,144,131,177,231,213,75,121,47,29,9,59,109,95,193,243,165,151,132,182,224,210,76,126,40,26,28,46,120,74,212,230,176,130,145,163,245,199,89,107,61,15,27,41,127,77,211,225,183,133,150,164,242,192,94,108,58,8,18,32,118,68,218,232,190,140,159,173,251,201,87,101,51,1,21,39,113,67,221,239,185,139,152,170,252,206,80,98,52,6,56,10,92,110,240,194,148,166,181,135,209,227,125,79,25,43,63,13,91,105,247,197,147,161,178,128,214,228,122,72,30,44,54,4,82,96,254,204,154,168,187,137,223,237,115,65,23,37,49,3,85,103,249,203,157,175,188,142,216,234,116,70,16,34,36,22,64,114,236,222,136,186,169,155,205,255,97,83,5,55,35,17,71,117,235,217,143,189,174,156,202,248,102,84,2,48,42,24,78,124,226,208,134,180,167,149,195,241,111,93,11,57,45,31,73,123,229,215,129,179,160,146,196,246,104,90,12,62}, + {0,51,102,85,204,255,170,153,133,182,227,208,73,122,47,28,23,36,113,66,219,232,189,142,146,161,244,199,94,109,56,11,46,29,72,123,226,209,132,183,171,152,205,254,103,84,1,50,57,10,95,108,245,198,147,160,188,143,218,233,112,67,22,37,92,111,58,9,144,163,246,197,217,234,191,140,21,38,115,64,75,120,45,30,135,180,225,210,206,253,168,155,2,49,100,87,114,65,20,39,190,141,216,235,247,196,145,162,59,8,93,110,101,86,3,48,169,154,207,252,224,211,134,181,44,31,74,121,184,139,222,237,116,71,18,33,61,14,91,104,241,194,151,164,175,156,201,250,99,80,5,54,42,25,76,127,230,213,128,179,150,165,240,195,90,105,60,15,19,32,117,70,223,236,185,138,129,178,231,212,77,126,43,24,4,55,98,81,200,251,174,157,228,215,130,177,40,27,78,125,97,82,7,52,173,158,203,248,243,192,149,166,63,12,89,106,118,69,16,35,186,137,220,239,202,249,172,159,6,53,96,83,79,124,41,26,131,176,229,214,221,238,187,136,17,34,119,68,88,107,62,13,148,167,242,193}, + {0,52,104,92,208,228,184,140,189,137,213,225,109,89,5,49,103,83,15,59,183,131,223,235,218,238,178,134,10,62,98,86,206,250,166,146,30,42,118,66,115,71,27,47,163,151,203,255,169,157,193,245,121,77,17,37,20,32,124,72,196,240,172,152,129,181,233,221,81,101,57,13,60,8,84,96,236,216,132,176,230,210,142,186,54,2,94,106,91,111,51,7,139,191,227,215,79,123,39,19,159,171,247,195,242,198,154,174,34,22,74,126,40,28,64,116,248,204,144,164,149,161,253,201,69,113,45,25,31,43,119,67,207,251,167,147,162,150,202,254,114,70,26,46,120,76,16,36,168,156,192,244,197,241,173,153,21,33,125,73,209,229,185,141,1,53,105,93,108,88,4,48,188,136,212,224,182,130,222,234,102,82,14,58,11,63,99,87,219,239,179,135,158,170,246,194,78,122,38,18,35,23,75,127,243,199,155,175,249,205,145,165,41,29,65,117,68,112,44,24,148,160,252,200,80,100,56,12,128,180,232,220,237,217,133,177,61,9,85,97,55,3,95,107,231,211,143,187,138,190,226,214,90,110,50,6}, + {0,53,106,95,212,225,190,139,181,128,223,234,97,84,11,62,119,66,29,40,163,150,201,252,194,247,168,157,22,35,124,73,238,219,132,177,58,15,80,101,91,110,49,4,143,186,229,208,153,172,243,198,77,120,39,18,44,25,70,115,248,205,146,167,193,244,171,158,21,32,127,74,116,65,30,43,160,149,202,255,182,131,220,233,98,87,8,61,3,54,105,92,215,226,189,136,47,26,69,112,251,206,145,164,154,175,240,197,78,123,36,17,88,109,50,7,140,185,230,211,237,216,135,178,57,12,83,102,159,170,245,192,75,126,33,20,42,31,64,117,254,203,148,161,232,221,130,183,60,9,86,99,93,104,55,2,137,188,227,214,113,68,27,46,165,144,207,250,196,241,174,155,16,37,122,79,6,51,108,89,210,231,184,141,179,134,217,236,103,82,13,56,94,107,52,1,138,191,224,213,235,222,129,180,63,10,85,96,41,28,67,118,253,200,151,162,156,169,246,195,72,125,34,23,176,133,218,239,100,81,14,59,5,48,111,90,209,228,187,142,199,242,173,152,19,38,121,76,114,71,24,45,166,147,204,249}, + {0,54,108,90,216,238,180,130,173,155,193,247,117,67,25,47,71,113,43,29,159,169,243,197,234,220,134,176,50,4,94,104,142,184,226,212,86,96,58,12,35,21,79,121,251,205,151,161,201,255,165,147,17,39,125,75,100,82,8,62,188,138,208,230,1,55,109,91,217,239,181,131,172,154,192,246,116,66,24,46,70,112,42,28,158,168,242,196,235,221,135,177,51,5,95,105,143,185,227,213,87,97,59,13,34,20,78,120,250,204,150,160,200,254,164,146,16,38,124,74,101,83,9,63,189,139,209,231,2,52,110,88,218,236,182,128,175,153,195,245,119,65,27,45,69,115,41,31,157,171,241,199,232,222,132,178,48,6,92,106,140,186,224,214,84,98,56,14,33,23,77,123,249,207,149,163,203,253,167,145,19,37,127,73,102,80,10,60,190,136,210,228,3,53,111,89,219,237,183,129,174,152,194,244,118,64,26,44,68,114,40,30,156,170,240,198,233,223,133,179,49,7,93,107,141,187,225,215,85,99,57,15,32,22,76,122,248,206,148,162,202,252,166,144,18,36,126,72,103,81,11,61,191,137,211,229}, + {0,55,110,89,220,235,178,133,165,146,203,252,121,78,23,32,87,96,57,14,139,188,229,210,242,197,156,171,46,25,64,119,174,153,192,247,114,69,28,43,11,60,101,82,215,224,185,142,249,206,151,160,37,18,75,124,92,107,50,5,128,183,238,217,65,118,47,24,157,170,243,196,228,211,138,189,56,15,86,97,22,33,120,79,202,253,164,147,179,132,221,234,111,88,1,54,239,216,129,182,51,4,93,106,74,125,36,19,150,161,248,207,184,143,214,225,100,83,10,61,29,42,115,68,193,246,175,152,130,181,236,219,94,105,48,7,39,16,73,126,251,204,149,162,213,226,187,140,9,62,103,80,112,71,30,41,172,155,194,245,44,27,66,117,240,199,158,169,137,190,231,208,85,98,59,12,123,76,21,34,167,144,201,254,222,233,176,135,2,53,108,91,195,244,173,154,31,40,113,70,102,81,8,63,186,141,212,227,148,163,250,205,72,127,38,17,49,6,95,104,237,218,131,180,109,90,3,52,177,134,223,232,200,255,166,145,20,35,122,77,58,13,84,99,230,209,136,191,159,168,241,198,67,116,45,26}, + {0,56,112,72,224,216,144,168,221,229,173,149,61,5,77,117,167,159,215,239,71,127,55,15,122,66,10,50,154,162,234,210,83,107,35,27,179,139,195,251,142,182,254,198,110,86,30,38,244,204,132,188,20,44,100,92,41,17,89,97,201,241,185,129,166,158,214,238,70,126,54,14,123,67,11,51,155,163,235,211,1,57,113,73,225,217,145,169,220,228,172,148,60,4,76,116,245,205,133,189,21,45,101,93,40,16,88,96,200,240,184,128,82,106,34,26,178,138,194,250,143,183,255,199,111,87,31,39,81,105,33,25,177,137,193,249,140,180,252,196,108,84,28,36,246,206,134,190,22,46,102,94,43,19,91,99,203,243,187,131,2,58,114,74,226,218,146,170,223,231,175,151,63,7,79,119,165,157,213,237,69,125,53,13,120,64,8,48,152,160,232,208,247,207,135,191,23,47,103,95,42,18,90,98,202,242,186,130,80,104,32,24,176,136,192,248,141,181,253,197,109,85,29,37,164,156,212,236,68,124,52,12,121,65,9,49,153,161,233,209,3,59,115,75,227,219,147,171,222,230,174,150,62,6,78,118}, + {0,57,114,75,228,221,150,175,213,236,167,158,49,8,67,122,183,142,197,252,83,106,33,24,98,91,16,41,134,191,244,205,115,74,1,56,151,174,229,220,166,159,212,237,66,123,48,9,196,253,182,143,32,25,82,107,17,40,99,90,245,204,135,190,230,223,148,173,2,59,112,73,51,10,65,120,215,238,165,156,81,104,35,26,181,140,199,254,132,189,246,207,96,89,18,43,149,172,231,222,113,72,3,58,64,121,50,11,164,157,214,239,34,27,80,105,198,255,180,141,247,206,133,188,19,42,97,88,209,232,163,154,53,12,71,126,4,61,118,79,224,217,146,171,102,95,20,45,130,187,240,201,179,138,193,248,87,110,37,28,162,155,208,233,70,127,52,13,119,78,5,60,147,170,225,216,21,44,103,94,241,200,131,186,192,249,178,139,36,29,86,111,55,14,69,124,211,234,161,152,226,219,144,169,6,63,116,77,128,185,242,203,100,93,22,47,85,108,39,30,177,136,195,250,68,125,54,15,160,153,210,235,145,168,227,218,117,76,7,62,243,202,129,184,23,46,101,92,38,31,84,109,194,251,176,137}, + {0,58,116,78,232,210,156,166,205,247,185,131,37,31,81,107,135,189,243,201,111,85,27,33,74,112,62,4,162,152,214,236,19,41,103,93,251,193,143,181,222,228,170,144,54,12,66,120,148,174,224,218,124,70,8,50,89,99,45,23,177,139,197,255,38,28,82,104,206,244,186,128,235,209,159,165,3,57,119,77,161,155,213,239,73,115,61,7,108,86,24,34,132,190,240,202,53,15,65,123,221,231,169,147,248,194,140,182,16,42,100,94,178,136,198,252,90,96,46,20,127,69,11,49,151,173,227,217,76,118,56,2,164,158,208,234,129,187,245,207,105,83,29,39,203,241,191,133,35,25,87,109,6,60,114,72,238,212,154,160,95,101,43,17,183,141,195,249,146,168,230,220,122,64,14,52,216,226,172,150,48,10,68,126,21,47,97,91,253,199,137,179,106,80,30,36,130,184,246,204,167,157,211,233,79,117,59,1,237,215,153,163,5,63,113,75,32,26,84,110,200,242,188,134,121,67,13,55,145,171,229,223,180,142,192,250,92,102,40,18,254,196,138,176,22,44,98,88,51,9,71,125,219,225,175,149}, + {0,59,118,77,236,215,154,161,197,254,179,136,41,18,95,100,151,172,225,218,123,64,13,54,82,105,36,31,190,133,200,243,51,8,69,126,223,228,169,146,246,205,128,187,26,33,108,87,164,159,210,233,72,115,62,5,97,90,23,44,141,182,251,192,102,93,16,43,138,177,252,199,163,152,213,238,79,116,57,2,241,202,135,188,29,38,107,80,52,15,66,121,216,227,174,149,85,110,35,24,185,130,207,244,144,171,230,221,124,71,10,49,194,249,180,143,46,21,88,99,7,60,113,74,235,208,157,166,204,247,186,129,32,27,86,109,9,50,127,68,229,222,147,168,91,96,45,22,183,140,193,250,158,165,232,211,114,73,4,63,255,196,137,178,19,40,101,94,58,1,76,119,214,237,160,155,104,83,30,37,132,191,242,201,173,150,219,224,65,122,55,12,170,145,220,231,70,125,48,11,111,84,25,34,131,184,245,206,61,6,75,112,209,234,167,156,248,195,142,181,20,47,98,89,153,162,239,212,117,78,3,56,92,103,42,17,176,139,198,253,14,53,120,67,226,217,148,175,203,240,189,134,39,28,81,106}, + {0,60,120,68,240,204,136,180,253,193,133,185,13,49,117,73,231,219,159,163,23,43,111,83,26,38,98,94,234,214,146,174,211,239,171,151,35,31,91,103,46,18,86,106,222,226,166,154,52,8,76,112,196,248,188,128,201,245,177,141,57,5,65,125,187,135,195,255,75,119,51,15,70,122,62,2,182,138,206,242,92,96,36,24,172,144,212,232,161,157,217,229,81,109,41,21,104,84,16,44,152,164,224,220,149,169,237,209,101,89,29,33,143,179,247,203,127,67,7,59,114,78,10,54,130,190,250,198,107,87,19,47,155,167,227,223,150,170,238,210,102,90,30,34,140,176,244,200,124,64,4,56,113,77,9,53,129,189,249,197,184,132,192,252,72,116,48,12,69,121,61,1,181,137,205,241,95,99,39,27,175,147,215,235,162,158,218,230,82,110,42,22,208,236,168,148,32,28,88,100,45,17,85,105,221,225,165,153,55,11,79,115,199,251,191,131,202,246,178,142,58,6,66,126,3,63,123,71,243,207,139,183,254,194,134,186,14,50,118,74,228,216,156,160,20,40,108,80,25,37,97,93,233,213,145,173}, + {0,61,122,71,244,201,142,179,245,200,143,178,1,60,123,70,247,202,141,176,3,62,121,68,2,63,120,69,246,203,140,177,243,206,137,180,7,58,125,64,6,59,124,65,242,207,136,181,4,57,126,67,240,205,138,183,241,204,139,182,5,56,127,66,251,198,129,188,15,50,117,72,14,51,116,73,250,199,128,189,12,49,118,75,248,197,130,191,249,196,131,190,13,48,119,74,8,53,114,79,252,193,134,187,253,192,135,186,9,52,115,78,255,194,133,184,11,54,113,76,10,55,112,77,254,195,132,185,235,214,145,172,31,34,101,88,30,35,100,89,234,215,144,173,28,33,102,91,232,213,146,175,233,212,147,174,29,32,103,90,24,37,98,95,236,209,150,171,237,208,151,170,25,36,99,94,239,210,149,168,27,38,97,92,26,39,96,93,238,211,148,169,16,45,106,87,228,217,158,163,229,216,159,162,17,44,107,86,231,218,157,160,19,46,105,84,18,47,104,85,230,219,156,161,227,222,153,164,23,42,109,80,22,43,108,81,226,223,152,165,20,41,110,83,224,221,154,167,225,220,155,166,21,40,111,82}, + {0,62,124,66,248,198,132,186,237,211,145,175,21,43,105,87,199,249,187,133,63,1,67,125,42,20,86,104,210,236,174,144,147,173,239,209,107,85,23,41,126,64,2,60,134,184,250,196,84,106,40,22,172,146,208,238,185,135,197,251,65,127,61,3,59,5,71,121,195,253,191,129,214,232,170,148,46,16,82,108,252,194,128,190,4,58,120,70,17,47,109,83,233,215,149,171,168,150,212,234,80,110,44,18,69,123,57,7,189,131,193,255,111,81,19,45,151,169,235,213,130,188,254,192,122,68,6,56,118,72,10,52,142,176,242,204,155,165,231,217,99,93,31,33,177,143,205,243,73,119,53,11,92,98,32,30,164,154,216,230,229,219,153,167,29,35,97,95,8,54,116,74,240,206,140,178,34,28,94,96,218,228,166,152,207,241,179,141,55,9,75,117,77,115,49,15,181,139,201,247,160,158,220,226,88,102,36,26,138,180,246,200,114,76,14,48,103,89,27,37,159,161,227,221,222,224,162,156,38,24,90,100,51,13,79,113,203,245,183,137,25,39,101,91,225,223,157,163,244,202,136,182,12,50,112,78}, + {0,63,126,65,252,195,130,189,229,218,155,164,25,38,103,88,215,232,169,150,43,20,85,106,50,13,76,115,206,241,176,143,179,140,205,242,79,112,49,14,86,105,40,23,170,149,212,235,100,91,26,37,152,167,230,217,129,190,255,192,125,66,3,60,123,68,5,58,135,184,249,198,158,161,224,223,98,93,28,35,172,147,210,237,80,111,46,17,73,118,55,8,181,138,203,244,200,247,182,137,52,11,74,117,45,18,83,108,209,238,175,144,31,32,97,94,227,220,157,162,250,197,132,187,6,57,120,71,246,201,136,183,10,53,116,75,19,44,109,82,239,208,145,174,33,30,95,96,221,226,163,156,196,251,186,133,56,7,70,121,69,122,59,4,185,134,199,248,160,159,222,225,92,99,34,29,146,173,236,211,110,81,16,47,119,72,9,54,139,180,245,202,141,178,243,204,113,78,15,48,104,87,22,41,148,171,234,213,90,101,36,27,166,153,216,231,191,128,193,254,67,124,61,2,62,1,64,127,194,253,188,131,219,228,165,154,39,24,89,102,233,214,151,168,21,42,107,84,12,51,114,77,240,207,142,177}, + {0,64,128,192,29,93,157,221,58,122,186,250,39,103,167,231,116,52,244,180,105,41,233,169,78,14,206,142,83,19,211,147,232,168,104,40,245,181,117,53,210,146,82,18,207,143,79,15,156,220,28,92,129,193,1,65,166,230,38,102,187,251,59,123,205,141,77,13,208,144,80,16,247,183,119,55,234,170,106,42,185,249,57,121,164,228,36,100,131,195,3,67,158,222,30,94,37,101,165,229,56,120,184,248,31,95,159,223,2,66,130,194,81,17,209,145,76,12,204,140,107,43,235,171,118,54,246,182,135,199,7,71,154,218,26,90,189,253,61,125,160,224,32,96,243,179,115,51,238,174,110,46,201,137,73,9,212,148,84,20,111,47,239,175,114,50,242,178,85,21,213,149,72,8,200,136,27,91,155,219,6,70,134,198,33,97,161,225,60,124,188,252,74,10,202,138,87,23,215,151,112,48,240,176,109,45,237,173,62,126,190,254,35,99,163,227,4,68,132,196,25,89,153,217,162,226,34,98,191,255,63,127,152,216,24,88,133,197,5,69,214,150,86,22,203,139,75,11,236,172,108,44,241,177,113,49}, + {0,65,130,195,25,88,155,218,50,115,176,241,43,106,169,232,100,37,230,167,125,60,255,190,86,23,212,149,79,14,205,140,200,137,74,11,209,144,83,18,250,187,120,57,227,162,97,32,172,237,46,111,181,244,55,118,158,223,28,93,135,198,5,68,141,204,15,78,148,213,22,87,191,254,61,124,166,231,36,101,233,168,107,42,240,177,114,51,219,154,89,24,194,131,64,1,69,4,199,134,92,29,222,159,119,54,245,180,110,47,236,173,33,96,163,226,56,121,186,251,19,82,145,208,10,75,136,201,7,70,133,196,30,95,156,221,53,116,183,246,44,109,174,239,99,34,225,160,122,59,248,185,81,16,211,146,72,9,202,139,207,142,77,12,214,151,84,21,253,188,127,62,228,165,102,39,171,234,41,104,178,243,48,113,153,216,27,90,128,193,2,67,138,203,8,73,147,210,17,80,184,249,58,123,161,224,35,98,238,175,108,45,247,182,117,52,220,157,94,31,197,132,71,6,66,3,192,129,91,26,217,152,112,49,242,179,105,40,235,170,38,103,164,229,63,126,189,252,20,85,150,215,13,76,143,206}, + {0,66,132,198,21,87,145,211,42,104,174,236,63,125,187,249,84,22,208,146,65,3,197,135,126,60,250,184,107,41,239,173,168,234,44,110,189,255,57,123,130,192,6,68,151,213,19,81,252,190,120,58,233,171,109,47,214,148,82,16,195,129,71,5,77,15,201,139,88,26,220,158,103,37,227,161,114,48,246,180,25,91,157,223,12,78,136,202,51,113,183,245,38,100,162,224,229,167,97,35,240,178,116,54,207,141,75,9,218,152,94,28,177,243,53,119,164,230,32,98,155,217,31,93,142,204,10,72,154,216,30,92,143,205,11,73,176,242,52,118,165,231,33,99,206,140,74,8,219,153,95,29,228,166,96,34,241,179,117,55,50,112,182,244,39,101,163,225,24,90,156,222,13,79,137,203,102,36,226,160,115,49,247,181,76,14,200,138,89,27,221,159,215,149,83,17,194,128,70,4,253,191,121,59,232,170,108,46,131,193,7,69,150,212,18,80,169,235,45,111,188,254,56,122,127,61,251,185,106,40,238,172,85,23,209,147,64,2,196,134,43,105,175,237,62,124,186,248,1,67,133,199,20,86,144,210}, + {0,67,134,197,17,82,151,212,34,97,164,231,51,112,181,246,68,7,194,129,85,22,211,144,102,37,224,163,119,52,241,178,136,203,14,77,153,218,31,92,170,233,44,111,187,248,61,126,204,143,74,9,221,158,91,24,238,173,104,43,255,188,121,58,13,78,139,200,28,95,154,217,47,108,169,234,62,125,184,251,73,10,207,140,88,27,222,157,107,40,237,174,122,57,252,191,133,198,3,64,148,215,18,81,167,228,33,98,182,245,48,115,193,130,71,4,208,147,86,21,227,160,101,38,242,177,116,55,26,89,156,223,11,72,141,206,56,123,190,253,41,106,175,236,94,29,216,155,79,12,201,138,124,63,250,185,109,46,235,168,146,209,20,87,131,192,5,70,176,243,54,117,161,226,39,100,214,149,80,19,199,132,65,2,244,183,114,49,229,166,99,32,23,84,145,210,6,69,128,195,53,118,179,240,36,103,162,225,83,16,213,150,66,1,196,135,113,50,247,180,96,35,230,165,159,220,25,90,142,205,8,75,189,254,59,120,172,239,42,105,219,152,93,30,202,137,76,15,249,186,127,60,232,171,110,45}, + {0,68,136,204,13,73,133,193,26,94,146,214,23,83,159,219,52,112,188,248,57,125,177,245,46,106,166,226,35,103,171,239,104,44,224,164,101,33,237,169,114,54,250,190,127,59,247,179,92,24,212,144,81,21,217,157,70,2,206,138,75,15,195,135,208,148,88,28,221,153,85,17,202,142,66,6,199,131,79,11,228,160,108,40,233,173,97,37,254,186,118,50,243,183,123,63,184,252,48,116,181,241,61,121,162,230,42,110,175,235,39,99,140,200,4,64,129,197,9,77,150,210,30,90,155,223,19,87,189,249,53,113,176,244,56,124,167,227,47,107,170,238,34,102,137,205,1,69,132,192,12,72,147,215,27,95,158,218,22,82,213,145,93,25,216,156,80,20,207,139,71,3,194,134,74,14,225,165,105,45,236,168,100,32,251,191,115,55,246,178,126,58,109,41,229,161,96,36,232,172,119,51,255,187,122,62,242,182,89,29,209,149,84,16,220,152,67,7,203,143,78,10,198,130,5,65,141,201,8,76,128,196,31,91,151,211,18,86,154,222,49,117,185,253,60,120,180,240,43,111,163,231,38,98,174,234}, + {0,69,138,207,9,76,131,198,18,87,152,221,27,94,145,212,36,97,174,235,45,104,167,226,54,115,188,249,63,122,181,240,72,13,194,135,65,4,203,142,90,31,208,149,83,22,217,156,108,41,230,163,101,32,239,170,126,59,244,177,119,50,253,184,144,213,26,95,153,220,19,86,130,199,8,77,139,206,1,68,180,241,62,123,189,248,55,114,166,227,44,105,175,234,37,96,216,157,82,23,209,148,91,30,202,143,64,5,195,134,73,12,252,185,118,51,245,176,127,58,238,171,100,33,231,162,109,40,61,120,183,242,52,113,190,251,47,106,165,224,38,99,172,233,25,92,147,214,16,85,154,223,11,78,129,196,2,71,136,205,117,48,255,186,124,57,246,179,103,34,237,168,110,43,228,161,81,20,219,158,88,29,210,151,67,6,201,140,74,15,192,133,173,232,39,98,164,225,46,107,191,250,53,112,182,243,60,121,137,204,3,70,128,197,10,79,155,222,17,84,146,215,24,93,229,160,111,42,236,169,102,35,247,178,125,56,254,187,116,49,193,132,75,14,200,141,66,7,211,150,89,28,218,159,80,21}, + {0,70,140,202,5,67,137,207,10,76,134,192,15,73,131,197,20,82,152,222,17,87,157,219,30,88,146,212,27,93,151,209,40,110,164,226,45,107,161,231,34,100,174,232,39,97,171,237,60,122,176,246,57,127,181,243,54,112,186,252,51,117,191,249,80,22,220,154,85,19,217,159,90,28,214,144,95,25,211,149,68,2,200,142,65,7,205,139,78,8,194,132,75,13,199,129,120,62,244,178,125,59,241,183,114,52,254,184,119,49,251,189,108,42,224,166,105,47,229,163,102,32,234,172,99,37,239,169,160,230,44,106,165,227,41,111,170,236,38,96,175,233,35,101,180,242,56,126,177,247,61,123,190,248,50,116,187,253,55,113,136,206,4,66,141,203,1,71,130,196,14,72,135,193,11,77,156,218,16,86,153,223,21,83,150,208,26,92,147,213,31,89,240,182,124,58,245,179,121,63,250,188,118,48,255,185,115,53,228,162,104,46,225,167,109,43,238,168,98,36,235,173,103,33,216,158,84,18,221,155,81,23,210,148,94,24,215,145,91,29,204,138,64,6,201,143,69,3,198,128,74,12,195,133,79,9}, + {0,71,142,201,1,70,143,200,2,69,140,203,3,68,141,202,4,67,138,205,5,66,139,204,6,65,136,207,7,64,137,206,8,79,134,193,9,78,135,192,10,77,132,195,11,76,133,194,12,75,130,197,13,74,131,196,14,73,128,199,15,72,129,198,16,87,158,217,17,86,159,216,18,85,156,219,19,84,157,218,20,83,154,221,21,82,155,220,22,81,152,223,23,80,153,222,24,95,150,209,25,94,151,208,26,93,148,211,27,92,149,210,28,91,146,213,29,90,147,212,30,89,144,215,31,88,145,214,32,103,174,233,33,102,175,232,34,101,172,235,35,100,173,234,36,99,170,237,37,98,171,236,38,97,168,239,39,96,169,238,40,111,166,225,41,110,167,224,42,109,164,227,43,108,165,226,44,107,162,229,45,106,163,228,46,105,160,231,47,104,161,230,48,119,190,249,49,118,191,248,50,117,188,251,51,116,189,250,52,115,186,253,53,114,187,252,54,113,184,255,55,112,185,254,56,127,182,241,57,126,183,240,58,125,180,243,59,124,181,242,60,123,178,245,61,122,179,244,62,121,176,247,63,120,177,246}, + {0,72,144,216,61,117,173,229,122,50,234,162,71,15,215,159,244,188,100,44,201,129,89,17,142,198,30,86,179,251,35,107,245,189,101,45,200,128,88,16,143,199,31,87,178,250,34,106,1,73,145,217,60,116,172,228,123,51,235,163,70,14,214,158,247,191,103,47,202,130,90,18,141,197,29,85,176,248,32,104,3,75,147,219,62,118,174,230,121,49,233,161,68,12,212,156,2,74,146,218,63,119,175,231,120,48,232,160,69,13,213,157,246,190,102,46,203,131,91,19,140,196,28,84,177,249,33,105,243,187,99,43,206,134,94,22,137,193,25,81,180,252,36,108,7,79,151,223,58,114,170,226,125,53,237,165,64,8,208,152,6,78,150,222,59,115,171,227,124,52,236,164,65,9,209,153,242,186,98,42,207,135,95,23,136,192,24,80,181,253,37,109,4,76,148,220,57,113,169,225,126,54,238,166,67,11,211,155,240,184,96,40,205,133,93,21,138,194,26,82,183,255,39,111,241,185,97,41,204,132,92,20,139,195,27,83,182,254,38,110,5,77,149,221,56,112,168,224,127,55,239,167,66,10,210,154}, + {0,73,146,219,57,112,171,226,114,59,224,169,75,2,217,144,228,173,118,63,221,148,79,6,150,223,4,77,175,230,61,116,213,156,71,14,236,165,126,55,167,238,53,124,158,215,12,69,49,120,163,234,8,65,154,211,67,10,209,152,122,51,232,161,183,254,37,108,142,199,28,85,197,140,87,30,252,181,110,39,83,26,193,136,106,35,248,177,33,104,179,250,24,81,138,195,98,43,240,185,91,18,201,128,16,89,130,203,41,96,187,242,134,207,20,93,191,246,45,100,244,189,102,47,205,132,95,22,115,58,225,168,74,3,216,145,1,72,147,218,56,113,170,227,151,222,5,76,174,231,60,117,229,172,119,62,220,149,78,7,166,239,52,125,159,214,13,68,212,157,70,15,237,164,127,54,66,11,208,153,123,50,233,160,48,121,162,235,9,64,155,210,196,141,86,31,253,180,111,38,182,255,36,109,143,198,29,84,32,105,178,251,25,80,139,194,82,27,192,137,107,34,249,176,17,88,131,202,40,97,186,243,99,42,241,184,90,19,200,129,245,188,103,46,204,133,94,23,135,206,21,92,190,247,44,101}, + {0,74,148,222,53,127,161,235,106,32,254,180,95,21,203,129,212,158,64,10,225,171,117,63,190,244,42,96,139,193,31,85,181,255,33,107,128,202,20,94,223,149,75,1,234,160,126,52,97,43,245,191,84,30,192,138,11,65,159,213,62,116,170,224,119,61,227,169,66,8,214,156,29,87,137,195,40,98,188,246,163,233,55,125,150,220,2,72,201,131,93,23,252,182,104,34,194,136,86,28,247,189,99,41,168,226,60,118,157,215,9,67,22,92,130,200,35,105,183,253,124,54,232,162,73,3,221,151,238,164,122,48,219,145,79,5,132,206,16,90,177,251,37,111,58,112,174,228,15,69,155,209,80,26,196,142,101,47,241,187,91,17,207,133,110,36,250,176,49,123,165,239,4,78,144,218,143,197,27,81,186,240,46,100,229,175,113,59,208,154,68,14,153,211,13,71,172,230,56,114,243,185,103,45,198,140,82,24,77,7,217,147,120,50,236,166,39,109,179,249,18,88,134,204,44,102,184,242,25,83,141,199,70,12,210,152,115,57,231,173,248,178,108,38,205,135,89,19,146,216,6,76,167,237,51,121}, + {0,75,150,221,49,122,167,236,98,41,244,191,83,24,197,142,196,143,82,25,245,190,99,40,166,237,48,123,151,220,1,74,149,222,3,72,164,239,50,121,247,188,97,42,198,141,80,27,81,26,199,140,96,43,246,189,51,120,165,238,2,73,148,223,55,124,161,234,6,77,144,219,85,30,195,136,100,47,242,185,243,184,101,46,194,137,84,31,145,218,7,76,160,235,54,125,162,233,52,127,147,216,5,78,192,139,86,29,241,186,103,44,102,45,240,187,87,28,193,138,4,79,146,217,53,126,163,232,110,37,248,179,95,20,201,130,12,71,154,209,61,118,171,224,170,225,60,119,155,208,13,70,200,131,94,21,249,178,111,36,251,176,109,38,202,129,92,23,153,210,15,68,168,227,62,117,63,116,169,226,14,69,152,211,93,22,203,128,108,39,250,177,89,18,207,132,104,35,254,181,59,112,173,230,10,65,156,215,157,214,11,64,172,231,58,113,255,180,105,34,206,133,88,19,204,135,90,17,253,182,107,32,174,229,56,115,159,212,9,66,8,67,158,213,57,114,175,228,106,33,252,183,91,16,205,134}, + {0,76,152,212,45,97,181,249,90,22,194,142,119,59,239,163,180,248,44,96,153,213,1,77,238,162,118,58,195,143,91,23,117,57,237,161,88,20,192,140,47,99,183,251,2,78,154,214,193,141,89,21,236,160,116,56,155,215,3,79,182,250,46,98,234,166,114,62,199,139,95,19,176,252,40,100,157,209,5,73,94,18,198,138,115,63,235,167,4,72,156,208,41,101,177,253,159,211,7,75,178,254,42,102,197,137,93,17,232,164,112,60,43,103,179,255,6,74,158,210,113,61,233,165,92,16,196,136,201,133,81,29,228,168,124,48,147,223,11,71,190,242,38,106,125,49,229,169,80,28,200,132,39,107,191,243,10,70,146,222,188,240,36,104,145,221,9,69,230,170,126,50,203,135,83,31,8,68,144,220,37,105,189,241,82,30,202,134,127,51,231,171,35,111,187,247,14,66,150,218,121,53,225,173,84,24,204,128,151,219,15,67,186,246,34,110,205,129,85,25,224,172,120,52,86,26,206,130,123,55,227,175,12,64,148,216,33,109,185,245,226,174,122,54,207,131,87,27,184,244,32,108,149,217,13,65}, + {0,77,154,215,41,100,179,254,82,31,200,133,123,54,225,172,164,233,62,115,141,192,23,90,246,187,108,33,223,146,69,8,85,24,207,130,124,49,230,171,7,74,157,208,46,99,180,249,241,188,107,38,216,149,66,15,163,238,57,116,138,199,16,93,170,231,48,125,131,206,25,84,248,181,98,47,209,156,75,6,14,67,148,217,39,106,189,240,92,17,198,139,117,56,239,162,255,178,101,40,214,155,76,1,173,224,55,122,132,201,30,83,91,22,193,140,114,63,232,165,9,68,147,222,32,109,186,247,73,4,211,158,96,45,250,183,27,86,129,204,50,127,168,229,237,160,119,58,196,137,94,19,191,242,37,104,150,219,12,65,28,81,134,203,53,120,175,226,78,3,212,153,103,42,253,176,184,245,34,111,145,220,11,70,234,167,112,61,195,142,89,20,227,174,121,52,202,135,80,29,177,252,43,102,152,213,2,79,71,10,221,144,110,35,244,185,21,88,143,194,60,113,166,235,182,251,44,97,159,210,5,72,228,169,126,51,205,128,87,26,18,95,136,197,59,118,161,236,64,13,218,151,105,36,243,190}, + {0,78,156,210,37,107,185,247,74,4,214,152,111,33,243,189,148,218,8,70,177,255,45,99,222,144,66,12,251,181,103,41,53,123,169,231,16,94,140,194,127,49,227,173,90,20,198,136,161,239,61,115,132,202,24,86,235,165,119,57,206,128,82,28,106,36,246,184,79,1,211,157,32,110,188,242,5,75,153,215,254,176,98,44,219,149,71,9,180,250,40,102,145,223,13,67,95,17,195,141,122,52,230,168,21,91,137,199,48,126,172,226,203,133,87,25,238,160,114,60,129,207,29,83,164,234,56,118,212,154,72,6,241,191,109,35,158,208,2,76,187,245,39,105,64,14,220,146,101,43,249,183,10,68,150,216,47,97,179,253,225,175,125,51,196,138,88,22,171,229,55,121,142,192,18,92,117,59,233,167,80,30,204,130,63,113,163,237,26,84,134,200,190,240,34,108,155,213,7,73,244,186,104,38,209,159,77,3,42,100,182,248,15,65,147,221,96,46,252,178,69,11,217,151,139,197,23,89,174,224,50,124,193,143,93,19,228,170,120,54,31,81,131,205,58,116,166,232,85,27,201,135,112,62,236,162}, + {0,79,158,209,33,110,191,240,66,13,220,147,99,44,253,178,132,203,26,85,165,234,59,116,198,137,88,23,231,168,121,54,21,90,139,196,52,123,170,229,87,24,201,134,118,57,232,167,145,222,15,64,176,255,46,97,211,156,77,2,242,189,108,35,42,101,180,251,11,68,149,218,104,39,246,185,73,6,215,152,174,225,48,127,143,192,17,94,236,163,114,61,205,130,83,28,63,112,161,238,30,81,128,207,125,50,227,172,92,19,194,141,187,244,37,106,154,213,4,75,249,182,103,40,216,151,70,9,84,27,202,133,117,58,235,164,22,89,136,199,55,120,169,230,208,159,78,1,241,190,111,32,146,221,12,67,179,252,45,98,65,14,223,144,96,47,254,177,3,76,157,210,34,109,188,243,197,138,91,20,228,171,122,53,135,200,25,86,166,233,56,119,126,49,224,175,95,16,193,142,60,115,162,237,29,82,131,204,250,181,100,43,219,148,69,10,184,247,38,105,153,214,7,72,107,36,245,186,74,5,212,155,41,102,183,248,8,71,150,217,239,160,113,62,206,129,80,31,173,226,51,124,140,195,18,93}, + {0,80,160,240,93,13,253,173,186,234,26,74,231,183,71,23,105,57,201,153,52,100,148,196,211,131,115,35,142,222,46,126,210,130,114,34,143,223,47,127,104,56,200,152,53,101,149,197,187,235,27,75,230,182,70,22,1,81,161,241,92,12,252,172,185,233,25,73,228,180,68,20,3,83,163,243,94,14,254,174,208,128,112,32,141,221,45,125,106,58,202,154,55,103,151,199,107,59,203,155,54,102,150,198,209,129,113,33,140,220,44,124,2,82,162,242,95,15,255,175,184,232,24,72,229,181,69,21,111,63,207,159,50,98,146,194,213,133,117,37,136,216,40,120,6,86,166,246,91,11,251,171,188,236,28,76,225,177,65,17,189,237,29,77,224,176,64,16,7,87,167,247,90,10,250,170,212,132,116,36,137,217,41,121,110,62,206,158,51,99,147,195,214,134,118,38,139,219,43,123,108,60,204,156,49,97,145,193,191,239,31,79,226,178,66,18,5,85,165,245,88,8,248,168,4,84,164,244,89,9,249,169,190,238,30,78,227,179,67,19,109,61,205,157,48,96,144,192,215,135,119,39,138,218,42,122}, + {0,81,162,243,89,8,251,170,178,227,16,65,235,186,73,24,121,40,219,138,32,113,130,211,203,154,105,56,146,195,48,97,242,163,80,1,171,250,9,88,64,17,226,179,25,72,187,234,139,218,41,120,210,131,112,33,57,104,155,202,96,49,194,147,249,168,91,10,160,241,2,83,75,26,233,184,18,67,176,225,128,209,34,115,217,136,123,42,50,99,144,193,107,58,201,152,11,90,169,248,82,3,240,161,185,232,27,74,224,177,66,19,114,35,208,129,43,122,137,216,192,145,98,51,153,200,59,106,239,190,77,28,182,231,20,69,93,12,255,174,4,85,166,247,150,199,52,101,207,158,109,60,36,117,134,215,125,44,223,142,29,76,191,238,68,21,230,183,175,254,13,92,246,167,84,5,100,53,198,151,61,108,159,206,214,135,116,37,143,222,45,124,22,71,180,229,79,30,237,188,164,245,6,87,253,172,95,14,111,62,205,156,54,103,148,197,221,140,127,46,132,213,38,119,228,181,70,23,189,236,31,78,86,7,244,165,15,94,173,252,157,204,63,110,196,149,102,55,47,126,141,220,118,39,212,133}, + {0,82,164,246,85,7,241,163,170,248,14,92,255,173,91,9,73,27,237,191,28,78,184,234,227,177,71,21,182,228,18,64,146,192,54,100,199,149,99,49,56,106,156,206,109,63,201,155,219,137,127,45,142,220,42,120,113,35,213,135,36,118,128,210,57,107,157,207,108,62,200,154,147,193,55,101,198,148,98,48,112,34,212,134,37,119,129,211,218,136,126,44,143,221,43,121,171,249,15,93,254,172,90,8,1,83,165,247,84,6,240,162,226,176,70,20,183,229,19,65,72,26,236,190,29,79,185,235,114,32,214,132,39,117,131,209,216,138,124,46,141,223,41,123,59,105,159,205,110,60,202,152,145,195,53,103,196,150,96,50,224,178,68,22,181,231,17,67,74,24,238,188,31,77,187,233,169,251,13,95,252,174,88,10,3,81,167,245,86,4,242,160,75,25,239,189,30,76,186,232,225,179,69,23,180,230,16,66,2,80,166,244,87,5,243,161,168,250,12,94,253,175,89,11,217,139,125,47,140,222,40,122,115,33,215,133,38,116,130,208,144,194,52,102,197,151,97,51,58,104,158,204,111,61,203,153}, + {0,83,166,245,81,2,247,164,162,241,4,87,243,160,85,6,89,10,255,172,8,91,174,253,251,168,93,14,170,249,12,95,178,225,20,71,227,176,69,22,16,67,182,229,65,18,231,180,235,184,77,30,186,233,28,79,73,26,239,188,24,75,190,237,121,42,223,140,40,123,142,221,219,136,125,46,138,217,44,127,32,115,134,213,113,34,215,132,130,209,36,119,211,128,117,38,203,152,109,62,154,201,60,111,105,58,207,156,56,107,158,205,146,193,52,103,195,144,101,54,48,99,150,197,97,50,199,148,242,161,84,7,163,240,5,86,80,3,246,165,1,82,167,244,171,248,13,94,250,169,92,15,9,90,175,252,88,11,254,173,64,19,230,181,17,66,183,228,226,177,68,23,179,224,21,70,25,74,191,236,72,27,238,189,187,232,29,78,234,185,76,31,139,216,45,126,218,137,124,47,41,122,143,220,120,43,222,141,210,129,116,39,131,208,37,118,112,35,214,133,33,114,135,212,57,106,159,204,104,59,206,157,155,200,61,110,202,153,108,63,96,51,198,149,49,98,151,196,194,145,100,55,147,192,53,102}, + {0,84,168,252,77,25,229,177,154,206,50,102,215,131,127,43,41,125,129,213,100,48,204,152,179,231,27,79,254,170,86,2,82,6,250,174,31,75,183,227,200,156,96,52,133,209,45,121,123,47,211,135,54,98,158,202,225,181,73,29,172,248,4,80,164,240,12,88,233,189,65,21,62,106,150,194,115,39,219,143,141,217,37,113,192,148,104,60,23,67,191,235,90,14,242,166,246,162,94,10,187,239,19,71,108,56,196,144,33,117,137,221,223,139,119,35,146,198,58,110,69,17,237,185,8,92,160,244,85,1,253,169,24,76,176,228,207,155,103,51,130,214,42,126,124,40,212,128,49,101,153,205,230,178,78,26,171,255,3,87,7,83,175,251,74,30,226,182,157,201,53,97,208,132,120,44,46,122,134,210,99,55,203,159,180,224,28,72,249,173,81,5,241,165,89,13,188,232,20,64,107,63,195,151,38,114,142,218,216,140,112,36,149,193,61,105,66,22,234,190,15,91,167,243,163,247,11,95,238,186,70,18,57,109,145,197,116,32,220,136,138,222,34,118,199,147,111,59,16,68,184,236,93,9,245,161}, + {0,85,170,255,73,28,227,182,146,199,56,109,219,142,113,36,57,108,147,198,112,37,218,143,171,254,1,84,226,183,72,29,114,39,216,141,59,110,145,196,224,181,74,31,169,252,3,86,75,30,225,180,2,87,168,253,217,140,115,38,144,197,58,111,228,177,78,27,173,248,7,82,118,35,220,137,63,106,149,192,221,136,119,34,148,193,62,107,79,26,229,176,6,83,172,249,150,195,60,105,223,138,117,32,4,81,174,251,77,24,231,178,175,250,5,80,230,179,76,25,61,104,151,194,116,33,222,139,213,128,127,42,156,201,54,99,71,18,237,184,14,91,164,241,236,185,70,19,165,240,15,90,126,43,212,129,55,98,157,200,167,242,13,88,238,187,68,17,53,96,159,202,124,41,214,131,158,203,52,97,215,130,125,40,12,89,166,243,69,16,239,186,49,100,155,206,120,45,210,135,163,246,9,92,234,191,64,21,8,93,162,247,65,20,235,190,154,207,48,101,211,134,121,44,67,22,233,188,10,95,160,245,209,132,123,46,152,205,50,103,122,47,208,133,51,102,153,204,232,189,66,23,161,244,11,94}, + {0,86,172,250,69,19,233,191,138,220,38,112,207,153,99,53,9,95,165,243,76,26,224,182,131,213,47,121,198,144,106,60,18,68,190,232,87,1,251,173,152,206,52,98,221,139,113,39,27,77,183,225,94,8,242,164,145,199,61,107,212,130,120,46,36,114,136,222,97,55,205,155,174,248,2,84,235,189,71,17,45,123,129,215,104,62,196,146,167,241,11,93,226,180,78,24,54,96,154,204,115,37,223,137,188,234,16,70,249,175,85,3,63,105,147,197,122,44,214,128,181,227,25,79,240,166,92,10,72,30,228,178,13,91,161,247,194,148,110,56,135,209,43,125,65,23,237,187,4,82,168,254,203,157,103,49,142,216,34,116,90,12,246,160,31,73,179,229,208,134,124,42,149,195,57,111,83,5,255,169,22,64,186,236,217,143,117,35,156,202,48,102,108,58,192,150,41,127,133,211,230,176,74,28,163,245,15,89,101,51,201,159,32,118,140,218,239,185,67,21,170,252,6,80,126,40,210,132,59,109,151,193,244,162,88,14,177,231,29,75,119,33,219,141,50,100,158,200,253,171,81,7,184,238,20,66}, + {0,87,174,249,65,22,239,184,130,213,44,123,195,148,109,58,25,78,183,224,88,15,246,161,155,204,53,98,218,141,116,35,50,101,156,203,115,36,221,138,176,231,30,73,241,166,95,8,43,124,133,210,106,61,196,147,169,254,7,80,232,191,70,17,100,51,202,157,37,114,139,220,230,177,72,31,167,240,9,94,125,42,211,132,60,107,146,197,255,168,81,6,190,233,16,71,86,1,248,175,23,64,185,238,212,131,122,45,149,194,59,108,79,24,225,182,14,89,160,247,205,154,99,52,140,219,34,117,200,159,102,49,137,222,39,112,74,29,228,179,11,92,165,242,209,134,127,40,144,199,62,105,83,4,253,170,18,69,188,235,250,173,84,3,187,236,21,66,120,47,214,129,57,110,151,192,227,180,77,26,162,245,12,91,97,54,207,152,32,119,142,217,172,251,2,85,237,186,67,20,46,121,128,215,111,56,193,150,181,226,27,76,244,163,90,13,55,96,153,206,118,33,216,143,158,201,48,103,223,136,113,38,28,75,178,229,93,10,243,164,135,208,41,126,198,145,104,63,5,82,171,252,68,19,234,189}, + {0,88,176,232,125,37,205,149,250,162,74,18,135,223,55,111,233,177,89,1,148,204,36,124,19,75,163,251,110,54,222,134,207,151,127,39,178,234,2,90,53,109,133,221,72,16,248,160,38,126,150,206,91,3,235,179,220,132,108,52,161,249,17,73,131,219,51,107,254,166,78,22,121,33,201,145,4,92,180,236,106,50,218,130,23,79,167,255,144,200,32,120,237,181,93,5,76,20,252,164,49,105,129,217,182,238,6,94,203,147,123,35,165,253,21,77,216,128,104,48,95,7,239,183,34,122,146,202,27,67,171,243,102,62,214,142,225,185,81,9,156,196,44,116,242,170,66,26,143,215,63,103,8,80,184,224,117,45,197,157,212,140,100,60,169,241,25,65,46,118,158,198,83,11,227,187,61,101,141,213,64,24,240,168,199,159,119,47,186,226,10,82,152,192,40,112,229,189,85,13,98,58,210,138,31,71,175,247,113,41,193,153,12,84,188,228,139,211,59,99,246,174,70,30,87,15,231,191,42,114,154,194,173,245,29,69,208,136,96,56,190,230,14,86,195,155,115,43,68,28,244,172,57,97,137,209}, + {0,89,178,235,121,32,203,146,242,171,64,25,139,210,57,96,249,160,75,18,128,217,50,107,11,82,185,224,114,43,192,153,239,182,93,4,150,207,36,125,29,68,175,246,100,61,214,143,22,79,164,253,111,54,221,132,228,189,86,15,157,196,47,118,195,154,113,40,186,227,8,81,49,104,131,218,72,17,250,163,58,99,136,209,67,26,241,168,200,145,122,35,177,232,3,90,44,117,158,199,85,12,231,190,222,135,108,53,167,254,21,76,213,140,103,62,172,245,30,71,39,126,149,204,94,7,236,181,155,194,41,112,226,187,80,9,105,48,219,130,16,73,162,251,98,59,208,137,27,66,169,240,144,201,34,123,233,176,91,2,116,45,198,159,13,84,191,230,134,223,52,109,255,166,77,20,141,212,63,102,244,173,70,31,127,38,205,148,6,95,180,237,88,1,234,179,33,120,147,202,170,243,24,65,211,138,97,56,161,248,19,74,216,129,106,51,83,10,225,184,42,115,152,193,183,238,5,92,206,151,124,37,69,28,247,174,60,101,142,215,78,23,252,165,55,110,133,220,188,229,14,87,197,156,119,46}, + {0,90,180,238,117,47,193,155,234,176,94,4,159,197,43,113,201,147,125,39,188,230,8,82,35,121,151,205,86,12,226,184,143,213,59,97,250,160,78,20,101,63,209,139,16,74,164,254,70,28,242,168,51,105,135,221,172,246,24,66,217,131,109,55,3,89,183,237,118,44,194,152,233,179,93,7,156,198,40,114,202,144,126,36,191,229,11,81,32,122,148,206,85,15,225,187,140,214,56,98,249,163,77,23,102,60,210,136,19,73,167,253,69,31,241,171,48,106,132,222,175,245,27,65,218,128,110,52,6,92,178,232,115,41,199,157,236,182,88,2,153,195,45,119,207,149,123,33,186,224,14,84,37,127,145,203,80,10,228,190,137,211,61,103,252,166,72,18,99,57,215,141,22,76,162,248,64,26,244,174,53,111,129,219,170,240,30,68,223,133,107,49,5,95,177,235,112,42,196,158,239,181,91,1,154,192,46,116,204,150,120,34,185,227,13,87,38,124,146,200,83,9,231,189,138,208,62,100,255,165,75,17,96,58,212,142,21,79,161,251,67,25,247,173,54,108,130,216,169,243,29,71,220,134,104,50}, + {0,91,182,237,113,42,199,156,226,185,84,15,147,200,37,126,217,130,111,52,168,243,30,69,59,96,141,214,74,17,252,167,175,244,25,66,222,133,104,51,77,22,251,160,60,103,138,209,118,45,192,155,7,92,177,234,148,207,34,121,229,190,83,8,67,24,245,174,50,105,132,223,161,250,23,76,208,139,102,61,154,193,44,119,235,176,93,6,120,35,206,149,9,82,191,228,236,183,90,1,157,198,43,112,14,85,184,227,127,36,201,146,53,110,131,216,68,31,242,169,215,140,97,58,166,253,16,75,134,221,48,107,247,172,65,26,100,63,210,137,21,78,163,248,95,4,233,178,46,117,152,195,189,230,11,80,204,151,122,33,41,114,159,196,88,3,238,181,203,144,125,38,186,225,12,87,240,171,70,29,129,218,55,108,18,73,164,255,99,56,213,142,197,158,115,40,180,239,2,89,39,124,145,202,86,13,224,187,28,71,170,241,109,54,219,128,254,165,72,19,143,212,57,98,106,49,220,135,27,64,173,246,136,211,62,101,249,162,79,20,179,232,5,94,194,153,116,47,81,10,231,188,32,123,150,205}, + {0,92,184,228,109,49,213,137,218,134,98,62,183,235,15,83,169,245,17,77,196,152,124,32,115,47,203,151,30,66,166,250,79,19,247,171,34,126,154,198,149,201,45,113,248,164,64,28,230,186,94,2,139,215,51,111,60,96,132,216,81,13,233,181,158,194,38,122,243,175,75,23,68,24,252,160,41,117,145,205,55,107,143,211,90,6,226,190,237,177,85,9,128,220,56,100,209,141,105,53,188,224,4,88,11,87,179,239,102,58,222,130,120,36,192,156,21,73,173,241,162,254,26,70,207,147,119,43,33,125,153,197,76,16,244,168,251,167,67,31,150,202,46,114,136,212,48,108,229,185,93,1,82,14,234,182,63,99,135,219,110,50,214,138,3,95,187,231,180,232,12,80,217,133,97,61,199,155,127,35,170,246,18,78,29,65,165,249,112,44,200,148,191,227,7,91,210,142,106,54,101,57,221,129,8,84,176,236,22,74,174,242,123,39,195,159,204,144,116,40,161,253,25,69,240,172,72,20,157,193,37,121,42,118,146,206,71,27,255,163,89,5,225,189,52,104,140,208,131,223,59,103,238,178,86,10}, + {0,93,186,231,105,52,211,142,210,143,104,53,187,230,1,92,185,228,3,94,208,141,106,55,107,54,209,140,2,95,184,229,111,50,213,136,6,91,188,225,189,224,7,90,212,137,110,51,214,139,108,49,191,226,5,88,4,89,190,227,109,48,215,138,222,131,100,57,183,234,13,80,12,81,182,235,101,56,223,130,103,58,221,128,14,83,180,233,181,232,15,82,220,129,102,59,177,236,11,86,216,133,98,63,99,62,217,132,10,87,176,237,8,85,178,239,97,60,219,134,218,135,96,61,179,238,9,84,161,252,27,70,200,149,114,47,115,46,201,148,26,71,160,253,24,69,162,255,113,44,203,150,202,151,112,45,163,254,25,68,206,147,116,41,167,250,29,64,28,65,166,251,117,40,207,146,119,42,205,144,30,67,164,249,165,248,31,66,204,145,118,43,127,34,197,152,22,75,172,241,173,240,23,74,196,153,126,35,198,155,124,33,175,242,21,72,20,73,174,243,125,32,199,154,16,77,170,247,121,36,195,158,194,159,120,37,171,246,17,76,169,244,19,78,192,157,122,39,123,38,193,156,18,79,168,245}, + {0,94,188,226,101,59,217,135,202,148,118,40,175,241,19,77,137,215,53,107,236,178,80,14,67,29,255,161,38,120,154,196,15,81,179,237,106,52,214,136,197,155,121,39,160,254,28,66,134,216,58,100,227,189,95,1,76,18,240,174,41,119,149,203,30,64,162,252,123,37,199,153,212,138,104,54,177,239,13,83,151,201,43,117,242,172,78,16,93,3,225,191,56,102,132,218,17,79,173,243,116,42,200,150,219,133,103,57,190,224,2,92,152,198,36,122,253,163,65,31,82,12,238,176,55,105,139,213,60,98,128,222,89,7,229,187,246,168,74,20,147,205,47,113,181,235,9,87,208,142,108,50,127,33,195,157,26,68,166,248,51,109,143,209,86,8,234,180,249,167,69,27,156,194,32,126,186,228,6,88,223,129,99,61,112,46,204,146,21,75,169,247,34,124,158,192,71,25,251,165,232,182,84,10,141,211,49,111,171,245,23,73,206,144,114,44,97,63,221,131,4,90,184,230,45,115,145,207,72,22,244,170,231,185,91,5,130,220,62,96,164,250,24,70,193,159,125,35,110,48,210,140,11,85,183,233}, + {0,95,190,225,97,62,223,128,194,157,124,35,163,252,29,66,153,198,39,120,248,167,70,25,91,4,229,186,58,101,132,219,47,112,145,206,78,17,240,175,237,178,83,12,140,211,50,109,182,233,8,87,215,136,105,54,116,43,202,149,21,74,171,244,94,1,224,191,63,96,129,222,156,195,34,125,253,162,67,28,199,152,121,38,166,249,24,71,5,90,187,228,100,59,218,133,113,46,207,144,16,79,174,241,179,236,13,82,210,141,108,51,232,183,86,9,137,214,55,104,42,117,148,203,75,20,245,170,188,227,2,93,221,130,99,60,126,33,192,159,31,64,161,254,37,122,155,196,68,27,250,165,231,184,89,6,134,217,56,103,147,204,45,114,242,173,76,19,81,14,239,176,48,111,142,209,10,85,180,235,107,52,213,138,200,151,118,41,169,246,23,72,226,189,92,3,131,220,61,98,32,127,158,193,65,30,255,160,123,36,197,154,26,69,164,251,185,230,7,88,216,135,102,57,205,146,115,44,172,243,18,77,15,80,177,238,110,49,208,143,84,11,234,181,53,106,139,212,150,201,40,119,247,168,73,22}, + {0,96,192,160,157,253,93,61,39,71,231,135,186,218,122,26,78,46,142,238,211,179,19,115,105,9,169,201,244,148,52,84,156,252,92,60,1,97,193,161,187,219,123,27,38,70,230,134,210,178,18,114,79,47,143,239,245,149,53,85,104,8,168,200,37,69,229,133,184,216,120,24,2,98,194,162,159,255,95,63,107,11,171,203,246,150,54,86,76,44,140,236,209,177,17,113,185,217,121,25,36,68,228,132,158,254,94,62,3,99,195,163,247,151,55,87,106,10,170,202,208,176,16,112,77,45,141,237,74,42,138,234,215,183,23,119,109,13,173,205,240,144,48,80,4,100,196,164,153,249,89,57,35,67,227,131,190,222,126,30,214,182,22,118,75,43,139,235,241,145,49,81,108,12,172,204,152,248,88,56,5,101,197,165,191,223,127,31,34,66,226,130,111,15,175,207,242,146,50,82,72,40,136,232,213,181,21,117,33,65,225,129,188,220,124,28,6,102,198,166,155,251,91,59,243,147,51,83,110,14,174,206,212,180,20,116,73,41,137,233,189,221,125,29,32,64,224,128,154,250,90,58,7,103,199,167}, + {0,97,194,163,153,248,91,58,47,78,237,140,182,215,116,21,94,63,156,253,199,166,5,100,113,16,179,210,232,137,42,75,188,221,126,31,37,68,231,134,147,242,81,48,10,107,200,169,226,131,32,65,123,26,185,216,205,172,15,110,84,53,150,247,101,4,167,198,252,157,62,95,74,43,136,233,211,178,17,112,59,90,249,152,162,195,96,1,20,117,214,183,141,236,79,46,217,184,27,122,64,33,130,227,246,151,52,85,111,14,173,204,135,230,69,36,30,127,220,189,168,201,106,11,49,80,243,146,202,171,8,105,83,50,145,240,229,132,39,70,124,29,190,223,148,245,86,55,13,108,207,174,187,218,121,24,34,67,224,129,118,23,180,213,239,142,45,76,89,56,155,250,192,161,2,99,40,73,234,139,177,208,115,18,7,102,197,164,158,255,92,61,175,206,109,12,54,87,244,149,128,225,66,35,25,120,219,186,241,144,51,82,104,9,170,203,222,191,28,125,71,38,133,228,19,114,209,176,138,235,72,41,60,93,254,159,165,196,103,6,77,44,143,238,212,181,22,119,98,3,160,193,251,154,57,88}, + {0,98,196,166,149,247,81,51,55,85,243,145,162,192,102,4,110,12,170,200,251,153,63,93,89,59,157,255,204,174,8,106,220,190,24,122,73,43,141,239,235,137,47,77,126,28,186,216,178,208,118,20,39,69,227,129,133,231,65,35,16,114,212,182,165,199,97,3,48,82,244,150,146,240,86,52,7,101,195,161,203,169,15,109,94,60,154,248,252,158,56,90,105,11,173,207,121,27,189,223,236,142,40,74,78,44,138,232,219,185,31,125,23,117,211,177,130,224,70,36,32,66,228,134,181,215,113,19,87,53,147,241,194,160,6,100,96,2,164,198,245,151,49,83,57,91,253,159,172,206,104,10,14,108,202,168,155,249,95,61,139,233,79,45,30,124,218,184,188,222,120,26,41,75,237,143,229,135,33,67,112,18,180,214,210,176,22,116,71,37,131,225,242,144,54,84,103,5,163,193,197,167,1,99,80,50,148,246,156,254,88,58,9,107,205,175,171,201,111,13,62,92,250,152,46,76,234,136,187,217,127,29,25,123,221,191,140,238,72,42,64,34,132,230,213,183,17,115,119,21,179,209,226,128,38,68}, + {0,99,198,165,145,242,87,52,63,92,249,154,174,205,104,11,126,29,184,219,239,140,41,74,65,34,135,228,208,179,22,117,252,159,58,89,109,14,171,200,195,160,5,102,82,49,148,247,130,225,68,39,19,112,213,182,189,222,123,24,44,79,234,137,229,134,35,64,116,23,178,209,218,185,28,127,75,40,141,238,155,248,93,62,10,105,204,175,164,199,98,1,53,86,243,144,25,122,223,188,136,235,78,45,38,69,224,131,183,212,113,18,103,4,161,194,246,149,48,83,88,59,158,253,201,170,15,108,215,180,17,114,70,37,128,227,232,139,46,77,121,26,191,220,169,202,111,12,56,91,254,157,150,245,80,51,7,100,193,162,43,72,237,142,186,217,124,31,20,119,210,177,133,230,67,32,85,54,147,240,196,167,2,97,106,9,172,207,251,152,61,94,50,81,244,151,163,192,101,6,13,110,203,168,156,255,90,57,76,47,138,233,221,190,27,120,115,16,181,214,226,129,36,71,206,173,8,107,95,60,153,250,241,146,55,84,96,3,166,197,176,211,118,21,33,66,231,132,143,236,73,42,30,125,216,187}, + {0,100,200,172,141,233,69,33,7,99,207,171,138,238,66,38,14,106,198,162,131,231,75,47,9,109,193,165,132,224,76,40,28,120,212,176,145,245,89,61,27,127,211,183,150,242,94,58,18,118,218,190,159,251,87,51,21,113,221,185,152,252,80,52,56,92,240,148,181,209,125,25,63,91,247,147,178,214,122,30,54,82,254,154,187,223,115,23,49,85,249,157,188,216,116,16,36,64,236,136,169,205,97,5,35,71,235,143,174,202,102,2,42,78,226,134,167,195,111,11,45,73,229,129,160,196,104,12,112,20,184,220,253,153,53,81,119,19,191,219,250,158,50,86,126,26,182,210,243,151,59,95,121,29,177,213,244,144,60,88,108,8,164,192,225,133,41,77,107,15,163,199,230,130,46,74,98,6,170,206,239,139,39,67,101,1,173,201,232,140,32,68,72,44,128,228,197,161,13,105,79,43,135,227,194,166,10,110,70,34,142,234,203,175,3,103,65,37,137,237,204,168,4,96,84,48,156,248,217,189,17,117,83,55,155,255,222,186,22,114,90,62,146,246,215,179,31,123,93,57,149,241,208,180,24,124}, + {0,101,202,175,137,236,67,38,15,106,197,160,134,227,76,41,30,123,212,177,151,242,93,56,17,116,219,190,152,253,82,55,60,89,246,147,181,208,127,26,51,86,249,156,186,223,112,21,34,71,232,141,171,206,97,4,45,72,231,130,164,193,110,11,120,29,178,215,241,148,59,94,119,18,189,216,254,155,52,81,102,3,172,201,239,138,37,64,105,12,163,198,224,133,42,79,68,33,142,235,205,168,7,98,75,46,129,228,194,167,8,109,90,63,144,245,211,182,25,124,85,48,159,250,220,185,22,115,240,149,58,95,121,28,179,214,255,154,53,80,118,19,188,217,238,139,36,65,103,2,173,200,225,132,43,78,104,13,162,199,204,169,6,99,69,32,143,234,195,166,9,108,74,47,128,229,210,183,24,125,91,62,145,244,221,184,23,114,84,49,158,251,136,237,66,39,1,100,203,174,135,226,77,40,14,107,196,161,150,243,92,57,31,122,213,176,153,252,83,54,16,117,218,191,180,209,126,27,61,88,247,146,187,222,113,20,50,87,248,157,170,207,96,5,35,70,233,140,165,192,111,10,44,73,230,131}, + {0,102,204,170,133,227,73,47,23,113,219,189,146,244,94,56,46,72,226,132,171,205,103,1,57,95,245,147,188,218,112,22,92,58,144,246,217,191,21,115,75,45,135,225,206,168,2,100,114,20,190,216,247,145,59,93,101,3,169,207,224,134,44,74,184,222,116,18,61,91,241,151,175,201,99,5,42,76,230,128,150,240,90,60,19,117,223,185,129,231,77,43,4,98,200,174,228,130,40,78,97,7,173,203,243,149,63,89,118,16,186,220,202,172,6,96,79,41,131,229,221,187,17,119,88,62,148,242,109,11,161,199,232,142,36,66,122,28,182,208,255,153,51,85,67,37,143,233,198,160,10,108,84,50,152,254,209,183,29,123,49,87,253,155,180,210,120,30,38,64,234,140,163,197,111,9,31,121,211,181,154,252,86,48,8,110,196,162,141,235,65,39,213,179,25,127,80,54,156,250,194,164,14,104,71,33,139,237,251,157,55,81,126,24,178,212,236,138,32,70,105,15,165,195,137,239,69,35,12,106,192,166,158,248,82,52,27,125,215,177,167,193,107,13,34,68,238,136,176,214,124,26,53,83,249,159}, + {0,103,206,169,129,230,79,40,31,120,209,182,158,249,80,55,62,89,240,151,191,216,113,22,33,70,239,136,160,199,110,9,124,27,178,213,253,154,51,84,99,4,173,202,226,133,44,75,66,37,140,235,195,164,13,106,93,58,147,244,220,187,18,117,248,159,54,81,121,30,183,208,231,128,41,78,102,1,168,207,198,161,8,111,71,32,137,238,217,190,23,112,88,63,150,241,132,227,74,45,5,98,203,172,155,252,85,50,26,125,212,179,186,221,116,19,59,92,245,146,165,194,107,12,36,67,234,141,237,138,35,68,108,11,162,197,242,149,60,91,115,20,189,218,211,180,29,122,82,53,156,251,204,171,2,101,77,42,131,228,145,246,95,56,16,119,222,185,142,233,64,39,15,104,193,166,175,200,97,6,46,73,224,135,176,215,126,25,49,86,255,152,21,114,219,188,148,243,90,61,10,109,196,163,139,236,69,34,43,76,229,130,170,205,100,3,52,83,250,157,181,210,123,28,105,14,167,192,232,143,38,65,118,17,184,223,247,144,57,94,87,48,153,254,214,177,24,127,72,47,134,225,201,174,7,96}, + {0,104,208,184,189,213,109,5,103,15,183,223,218,178,10,98,206,166,30,118,115,27,163,203,169,193,121,17,20,124,196,172,129,233,81,57,60,84,236,132,230,142,54,94,91,51,139,227,79,39,159,247,242,154,34,74,40,64,248,144,149,253,69,45,31,119,207,167,162,202,114,26,120,16,168,192,197,173,21,125,209,185,1,105,108,4,188,212,182,222,102,14,11,99,219,179,158,246,78,38,35,75,243,155,249,145,41,65,68,44,148,252,80,56,128,232,237,133,61,85,55,95,231,143,138,226,90,50,62,86,238,134,131,235,83,59,89,49,137,225,228,140,52,92,240,152,32,72,77,37,157,245,151,255,71,47,42,66,250,146,191,215,111,7,2,106,210,186,216,176,8,96,101,13,181,221,113,25,161,201,204,164,28,116,22,126,198,174,171,195,123,19,33,73,241,153,156,244,76,36,70,46,150,254,251,147,43,67,239,135,63,87,82,58,130,234,136,224,88,48,53,93,229,141,160,200,112,24,29,117,205,165,199,175,23,127,122,18,170,194,110,6,190,214,211,187,3,107,9,97,217,177,180,220,100,12}, + {0,105,210,187,185,208,107,2,111,6,189,212,214,191,4,109,222,183,12,101,103,14,181,220,177,216,99,10,8,97,218,179,161,200,115,26,24,113,202,163,206,167,28,117,119,30,165,204,127,22,173,196,198,175,20,125,16,121,194,171,169,192,123,18,95,54,141,228,230,143,52,93,48,89,226,139,137,224,91,50,129,232,83,58,56,81,234,131,238,135,60,85,87,62,133,236,254,151,44,69,71,46,149,252,145,248,67,42,40,65,250,147,32,73,242,155,153,240,75,34,79,38,157,244,246,159,36,77,190,215,108,5,7,110,213,188,209,184,3,106,104,1,186,211,96,9,178,219,217,176,11,98,15,102,221,180,182,223,100,13,31,118,205,164,166,207,116,29,112,25,162,203,201,160,27,114,193,168,19,122,120,17,170,195,174,199,124,21,23,126,197,172,225,136,51,90,88,49,138,227,142,231,92,53,55,94,229,140,63,86,237,132,134,239,84,61,80,57,130,235,233,128,59,82,64,41,146,251,249,144,43,66,47,70,253,148,150,255,68,45,158,247,76,37,39,78,245,156,241,152,35,74,72,33,154,243}, + {0,106,212,190,181,223,97,11,119,29,163,201,194,168,22,124,238,132,58,80,91,49,143,229,153,243,77,39,44,70,248,146,193,171,21,127,116,30,160,202,182,220,98,8,3,105,215,189,47,69,251,145,154,240,78,36,88,50,140,230,237,135,57,83,159,245,75,33,42,64,254,148,232,130,60,86,93,55,137,227,113,27,165,207,196,174,16,122,6,108,210,184,179,217,103,13,94,52,138,224,235,129,63,85,41,67,253,151,156,246,72,34,176,218,100,14,5,111,209,187,199,173,19,121,114,24,166,204,35,73,247,157,150,252,66,40,84,62,128,234,225,139,53,95,205,167,25,115,120,18,172,198,186,208,110,4,15,101,219,177,226,136,54,92,87,61,131,233,149,255,65,43,32,74,244,158,12,102,216,178,185,211,109,7,123,17,175,197,206,164,26,112,188,214,104,2,9,99,221,183,203,161,31,117,126,20,170,192,82,56,134,236,231,141,51,89,37,79,241,155,144,250,68,46,125,23,169,195,200,162,28,118,10,96,222,180,191,213,107,1,147,249,71,45,38,76,242,152,228,142,48,90,81,59,133,239}, + {0,107,214,189,177,218,103,12,127,20,169,194,206,165,24,115,254,149,40,67,79,36,153,242,129,234,87,60,48,91,230,141,225,138,55,92,80,59,134,237,158,245,72,35,47,68,249,146,31,116,201,162,174,197,120,19,96,11,182,221,209,186,7,108,223,180,9,98,110,5,184,211,160,203,118,29,17,122,199,172,33,74,247,156,144,251,70,45,94,53,136,227,239,132,57,82,62,85,232,131,143,228,89,50,65,42,151,252,240,155,38,77,192,171,22,125,113,26,167,204,191,212,105,2,14,101,216,179,163,200,117,30,18,121,196,175,220,183,10,97,109,6,187,208,93,54,139,224,236,135,58,81,34,73,244,159,147,248,69,46,66,41,148,255,243,152,37,78,61,86,235,128,140,231,90,49,188,215,106,1,13,102,219,176,195,168,21,126,114,25,164,207,124,23,170,193,205,166,27,112,3,104,213,190,178,217,100,15,130,233,84,63,51,88,229,142,253,150,43,64,76,39,154,241,157,246,75,32,44,71,250,145,226,137,52,95,83,56,133,238,99,8,181,222,210,185,4,111,28,119,202,161,173,198,123,16}, + {0,108,216,180,173,193,117,25,71,43,159,243,234,134,50,94,142,226,86,58,35,79,251,151,201,165,17,125,100,8,188,208,1,109,217,181,172,192,116,24,70,42,158,242,235,135,51,95,143,227,87,59,34,78,250,150,200,164,16,124,101,9,189,209,2,110,218,182,175,195,119,27,69,41,157,241,232,132,48,92,140,224,84,56,33,77,249,149,203,167,19,127,102,10,190,210,3,111,219,183,174,194,118,26,68,40,156,240,233,133,49,93,141,225,85,57,32,76,248,148,202,166,18,126,103,11,191,211,4,104,220,176,169,197,113,29,67,47,155,247,238,130,54,90,138,230,82,62,39,75,255,147,205,161,21,121,96,12,184,212,5,105,221,177,168,196,112,28,66,46,154,246,239,131,55,91,139,231,83,63,38,74,254,146,204,160,20,120,97,13,185,213,6,106,222,178,171,199,115,31,65,45,153,245,236,128,52,88,136,228,80,60,37,73,253,145,207,163,23,123,98,14,186,214,7,107,223,179,170,198,114,30,64,44,152,244,237,129,53,89,137,229,81,61,36,72,252,144,206,162,22,122,99,15,187,215}, + {0,109,218,183,169,196,115,30,79,34,149,248,230,139,60,81,158,243,68,41,55,90,237,128,209,188,11,102,120,21,162,207,33,76,251,150,136,229,82,63,110,3,180,217,199,170,29,112,191,210,101,8,22,123,204,161,240,157,42,71,89,52,131,238,66,47,152,245,235,134,49,92,13,96,215,186,164,201,126,19,220,177,6,107,117,24,175,194,147,254,73,36,58,87,224,141,99,14,185,212,202,167,16,125,44,65,246,155,133,232,95,50,253,144,39,74,84,57,142,227,178,223,104,5,27,118,193,172,132,233,94,51,45,64,247,154,203,166,17,124,98,15,184,213,26,119,192,173,179,222,105,4,85,56,143,226,252,145,38,75,165,200,127,18,12,97,214,187,234,135,48,93,67,46,153,244,59,86,225,140,146,255,72,37,116,25,174,195,221,176,7,106,198,171,28,113,111,2,181,216,137,228,83,62,32,77,250,151,88,53,130,239,241,156,43,70,23,122,205,160,190,211,100,9,231,138,61,80,78,35,148,249,168,197,114,31,1,108,219,182,121,20,163,206,208,189,10,103,54,91,236,129,159,242,69,40}, + {0,110,220,178,165,203,121,23,87,57,139,229,242,156,46,64,174,192,114,28,11,101,215,185,249,151,37,75,92,50,128,238,65,47,157,243,228,138,56,86,22,120,202,164,179,221,111,1,239,129,51,93,74,36,150,248,184,214,100,10,29,115,193,175,130,236,94,48,39,73,251,149,213,187,9,103,112,30,172,194,44,66,240,158,137,231,85,59,123,21,167,201,222,176,2,108,195,173,31,113,102,8,186,212,148,250,72,38,49,95,237,131,109,3,177,223,200,166,20,122,58,84,230,136,159,241,67,45,25,119,197,171,188,210,96,14,78,32,146,252,235,133,55,89,183,217,107,5,18,124,206,160,224,142,60,82,69,43,153,247,88,54,132,234,253,147,33,79,15,97,211,189,170,196,118,24,246,152,42,68,83,61,143,225,161,207,125,19,4,106,216,182,155,245,71,41,62,80,226,140,204,162,16,126,105,7,181,219,53,91,233,135,144,254,76,34,98,12,190,208,199,169,27,117,218,180,6,104,127,17,163,205,141,227,81,63,40,70,244,154,116,26,168,198,209,191,13,99,35,77,255,145,134,232,90,52}, + {0,111,222,177,161,206,127,16,95,48,129,238,254,145,32,79,190,209,96,15,31,112,193,174,225,142,63,80,64,47,158,241,97,14,191,208,192,175,30,113,62,81,224,143,159,240,65,46,223,176,1,110,126,17,160,207,128,239,94,49,33,78,255,144,194,173,28,115,99,12,189,210,157,242,67,44,60,83,226,141,124,19,162,205,221,178,3,108,35,76,253,146,130,237,92,51,163,204,125,18,2,109,220,179,252,147,34,77,93,50,131,236,29,114,195,172,188,211,98,13,66,45,156,243,227,140,61,82,153,246,71,40,56,87,230,137,198,169,24,119,103,8,185,214,39,72,249,150,134,233,88,55,120,23,166,201,217,182,7,104,248,151,38,73,89,54,135,232,167,200,121,22,6,105,216,183,70,41,152,247,231,136,57,86,25,118,199,168,184,215,102,9,91,52,133,234,250,149,36,75,4,107,218,181,165,202,123,20,229,138,59,84,68,43,154,245,186,213,100,11,27,116,197,170,58,85,228,139,155,244,69,42,101,10,187,212,196,171,26,117,132,235,90,53,37,74,251,148,219,180,5,106,122,21,164,203}, + {0,112,224,144,221,173,61,77,167,215,71,55,122,10,154,234,83,35,179,195,142,254,110,30,244,132,20,100,41,89,201,185,166,214,70,54,123,11,155,235,1,113,225,145,220,172,60,76,245,133,21,101,40,88,200,184,82,34,178,194,143,255,111,31,81,33,177,193,140,252,108,28,246,134,22,102,43,91,203,187,2,114,226,146,223,175,63,79,165,213,69,53,120,8,152,232,247,135,23,103,42,90,202,186,80,32,176,192,141,253,109,29,164,212,68,52,121,9,153,233,3,115,227,147,222,174,62,78,162,210,66,50,127,15,159,239,5,117,229,149,216,168,56,72,241,129,17,97,44,92,204,188,86,38,182,198,139,251,107,27,4,116,228,148,217,169,57,73,163,211,67,51,126,14,158,238,87,39,183,199,138,250,106,26,240,128,16,96,45,93,205,189,243,131,19,99,46,94,206,190,84,36,180,196,137,249,105,25,160,208,64,48,125,13,157,237,7,119,231,151,218,170,58,74,85,37,181,197,136,248,104,24,242,130,18,98,47,95,207,191,6,118,230,150,219,171,59,75,161,209,65,49,124,12,156,236}, + {0,113,226,147,217,168,59,74,175,222,77,60,118,7,148,229,67,50,161,208,154,235,120,9,236,157,14,127,53,68,215,166,134,247,100,21,95,46,189,204,41,88,203,186,240,129,18,99,197,180,39,86,28,109,254,143,106,27,136,249,179,194,81,32,17,96,243,130,200,185,42,91,190,207,92,45,103,22,133,244,82,35,176,193,139,250,105,24,253,140,31,110,36,85,198,183,151,230,117,4,78,63,172,221,56,73,218,171,225,144,3,114,212,165,54,71,13,124,239,158,123,10,153,232,162,211,64,49,34,83,192,177,251,138,25,104,141,252,111,30,84,37,182,199,97,16,131,242,184,201,90,43,206,191,44,93,23,102,245,132,164,213,70,55,125,12,159,238,11,122,233,152,210,163,48,65,231,150,5,116,62,79,220,173,72,57,170,219,145,224,115,2,51,66,209,160,234,155,8,121,156,237,126,15,69,52,167,214,112,1,146,227,169,216,75,58,223,174,61,76,6,119,228,149,181,196,87,38,108,29,142,255,26,107,248,137,195,178,33,80,246,135,20,101,47,94,205,188,89,40,187,202,128,241,98,19}, + {0,114,228,150,213,167,49,67,183,197,83,33,98,16,134,244,115,1,151,229,166,212,66,48,196,182,32,82,17,99,245,135,230,148,2,112,51,65,215,165,81,35,181,199,132,246,96,18,149,231,113,3,64,50,164,214,34,80,198,180,247,133,19,97,209,163,53,71,4,118,224,146,102,20,130,240,179,193,87,37,162,208,70,52,119,5,147,225,21,103,241,131,192,178,36,86,55,69,211,161,226,144,6,116,128,242,100,22,85,39,177,195,68,54,160,210,145,227,117,7,243,129,23,101,38,84,194,176,191,205,91,41,106,24,142,252,8,122,236,158,221,175,57,75,204,190,40,90,25,107,253,143,123,9,159,237,174,220,74,56,89,43,189,207,140,254,104,26,238,156,10,120,59,73,223,173,42,88,206,188,255,141,27,105,157,239,121,11,72,58,172,222,110,28,138,248,187,201,95,45,217,171,61,79,12,126,232,154,29,111,249,139,200,186,44,94,170,216,78,60,127,13,155,233,136,250,108,30,93,47,185,203,63,77,219,169,234,152,14,124,251,137,31,109,46,92,202,184,76,62,168,218,153,235,125,15}, + {0,115,230,149,209,162,55,68,191,204,89,42,110,29,136,251,99,16,133,246,178,193,84,39,220,175,58,73,13,126,235,152,198,181,32,83,23,100,241,130,121,10,159,236,168,219,78,61,165,214,67,48,116,7,146,225,26,105,252,143,203,184,45,94,145,226,119,4,64,51,166,213,46,93,200,187,255,140,25,106,242,129,20,103,35,80,197,182,77,62,171,216,156,239,122,9,87,36,177,194,134,245,96,19,232,155,14,125,57,74,223,172,52,71,210,161,229,150,3,112,139,248,109,30,90,41,188,207,63,76,217,170,238,157,8,123,128,243,102,21,81,34,183,196,92,47,186,201,141,254,107,24,227,144,5,118,50,65,212,167,249,138,31,108,40,91,206,189,70,53,160,211,151,228,113,2,154,233,124,15,75,56,173,222,37,86,195,176,244,135,18,97,174,221,72,59,127,12,153,234,17,98,247,132,192,179,38,85,205,190,43,88,28,111,250,137,114,1,148,231,163,208,69,54,104,27,142,253,185,202,95,44,215,164,49,66,6,117,224,147,11,120,237,158,218,169,60,79,180,199,82,33,101,22,131,240}, + {0,116,232,156,205,185,37,81,135,243,111,27,74,62,162,214,19,103,251,143,222,170,54,66,148,224,124,8,89,45,177,197,38,82,206,186,235,159,3,119,161,213,73,61,108,24,132,240,53,65,221,169,248,140,16,100,178,198,90,46,127,11,151,227,76,56,164,208,129,245,105,29,203,191,35,87,6,114,238,154,95,43,183,195,146,230,122,14,216,172,48,68,21,97,253,137,106,30,130,246,167,211,79,59,237,153,5,113,32,84,200,188,121,13,145,229,180,192,92,40,254,138,22,98,51,71,219,175,152,236,112,4,85,33,189,201,31,107,247,131,210,166,58,78,139,255,99,23,70,50,174,218,12,120,228,144,193,181,41,93,190,202,86,34,115,7,155,239,57,77,209,165,244,128,28,104,173,217,69,49,96,20,136,252,42,94,194,182,231,147,15,123,212,160,60,72,25,109,241,133,83,39,187,207,158,234,118,2,199,179,47,91,10,126,226,150,64,52,168,220,141,249,101,17,242,134,26,110,63,75,215,163,117,1,157,233,184,204,80,36,225,149,9,125,44,88,196,176,102,18,142,250,171,223,67,55}, + {0,117,234,159,201,188,35,86,143,250,101,16,70,51,172,217,3,118,233,156,202,191,32,85,140,249,102,19,69,48,175,218,6,115,236,153,207,186,37,80,137,252,99,22,64,53,170,223,5,112,239,154,204,185,38,83,138,255,96,21,67,54,169,220,12,121,230,147,197,176,47,90,131,246,105,28,74,63,160,213,15,122,229,144,198,179,44,89,128,245,106,31,73,60,163,214,10,127,224,149,195,182,41,92,133,240,111,26,76,57,166,211,9,124,227,150,192,181,42,95,134,243,108,25,79,58,165,208,24,109,242,135,209,164,59,78,151,226,125,8,94,43,180,193,27,110,241,132,210,167,56,77,148,225,126,11,93,40,183,194,30,107,244,129,215,162,61,72,145,228,123,14,88,45,178,199,29,104,247,130,212,161,62,75,146,231,120,13,91,46,177,196,20,97,254,139,221,168,55,66,155,238,113,4,82,39,184,205,23,98,253,136,222,171,52,65,152,237,114,7,81,36,187,206,18,103,248,141,219,174,49,68,157,232,119,2,84,33,190,203,17,100,251,142,216,173,50,71,158,235,116,1,87,34,189,200}, + {0,118,236,154,197,179,41,95,151,225,123,13,82,36,190,200,51,69,223,169,246,128,26,108,164,210,72,62,97,23,141,251,102,16,138,252,163,213,79,57,241,135,29,107,52,66,216,174,85,35,185,207,144,230,124,10,194,180,46,88,7,113,235,157,204,186,32,86,9,127,229,147,91,45,183,193,158,232,114,4,255,137,19,101,58,76,214,160,104,30,132,242,173,219,65,55,170,220,70,48,111,25,131,245,61,75,209,167,248,142,20,98,153,239,117,3,92,42,176,198,14,120,226,148,203,189,39,81,133,243,105,31,64,54,172,218,18,100,254,136,215,161,59,77,182,192,90,44,115,5,159,233,33,87,205,187,228,146,8,126,227,149,15,121,38,80,202,188,116,2,152,238,177,199,93,43,208,166,60,74,21,99,249,143,71,49,171,221,130,244,110,24,73,63,165,211,140,250,96,22,222,168,50,68,27,109,247,129,122,12,150,224,191,201,83,37,237,155,1,119,40,94,196,178,47,89,195,181,234,156,6,112,184,206,84,34,125,11,145,231,28,106,240,134,217,175,53,67,139,253,103,17,78,56,162,212}, + {0,119,238,153,193,182,47,88,159,232,113,6,94,41,176,199,35,84,205,186,226,149,12,123,188,203,82,37,125,10,147,228,70,49,168,223,135,240,105,30,217,174,55,64,24,111,246,129,101,18,139,252,164,211,74,61,250,141,20,99,59,76,213,162,140,251,98,21,77,58,163,212,19,100,253,138,210,165,60,75,175,216,65,54,110,25,128,247,48,71,222,169,241,134,31,104,202,189,36,83,11,124,229,146,85,34,187,204,148,227,122,13,233,158,7,112,40,95,198,177,118,1,152,239,183,192,89,46,5,114,235,156,196,179,42,93,154,237,116,3,91,44,181,194,38,81,200,191,231,144,9,126,185,206,87,32,120,15,150,225,67,52,173,218,130,245,108,27,220,171,50,69,29,106,243,132,96,23,142,249,161,214,79,56,255,136,17,102,62,73,208,167,137,254,103,16,72,63,166,209,22,97,248,143,215,160,57,78,170,221,68,51,107,28,133,242,53,66,219,172,244,131,26,109,207,184,33,86,14,121,224,151,80,39,190,201,145,230,127,8,236,155,2,117,45,90,195,180,115,4,157,234,178,197,92,43}, + {0,120,240,136,253,133,13,117,231,159,23,111,26,98,234,146,211,171,35,91,46,86,222,166,52,76,196,188,201,177,57,65,187,195,75,51,70,62,182,206,92,36,172,212,161,217,81,41,104,16,152,224,149,237,101,29,143,247,127,7,114,10,130,250,107,19,155,227,150,238,102,30,140,244,124,4,113,9,129,249,184,192,72,48,69,61,181,205,95,39,175,215,162,218,82,42,208,168,32,88,45,85,221,165,55,79,199,191,202,178,58,66,3,123,243,139,254,134,14,118,228,156,20,108,25,97,233,145,214,174,38,94,43,83,219,163,49,73,193,185,204,180,60,68,5,125,245,141,248,128,8,112,226,154,18,106,31,103,239,151,109,21,157,229,144,232,96,24,138,242,122,2,119,15,135,255,190,198,78,54,67,59,179,203,89,33,169,209,164,220,84,44,189,197,77,53,64,56,176,200,90,34,170,210,167,223,87,47,110,22,158,230,147,235,99,27,137,241,121,1,116,12,132,252,6,126,246,142,251,131,11,115,225,153,17,105,28,100,236,148,213,173,37,93,40,80,216,160,50,74,194,186,207,183,63,71}, + {0,121,242,139,249,128,11,114,239,150,29,100,22,111,228,157,195,186,49,72,58,67,200,177,44,85,222,167,213,172,39,94,155,226,105,16,98,27,144,233,116,13,134,255,141,244,127,6,88,33,170,211,161,216,83,42,183,206,69,60,78,55,188,197,43,82,217,160,210,171,32,89,196,189,54,79,61,68,207,182,232,145,26,99,17,104,227,154,7,126,245,140,254,135,12,117,176,201,66,59,73,48,187,194,95,38,173,212,166,223,84,45,115,10,129,248,138,243,120,1,156,229,110,23,101,28,151,238,86,47,164,221,175,214,93,36,185,192,75,50,64,57,178,203,149,236,103,30,108,21,158,231,122,3,136,241,131,250,113,8,205,180,63,70,52,77,198,191,34,91,208,169,219,162,41,80,14,119,252,133,247,142,5,124,225,152,19,106,24,97,234,147,125,4,143,246,132,253,118,15,146,235,96,25,107,18,153,224,190,199,76,53,71,62,181,204,81,40,163,218,168,209,90,35,230,159,20,109,31,102,237,148,9,112,251,130,240,137,2,123,37,92,215,174,220,165,46,87,202,179,56,65,51,74,193,184}, + {0,122,244,142,245,143,1,123,247,141,3,121,2,120,246,140,243,137,7,125,6,124,242,136,4,126,240,138,241,139,5,127,251,129,15,117,14,116,250,128,12,118,248,130,249,131,13,119,8,114,252,134,253,135,9,115,255,133,11,113,10,112,254,132,235,145,31,101,30,100,234,144,28,102,232,146,233,147,29,103,24,98,236,150,237,151,25,99,239,149,27,97,26,96,238,148,16,106,228,158,229,159,17,107,231,157,19,105,18,104,230,156,227,153,23,109,22,108,226,152,20,110,224,154,225,155,21,111,203,177,63,69,62,68,202,176,60,70,200,178,201,179,61,71,56,66,204,182,205,183,57,67,207,181,59,65,58,64,206,180,48,74,196,190,197,191,49,75,199,189,51,73,50,72,198,188,195,185,55,77,54,76,194,184,52,78,192,186,193,187,53,79,32,90,212,174,213,175,33,91,215,173,35,89,34,88,214,172,211,169,39,93,38,92,210,168,36,94,208,170,209,171,37,95,219,161,47,85,46,84,218,160,44,86,216,162,217,163,45,87,40,82,220,166,221,167,41,83,223,165,43,81,42,80,222,164}, + {0,123,246,141,241,138,7,124,255,132,9,114,14,117,248,131,227,152,21,110,18,105,228,159,28,103,234,145,237,150,27,96,219,160,45,86,42,81,220,167,36,95,210,169,213,174,35,88,56,67,206,181,201,178,63,68,199,188,49,74,54,77,192,187,171,208,93,38,90,33,172,215,84,47,162,217,165,222,83,40,72,51,190,197,185,194,79,52,183,204,65,58,70,61,176,203,112,11,134,253,129,250,119,12,143,244,121,2,126,5,136,243,147,232,101,30,98,25,148,239,108,23,154,225,157,230,107,16,75,48,189,198,186,193,76,55,180,207,66,57,69,62,179,200,168,211,94,37,89,34,175,212,87,44,161,218,166,221,80,43,144,235,102,29,97,26,151,236,111,20,153,226,158,229,104,19,115,8,133,254,130,249,116,15,140,247,122,1,125,6,139,240,224,155,22,109,17,106,231,156,31,100,233,146,238,149,24,99,3,120,245,142,242,137,4,127,252,135,10,113,13,118,251,128,59,64,205,182,202,177,60,71,196,191,50,73,53,78,195,184,216,163,46,85,41,82,223,164,39,92,209,170,214,173,32,91}, + {0,124,248,132,237,145,21,105,199,187,63,67,42,86,210,174,147,239,107,23,126,2,134,250,84,40,172,208,185,197,65,61,59,71,195,191,214,170,46,82,252,128,4,120,17,109,233,149,168,212,80,44,69,57,189,193,111,19,151,235,130,254,122,6,118,10,142,242,155,231,99,31,177,205,73,53,92,32,164,216,229,153,29,97,8,116,240,140,34,94,218,166,207,179,55,75,77,49,181,201,160,220,88,36,138,246,114,14,103,27,159,227,222,162,38,90,51,79,203,183,25,101,225,157,244,136,12,112,236,144,20,104,1,125,249,133,43,87,211,175,198,186,62,66,127,3,135,251,146,238,106,22,184,196,64,60,85,41,173,209,215,171,47,83,58,70,194,190,16,108,232,148,253,129,5,121,68,56,188,192,169,213,81,45,131,255,123,7,110,18,150,234,154,230,98,30,119,11,143,243,93,33,165,217,176,204,72,52,9,117,241,141,228,152,28,96,206,178,54,74,35,95,219,167,161,221,89,37,76,48,180,200,102,26,158,226,139,247,115,15,50,78,202,182,223,163,39,91,245,137,13,113,24,100,224,156}, + {0,125,250,135,233,148,19,110,207,178,53,72,38,91,220,161,131,254,121,4,106,23,144,237,76,49,182,203,165,216,95,34,27,102,225,156,242,143,8,117,212,169,46,83,61,64,199,186,152,229,98,31,113,12,139,246,87,42,173,208,190,195,68,57,54,75,204,177,223,162,37,88,249,132,3,126,16,109,234,151,181,200,79,50,92,33,166,219,122,7,128,253,147,238,105,20,45,80,215,170,196,185,62,67,226,159,24,101,11,118,241,140,174,211,84,41,71,58,189,192,97,28,155,230,136,245,114,15,108,17,150,235,133,248,127,2,163,222,89,36,74,55,176,205,239,146,21,104,6,123,252,129,32,93,218,167,201,180,51,78,119,10,141,240,158,227,100,25,184,197,66,63,81,44,171,214,244,137,14,115,29,96,231,154,59,70,193,188,210,175,40,85,90,39,160,221,179,206,73,52,149,232,111,18,124,1,134,251,217,164,35,94,48,77,202,183,22,107,236,145,255,130,5,120,65,60,187,198,168,213,82,47,142,243,116,9,103,26,157,224,194,191,56,69,43,86,209,172,13,112,247,138,228,153,30,99}, + {0,126,252,130,229,155,25,103,215,169,43,85,50,76,206,176,179,205,79,49,86,40,170,212,100,26,152,230,129,255,125,3,123,5,135,249,158,224,98,28,172,210,80,46,73,55,181,203,200,182,52,74,45,83,209,175,31,97,227,157,250,132,6,120,246,136,10,116,19,109,239,145,33,95,221,163,196,186,56,70,69,59,185,199,160,222,92,34,146,236,110,16,119,9,139,245,141,243,113,15,104,22,148,234,90,36,166,216,191,193,67,61,62,64,194,188,219,165,39,89,233,151,21,107,12,114,240,142,241,143,13,115,20,106,232,150,38,88,218,164,195,189,63,65,66,60,190,192,167,217,91,37,149,235,105,23,112,14,140,242,138,244,118,8,111,17,147,237,93,35,161,223,184,198,68,58,57,71,197,187,220,162,32,94,238,144,18,108,11,117,247,137,7,121,251,133,226,156,30,96,208,174,44,82,53,75,201,183,180,202,72,54,81,47,173,211,99,29,159,225,134,248,122,4,124,2,128,254,153,231,101,27,171,213,87,41,78,48,178,204,207,177,51,77,42,84,214,168,24,102,228,154,253,131,1,127}, + {0,127,254,129,225,158,31,96,223,160,33,94,62,65,192,191,163,220,93,34,66,61,188,195,124,3,130,253,157,226,99,28,91,36,165,218,186,197,68,59,132,251,122,5,101,26,155,228,248,135,6,121,25,102,231,152,39,88,217,166,198,185,56,71,182,201,72,55,87,40,169,214,105,22,151,232,136,247,118,9,21,106,235,148,244,139,10,117,202,181,52,75,43,84,213,170,237,146,19,108,12,115,242,141,50,77,204,179,211,172,45,82,78,49,176,207,175,208,81,46,145,238,111,16,112,15,142,241,113,14,143,240,144,239,110,17,174,209,80,47,79,48,177,206,210,173,44,83,51,76,205,178,13,114,243,140,236,147,18,109,42,85,212,171,203,180,53,74,245,138,11,116,20,107,234,149,137,246,119,8,104,23,150,233,86,41,168,215,183,200,73,54,199,184,57,70,38,89,216,167,24,103,230,153,249,134,7,120,100,27,154,229,133,250,123,4,187,196,69,58,90,37,164,219,156,227,98,29,125,2,131,252,67,60,189,194,162,221,92,35,63,64,193,190,222,161,32,95,224,159,30,97,1,126,255,128}, + {0,128,29,157,58,186,39,167,116,244,105,233,78,206,83,211,232,104,245,117,210,82,207,79,156,28,129,1,166,38,187,59,205,77,208,80,247,119,234,106,185,57,164,36,131,3,158,30,37,165,56,184,31,159,2,130,81,209,76,204,107,235,118,246,135,7,154,26,189,61,160,32,243,115,238,110,201,73,212,84,111,239,114,242,85,213,72,200,27,155,6,134,33,161,60,188,74,202,87,215,112,240,109,237,62,190,35,163,4,132,25,153,162,34,191,63,152,24,133,5,214,86,203,75,236,108,241,113,19,147,14,142,41,169,52,180,103,231,122,250,93,221,64,192,251,123,230,102,193,65,220,92,143,15,146,18,181,53,168,40,222,94,195,67,228,100,249,121,170,42,183,55,144,16,141,13,54,182,43,171,12,140,17,145,66,194,95,223,120,248,101,229,148,20,137,9,174,46,179,51,224,96,253,125,218,90,199,71,124,252,97,225,70,198,91,219,8,136,21,149,50,178,47,175,89,217,68,196,99,227,126,254,45,173,48,176,23,151,10,138,177,49,172,44,139,11,150,22,197,69,216,88,255,127,226,98}, + {0,129,31,158,62,191,33,160,124,253,99,226,66,195,93,220,248,121,231,102,198,71,217,88,132,5,155,26,186,59,165,36,237,108,242,115,211,82,204,77,145,16,142,15,175,46,176,49,21,148,10,139,43,170,52,181,105,232,118,247,87,214,72,201,199,70,216,89,249,120,230,103,187,58,164,37,133,4,154,27,63,190,32,161,1,128,30,159,67,194,92,221,125,252,98,227,42,171,53,180,20,149,11,138,86,215,73,200,104,233,119,246,210,83,205,76,236,109,243,114,174,47,177,48,144,17,143,14,147,18,140,13,173,44,178,51,239,110,240,113,209,80,206,79,107,234,116,245,85,212,74,203,23,150,8,137,41,168,54,183,126,255,97,224,64,193,95,222,2,131,29,156,60,189,35,162,134,7,153,24,184,57,167,38,250,123,229,100,196,69,219,90,84,213,75,202,106,235,117,244,40,169,55,182,22,151,9,136,172,45,179,50,146,19,141,12,208,81,207,78,238,111,241,112,185,56,166,39,135,6,152,25,197,68,218,91,251,122,228,101,65,192,94,223,127,254,96,225,61,188,34,163,3,130,28,157}, + {0,130,25,155,50,176,43,169,100,230,125,255,86,212,79,205,200,74,209,83,250,120,227,97,172,46,181,55,158,28,135,5,141,15,148,22,191,61,166,36,233,107,240,114,219,89,194,64,69,199,92,222,119,245,110,236,33,163,56,186,19,145,10,136,7,133,30,156,53,183,44,174,99,225,122,248,81,211,72,202,207,77,214,84,253,127,228,102,171,41,178,48,153,27,128,2,138,8,147,17,184,58,161,35,238,108,247,117,220,94,197,71,66,192,91,217,112,242,105,235,38,164,63,189,20,150,13,143,14,140,23,149,60,190,37,167,106,232,115,241,88,218,65,195,198,68,223,93,244,118,237,111,162,32,187,57,144,18,137,11,131,1,154,24,177,51,168,42,231,101,254,124,213,87,204,78,75,201,82,208,121,251,96,226,47,173,54,180,29,159,4,134,9,139,16,146,59,185,34,160,109,239,116,246,95,221,70,196,193,67,216,90,243,113,234,104,165,39,188,62,151,21,142,12,132,6,157,31,182,52,175,45,224,98,249,123,210,80,203,73,76,206,85,215,126,252,103,229,40,170,49,179,26,152,3,129}, + {0,131,27,152,54,181,45,174,108,239,119,244,90,217,65,194,216,91,195,64,238,109,245,118,180,55,175,44,130,1,153,26,173,46,182,53,155,24,128,3,193,66,218,89,247,116,236,111,117,246,110,237,67,192,88,219,25,154,2,129,47,172,52,183,71,196,92,223,113,242,106,233,43,168,48,179,29,158,6,133,159,28,132,7,169,42,178,49,243,112,232,107,197,70,222,93,234,105,241,114,220,95,199,68,134,5,157,30,176,51,171,40,50,177,41,170,4,135,31,156,94,221,69,198,104,235,115,240,142,13,149,22,184,59,163,32,226,97,249,122,212,87,207,76,86,213,77,206,96,227,123,248,58,185,33,162,12,143,23,148,35,160,56,187,21,150,14,141,79,204,84,215,121,250,98,225,251,120,224,99,205,78,214,85,151,20,140,15,161,34,186,57,201,74,210,81,255,124,228,103,165,38,190,61,147,16,136,11,17,146,10,137,39,164,60,191,125,254,102,229,75,200,80,211,100,231,127,252,82,209,73,202,8,139,19,144,62,189,37,166,188,63,167,36,138,9,145,18,208,83,203,72,230,101,253,126}, + {0,132,21,145,42,174,63,187,84,208,65,197,126,250,107,239,168,44,189,57,130,6,151,19,252,120,233,109,214,82,195,71,77,201,88,220,103,227,114,246,25,157,12,136,51,183,38,162,229,97,240,116,207,75,218,94,177,53,164,32,155,31,142,10,154,30,143,11,176,52,165,33,206,74,219,95,228,96,241,117,50,182,39,163,24,156,13,137,102,226,115,247,76,200,89,221,215,83,194,70,253,121,232,108,131,7,150,18,169,45,188,56,127,251,106,238,85,209,64,196,43,175,62,186,1,133,20,144,41,173,60,184,3,135,22,146,125,249,104,236,87,211,66,198,129,5,148,16,171,47,190,58,213,81,192,68,255,123,234,110,100,224,113,245,78,202,91,223,48,180,37,161,26,158,15,139,204,72,217,93,230,98,243,119,152,28,141,9,178,54,167,35,179,55,166,34,153,29,140,8,231,99,242,118,205,73,216,92,27,159,14,138,49,181,36,160,79,203,90,222,101,225,112,244,254,122,235,111,212,80,193,69,170,46,191,59,128,4,149,17,86,210,67,199,124,248,105,237,2,134,23,147,40,172,61,185}, + {0,133,23,146,46,171,57,188,92,217,75,206,114,247,101,224,184,61,175,42,150,19,129,4,228,97,243,118,202,79,221,88,109,232,122,255,67,198,84,209,49,180,38,163,31,154,8,141,213,80,194,71,251,126,236,105,137,12,158,27,167,34,176,53,218,95,205,72,244,113,227,102,134,3,145,20,168,45,191,58,98,231,117,240,76,201,91,222,62,187,41,172,16,149,7,130,183,50,160,37,153,28,142,11,235,110,252,121,197,64,210,87,15,138,24,157,33,164,54,179,83,214,68,193,125,248,106,239,169,44,190,59,135,2,144,21,245,112,226,103,219,94,204,73,17,148,6,131,63,186,40,173,77,200,90,223,99,230,116,241,196,65,211,86,234,111,253,120,152,29,143,10,182,51,161,36,124,249,107,238,82,215,69,192,32,165,55,178,14,139,25,156,115,246,100,225,93,216,74,207,47,170,56,189,1,132,22,147,203,78,220,89,229,96,242,119,151,18,128,5,185,60,174,43,30,155,9,140,48,181,39,162,66,199,85,208,108,233,123,254,166,35,177,52,136,13,159,26,250,127,237,104,212,81,195,70}, + {0,134,17,151,34,164,51,181,68,194,85,211,102,224,119,241,136,14,153,31,170,44,187,61,204,74,221,91,238,104,255,121,13,139,28,154,47,169,62,184,73,207,88,222,107,237,122,252,133,3,148,18,167,33,182,48,193,71,208,86,227,101,242,116,26,156,11,141,56,190,41,175,94,216,79,201,124,250,109,235,146,20,131,5,176,54,161,39,214,80,199,65,244,114,229,99,23,145,6,128,53,179,36,162,83,213,66,196,113,247,96,230,159,25,142,8,189,59,172,42,219,93,202,76,249,127,232,110,52,178,37,163,22,144,7,129,112,246,97,231,82,212,67,197,188,58,173,43,158,24,143,9,248,126,233,111,218,92,203,77,57,191,40,174,27,157,10,140,125,251,108,234,95,217,78,200,177,55,160,38,147,21,130,4,245,115,228,98,215,81,198,64,46,168,63,185,12,138,29,155,106,236,123,253,72,206,89,223,166,32,183,49,132,2,149,19,226,100,243,117,192,70,209,87,35,165,50,180,1,135,16,150,103,225,118,240,69,195,84,210,171,45,186,60,137,15,152,30,239,105,254,120,205,75,220,90}, + {0,135,19,148,38,161,53,178,76,203,95,216,106,237,121,254,152,31,139,12,190,57,173,42,212,83,199,64,242,117,225,102,45,170,62,185,11,140,24,159,97,230,114,245,71,192,84,211,181,50,166,33,147,20,128,7,249,126,234,109,223,88,204,75,90,221,73,206,124,251,111,232,22,145,5,130,48,183,35,164,194,69,209,86,228,99,247,112,142,9,157,26,168,47,187,60,119,240,100,227,81,214,66,197,59,188,40,175,29,154,14,137,239,104,252,123,201,78,218,93,163,36,176,55,133,2,150,17,180,51,167,32,146,21,129,6,248,127,235,108,222,89,205,74,44,171,63,184,10,141,25,158,96,231,115,244,70,193,85,210,153,30,138,13,191,56,172,43,213,82,198,65,243,116,224,103,1,134,18,149,39,160,52,179,77,202,94,217,107,236,120,255,238,105,253,122,200,79,219,92,162,37,177,54,132,3,151,16,118,241,101,226,80,215,67,196,58,189,41,174,28,155,15,136,195,68,208,87,229,98,246,113,143,8,156,27,169,46,186,61,91,220,72,207,125,250,110,233,23,144,4,131,49,182,34,165}, + {0,136,13,133,26,146,23,159,52,188,57,177,46,166,35,171,104,224,101,237,114,250,127,247,92,212,81,217,70,206,75,195,208,88,221,85,202,66,199,79,228,108,233,97,254,118,243,123,184,48,181,61,162,42,175,39,140,4,129,9,150,30,155,19,189,53,176,56,167,47,170,34,137,1,132,12,147,27,158,22,213,93,216,80,207,71,194,74,225,105,236,100,251,115,246,126,109,229,96,232,119,255,122,242,89,209,84,220,67,203,78,198,5,141,8,128,31,151,18,154,49,185,60,180,43,163,38,174,103,239,106,226,125,245,112,248,83,219,94,214,73,193,68,204,15,135,2,138,21,157,24,144,59,179,54,190,33,169,44,164,183,63,186,50,173,37,160,40,131,11,142,6,153,17,148,28,223,87,210,90,197,77,200,64,235,99,230,110,241,121,252,116,218,82,215,95,192,72,205,69,238,102,227,107,244,124,249,113,178,58,191,55,168,32,165,45,134,14,139,3,156,20,145,25,10,130,7,143,16,152,29,149,62,182,51,187,36,172,41,161,98,234,111,231,120,240,117,253,86,222,91,211,76,196,65,201}, + {0,137,15,134,30,151,17,152,60,181,51,186,34,171,45,164,120,241,119,254,102,239,105,224,68,205,75,194,90,211,85,220,240,121,255,118,238,103,225,104,204,69,195,74,210,91,221,84,136,1,135,14,150,31,153,16,180,61,187,50,170,35,165,44,253,116,242,123,227,106,236,101,193,72,206,71,223,86,208,89,133,12,138,3,155,18,148,29,185,48,182,63,167,46,168,33,13,132,2,139,19,154,28,149,49,184,62,183,47,166,32,169,117,252,122,243,107,226,100,237,73,192,70,207,87,222,88,209,231,110,232,97,249,112,246,127,219,82,212,93,197,76,202,67,159,22,144,25,129,8,142,7,163,42,172,37,189,52,178,59,23,158,24,145,9,128,6,143,43,162,36,173,53,188,58,179,111,230,96,233,113,248,126,247,83,218,92,213,77,196,66,203,26,147,21,156,4,141,11,130,38,175,41,160,56,177,55,190,98,235,109,228,124,245,115,250,94,215,81,216,64,201,79,198,234,99,229,108,244,125,251,114,214,95,217,80,200,65,199,78,146,27,157,20,140,5,131,10,174,39,161,40,176,57,191,54}, + {0,138,9,131,18,152,27,145,36,174,45,167,54,188,63,181,72,194,65,203,90,208,83,217,108,230,101,239,126,244,119,253,144,26,153,19,130,8,139,1,180,62,189,55,166,44,175,37,216,82,209,91,202,64,195,73,252,118,245,127,238,100,231,109,61,183,52,190,47,165,38,172,25,147,16,154,11,129,2,136,117,255,124,246,103,237,110,228,81,219,88,210,67,201,74,192,173,39,164,46,191,53,182,60,137,3,128,10,155,17,146,24,229,111,236,102,247,125,254,116,193,75,200,66,211,89,218,80,122,240,115,249,104,226,97,235,94,212,87,221,76,198,69,207,50,184,59,177,32,170,41,163,22,156,31,149,4,142,13,135,234,96,227,105,248,114,241,123,206,68,199,77,220,86,213,95,162,40,171,33,176,58,185,51,134,12,143,5,148,30,157,23,71,205,78,196,85,223,92,214,99,233,106,224,113,251,120,242,15,133,6,140,29,151,20,158,43,161,34,168,57,179,48,186,215,93,222,84,197,79,204,70,243,121,250,112,225,107,232,98,159,21,150,28,141,7,132,14,187,49,178,56,169,35,160,42}, + {0,139,11,128,22,157,29,150,44,167,39,172,58,177,49,186,88,211,83,216,78,197,69,206,116,255,127,244,98,233,105,226,176,59,187,48,166,45,173,38,156,23,151,28,138,1,129,10,232,99,227,104,254,117,245,126,196,79,207,68,210,89,217,82,125,246,118,253,107,224,96,235,81,218,90,209,71,204,76,199,37,174,46,165,51,184,56,179,9,130,2,137,31,148,20,159,205,70,198,77,219,80,208,91,225,106,234,97,247,124,252,119,149,30,158,21,131,8,136,3,185,50,178,57,175,36,164,47,250,113,241,122,236,103,231,108,214,93,221,86,192,75,203,64,162,41,169,34,180,63,191,52,142,5,133,14,152,19,147,24,74,193,65,202,92,215,87,220,102,237,109,230,112,251,123,240,18,153,25,146,4,143,15,132,62,181,53,190,40,163,35,168,135,12,140,7,145,26,154,17,171,32,160,43,189,54,182,61,223,84,212,95,201,66,194,73,243,120,248,115,229,110,238,101,55,188,60,183,33,170,42,161,27,144,16,155,13,134,6,141,111,228,100,239,121,242,114,249,67,200,72,195,85,222,94,213}, + {0,140,5,137,10,134,15,131,20,152,17,157,30,146,27,151,40,164,45,161,34,174,39,171,60,176,57,181,54,186,51,191,80,220,85,217,90,214,95,211,68,200,65,205,78,194,75,199,120,244,125,241,114,254,119,251,108,224,105,229,102,234,99,239,160,44,165,41,170,38,175,35,180,56,177,61,190,50,187,55,136,4,141,1,130,14,135,11,156,16,153,21,150,26,147,31,240,124,245,121,250,118,255,115,228,104,225,109,238,98,235,103,216,84,221,81,210,94,215,91,204,64,201,69,198,74,195,79,93,209,88,212,87,219,82,222,73,197,76,192,67,207,70,202,117,249,112,252,127,243,122,246,97,237,100,232,107,231,110,226,13,129,8,132,7,139,2,142,25,149,28,144,19,159,22,154,37,169,32,172,47,163,42,166,49,189,52,184,59,183,62,178,253,113,248,116,247,123,242,126,233,101,236,96,227,111,230,106,213,89,208,92,223,83,218,86,193,77,196,72,203,71,206,66,173,33,168,36,167,43,162,46,185,53,188,48,179,63,182,58,133,9,128,12,143,3,138,6,145,29,148,24,155,23,158,18}, + {0,141,7,138,14,131,9,132,28,145,27,150,18,159,21,152,56,181,63,178,54,187,49,188,36,169,35,174,42,167,45,160,112,253,119,250,126,243,121,244,108,225,107,230,98,239,101,232,72,197,79,194,70,203,65,204,84,217,83,222,90,215,93,208,224,109,231,106,238,99,233,100,252,113,251,118,242,127,245,120,216,85,223,82,214,91,209,92,196,73,195,78,202,71,205,64,144,29,151,26,158,19,153,20,140,1,139,6,130,15,133,8,168,37,175,34,166,43,161,44,180,57,179,62,186,55,189,48,221,80,218,87,211,94,212,89,193,76,198,75,207,66,200,69,229,104,226,111,235,102,236,97,249,116,254,115,247,122,240,125,173,32,170,39,163,46,164,41,177,60,182,59,191,50,184,53,149,24,146,31,155,22,156,17,137,4,142,3,135,10,128,13,61,176,58,183,51,190,52,185,33,172,38,171,47,162,40,165,5,136,2,143,11,134,12,129,25,148,30,147,23,154,16,157,77,192,74,199,67,206,68,201,81,220,86,219,95,210,88,213,117,248,114,255,123,246,124,241,105,228,110,227,103,234,96,237}, + {0,142,1,143,2,140,3,141,4,138,5,139,6,136,7,137,8,134,9,135,10,132,11,133,12,130,13,131,14,128,15,129,16,158,17,159,18,156,19,157,20,154,21,155,22,152,23,153,24,150,25,151,26,148,27,149,28,146,29,147,30,144,31,145,32,174,33,175,34,172,35,173,36,170,37,171,38,168,39,169,40,166,41,167,42,164,43,165,44,162,45,163,46,160,47,161,48,190,49,191,50,188,51,189,52,186,53,187,54,184,55,185,56,182,57,183,58,180,59,181,60,178,61,179,62,176,63,177,64,206,65,207,66,204,67,205,68,202,69,203,70,200,71,201,72,198,73,199,74,196,75,197,76,194,77,195,78,192,79,193,80,222,81,223,82,220,83,221,84,218,85,219,86,216,87,217,88,214,89,215,90,212,91,213,92,210,93,211,94,208,95,209,96,238,97,239,98,236,99,237,100,234,101,235,102,232,103,233,104,230,105,231,106,228,107,229,108,226,109,227,110,224,111,225,112,254,113,255,114,252,115,253,116,250,117,251,118,248,119,249,120,246,121,247,122,244,123,245,124,242,125,243,126,240,127,241}, + {0,143,3,140,6,137,5,138,12,131,15,128,10,133,9,134,24,151,27,148,30,145,29,146,20,155,23,152,18,157,17,158,48,191,51,188,54,185,53,186,60,179,63,176,58,181,57,182,40,167,43,164,46,161,45,162,36,171,39,168,34,173,33,174,96,239,99,236,102,233,101,234,108,227,111,224,106,229,105,230,120,247,123,244,126,241,125,242,116,251,119,248,114,253,113,254,80,223,83,220,86,217,85,218,92,211,95,208,90,213,89,214,72,199,75,196,78,193,77,194,68,203,71,200,66,205,65,206,192,79,195,76,198,73,197,74,204,67,207,64,202,69,201,70,216,87,219,84,222,81,221,82,212,91,215,88,210,93,209,94,240,127,243,124,246,121,245,122,252,115,255,112,250,117,249,118,232,103,235,100,238,97,237,98,228,107,231,104,226,109,225,110,160,47,163,44,166,41,165,42,172,35,175,32,170,37,169,38,184,55,187,52,190,49,189,50,180,59,183,56,178,61,177,62,144,31,147,28,150,25,149,26,156,19,159,16,154,21,153,22,136,7,139,4,142,1,141,2,132,11,135,8,130,13,129,14}, + {0,144,61,173,122,234,71,215,244,100,201,89,142,30,179,35,245,101,200,88,143,31,178,34,1,145,60,172,123,235,70,214,247,103,202,90,141,29,176,32,3,147,62,174,121,233,68,212,2,146,63,175,120,232,69,213,246,102,203,91,140,28,177,33,243,99,206,94,137,25,180,36,7,151,58,170,125,237,64,208,6,150,59,171,124,236,65,209,242,98,207,95,136,24,181,37,4,148,57,169,126,238,67,211,240,96,205,93,138,26,183,39,241,97,204,92,139,27,182,38,5,149,56,168,127,239,66,210,251,107,198,86,129,17,188,44,15,159,50,162,117,229,72,216,14,158,51,163,116,228,73,217,250,106,199,87,128,16,189,45,12,156,49,161,118,230,75,219,248,104,197,85,130,18,191,47,249,105,196,84,131,19,190,46,13,157,48,160,119,231,74,218,8,152,53,165,114,226,79,223,252,108,193,81,134,22,187,43,253,109,192,80,135,23,186,42,9,153,52,164,115,227,78,222,255,111,194,82,133,21,184,40,11,155,54,166,113,225,76,220,10,154,55,167,112,224,77,221,254,110,195,83,132,20,185,41}, + {0,145,63,174,126,239,65,208,252,109,195,82,130,19,189,44,229,116,218,75,155,10,164,53,25,136,38,183,103,246,88,201,215,70,232,121,169,56,150,7,43,186,20,133,85,196,106,251,50,163,13,156,76,221,115,226,206,95,241,96,176,33,143,30,179,34,140,29,205,92,242,99,79,222,112,225,49,160,14,159,86,199,105,248,40,185,23,134,170,59,149,4,212,69,235,122,100,245,91,202,26,139,37,180,152,9,167,54,230,119,217,72,129,16,190,47,255,110,192,81,125,236,66,211,3,146,60,173,123,234,68,213,5,148,58,171,135,22,184,41,249,104,198,87,158,15,161,48,224,113,223,78,98,243,93,204,28,141,35,178,172,61,147,2,210,67,237,124,80,193,111,254,46,191,17,128,73,216,118,231,55,166,8,153,181,36,138,27,203,90,244,101,200,89,247,102,182,39,137,24,52,165,11,154,74,219,117,228,45,188,18,131,83,194,108,253,209,64,238,127,175,62,144,1,31,142,32,177,97,240,94,207,227,114,220,77,157,12,162,51,250,107,197,84,132,21,187,42,6,151,57,168,120,233,71,214}, + {0,146,57,171,114,224,75,217,228,118,221,79,150,4,175,61,213,71,236,126,167,53,158,12,49,163,8,154,67,209,122,232,183,37,142,28,197,87,252,110,83,193,106,248,33,179,24,138,98,240,91,201,16,130,41,187,134,20,191,45,244,102,205,95,115,225,74,216,1,147,56,170,151,5,174,60,229,119,220,78,166,52,159,13,212,70,237,127,66,208,123,233,48,162,9,155,196,86,253,111,182,36,143,29,32,178,25,139,82,192,107,249,17,131,40,186,99,241,90,200,245,103,204,94,135,21,190,44,230,116,223,77,148,6,173,63,2,144,59,169,112,226,73,219,51,161,10,152,65,211,120,234,215,69,238,124,165,55,156,14,81,195,104,250,35,177,26,136,181,39,140,30,199,85,254,108,132,22,189,47,246,100,207,93,96,242,89,203,18,128,43,185,149,7,172,62,231,117,222,76,113,227,72,218,3,145,58,168,64,210,121,235,50,160,11,153,164,54,157,15,214,68,239,125,34,176,27,137,80,194,105,251,198,84,255,109,180,38,141,31,247,101,206,92,133,23,188,46,19,129,42,184,97,243,88,202}, + {0,147,59,168,118,229,77,222,236,127,215,68,154,9,161,50,197,86,254,109,179,32,136,27,41,186,18,129,95,204,100,247,151,4,172,63,225,114,218,73,123,232,64,211,13,158,54,165,82,193,105,250,36,183,31,140,190,45,133,22,200,91,243,96,51,160,8,155,69,214,126,237,223,76,228,119,169,58,146,1,246,101,205,94,128,19,187,40,26,137,33,178,108,255,87,196,164,55,159,12,210,65,233,122,72,219,115,224,62,173,5,150,97,242,90,201,23,132,44,191,141,30,182,37,251,104,192,83,102,245,93,206,16,131,43,184,138,25,177,34,252,111,199,84,163,48,152,11,213,70,238,125,79,220,116,231,57,170,2,145,241,98,202,89,135,20,188,47,29,142,38,181,107,248,80,195,52,167,15,156,66,209,121,234,216,75,227,112,174,61,149,6,85,198,110,253,35,176,24,139,185,42,130,17,207,92,244,103,144,3,171,56,230,117,221,78,124,239,71,212,10,153,49,162,194,81,249,106,180,39,143,28,46,189,21,134,88,203,99,240,7,148,60,175,113,226,74,217,235,120,208,67,157,14,166,53}, + {0,148,53,161,106,254,95,203,212,64,225,117,190,42,139,31,181,33,128,20,223,75,234,126,97,245,84,192,11,159,62,170,119,227,66,214,29,137,40,188,163,55,150,2,201,93,252,104,194,86,247,99,168,60,157,9,22,130,35,183,124,232,73,221,238,122,219,79,132,16,177,37,58,174,15,155,80,196,101,241,91,207,110,250,49,165,4,144,143,27,186,46,229,113,208,68,153,13,172,56,243,103,198,82,77,217,120,236,39,179,18,134,44,184,25,141,70,210,115,231,248,108,205,89,146,6,167,51,193,85,244,96,171,63,158,10,21,129,32,180,127,235,74,222,116,224,65,213,30,138,43,191,160,52,149,1,202,94,255,107,182,34,131,23,220,72,233,125,98,246,87,195,8,156,61,169,3,151,54,162,105,253,92,200,215,67,226,118,189,41,136,28,47,187,26,142,69,209,112,228,251,111,206,90,145,5,164,48,154,14,175,59,240,100,197,81,78,218,123,239,36,176,17,133,88,204,109,249,50,166,7,147,140,24,185,45,230,114,211,71,237,121,216,76,135,19,178,38,57,173,12,152,83,199,102,242}, + {0,149,55,162,110,251,89,204,220,73,235,126,178,39,133,16,165,48,146,7,203,94,252,105,121,236,78,219,23,130,32,181,87,194,96,245,57,172,14,155,139,30,188,41,229,112,210,71,242,103,197,80,156,9,171,62,46,187,25,140,64,213,119,226,174,59,153,12,192,85,247,98,114,231,69,208,28,137,43,190,11,158,60,169,101,240,82,199,215,66,224,117,185,44,142,27,249,108,206,91,151,2,160,53,37,176,18,135,75,222,124,233,92,201,107,254,50,167,5,144,128,21,183,34,238,123,217,76,65,212,118,227,47,186,24,141,157,8,170,63,243,102,196,81,228,113,211,70,138,31,189,40,56,173,15,154,86,195,97,244,22,131,33,180,120,237,79,218,202,95,253,104,164,49,147,6,179,38,132,17,221,72,234,127,111,250,88,205,1,148,54,163,239,122,216,77,129,20,182,35,51,166,4,145,93,200,106,255,74,223,125,232,36,177,19,134,150,3,161,52,248,109,207,90,184,45,143,26,214,67,225,116,100,241,83,198,10,159,61,168,29,136,42,191,115,230,68,209,193,84,246,99,175,58,152,13}, + {0,150,49,167,98,244,83,197,196,82,245,99,166,48,151,1,149,3,164,50,247,97,198,80,81,199,96,246,51,165,2,148,55,161,6,144,85,195,100,242,243,101,194,84,145,7,160,54,162,52,147,5,192,86,241,103,102,240,87,193,4,146,53,163,110,248,95,201,12,154,61,171,170,60,155,13,200,94,249,111,251,109,202,92,153,15,168,62,63,169,14,152,93,203,108,250,89,207,104,254,59,173,10,156,157,11,172,58,255,105,206,88,204,90,253,107,174,56,159,9,8,158,57,175,106,252,91,205,220,74,237,123,190,40,143,25,24,142,41,191,122,236,75,221,73,223,120,238,43,189,26,140,141,27,188,42,239,121,222,72,235,125,218,76,137,31,184,46,47,185,30,136,77,219,124,234,126,232,79,217,28,138,45,187,186,44,139,29,216,78,233,127,178,36,131,21,208,70,225,119,118,224,71,209,20,130,37,179,39,177,22,128,69,211,116,226,227,117,210,68,129,23,176,38,133,19,180,34,231,113,214,64,65,215,112,230,35,181,18,132,16,134,33,183,114,228,67,213,212,66,229,115,182,32,135,17}, + {0,151,51,164,102,241,85,194,204,91,255,104,170,61,153,14,133,18,182,33,227,116,208,71,73,222,122,237,47,184,28,139,23,128,36,179,113,230,66,213,219,76,232,127,189,42,142,25,146,5,161,54,244,99,199,80,94,201,109,250,56,175,11,156,46,185,29,138,72,223,123,236,226,117,209,70,132,19,183,32,171,60,152,15,205,90,254,105,103,240,84,195,1,150,50,165,57,174,10,157,95,200,108,251,245,98,198,81,147,4,160,55,188,43,143,24,218,77,233,126,112,231,67,212,22,129,37,178,92,203,111,248,58,173,9,158,144,7,163,52,246,97,197,82,217,78,234,125,191,40,140,27,21,130,38,177,115,228,64,215,75,220,120,239,45,186,30,137,135,16,180,35,225,118,210,69,206,89,253,106,168,63,155,12,2,149,49,166,100,243,87,192,114,229,65,214,20,131,39,176,190,41,141,26,216,79,235,124,247,96,196,83,145,6,162,53,59,172,8,159,93,202,110,249,101,242,86,193,3,148,48,167,169,62,154,13,207,88,252,107,224,119,211,68,134,17,181,34,44,187,31,136,74,221,121,238}, + {0,152,45,181,90,194,119,239,180,44,153,1,238,118,195,91,117,237,88,192,47,183,2,154,193,89,236,116,155,3,182,46,234,114,199,95,176,40,157,5,94,198,115,235,4,156,41,177,159,7,178,42,197,93,232,112,43,179,6,158,113,233,92,196,201,81,228,124,147,11,190,38,125,229,80,200,39,191,10,146,188,36,145,9,230,126,203,83,8,144,37,189,82,202,127,231,35,187,14,150,121,225,84,204,151,15,186,34,205,85,224,120,86,206,123,227,12,148,33,185,226,122,207,87,184,32,149,13,143,23,162,58,213,77,248,96,59,163,22,142,97,249,76,212,250,98,215,79,160,56,141,21,78,214,99,251,20,140,57,161,101,253,72,208,63,167,18,138,209,73,252,100,139,19,166,62,16,136,61,165,74,210,103,255,164,60,137,17,254,102,211,75,70,222,107,243,28,132,49,169,242,106,223,71,168,48,133,29,51,171,30,134,105,241,68,220,135,31,170,50,221,69,240,104,172,52,129,25,246,110,219,67,24,128,53,173,66,218,111,247,217,65,244,108,131,27,174,54,109,245,64,216,55,175,26,130}, + {0,153,47,182,94,199,113,232,188,37,147,10,226,123,205,84,101,252,74,211,59,162,20,141,217,64,246,111,135,30,168,49,202,83,229,124,148,13,187,34,118,239,89,192,40,177,7,158,175,54,128,25,241,104,222,71,19,138,60,165,77,212,98,251,137,16,166,63,215,78,248,97,53,172,26,131,107,242,68,221,236,117,195,90,178,43,157,4,80,201,127,230,14,151,33,184,67,218,108,245,29,132,50,171,255,102,208,73,161,56,142,23,38,191,9,144,120,225,87,206,154,3,181,44,196,93,235,114,15,150,32,185,81,200,126,231,179,42,156,5,237,116,194,91,106,243,69,220,52,173,27,130,214,79,249,96,136,17,167,62,197,92,234,115,155,2,180,45,121,224,86,207,39,190,8,145,160,57,143,22,254,103,209,72,28,133,51,170,66,219,109,244,134,31,169,48,216,65,247,110,58,163,21,140,100,253,75,210,227,122,204,85,189,36,146,11,95,198,112,233,1,152,46,183,76,213,99,250,18,139,61,164,240,105,223,70,174,55,129,24,41,176,6,159,119,238,88,193,149,12,186,35,203,82,228,125}, + {0,154,41,179,82,200,123,225,164,62,141,23,246,108,223,69,85,207,124,230,7,157,46,180,241,107,216,66,163,57,138,16,170,48,131,25,248,98,209,75,14,148,39,189,92,198,117,239,255,101,214,76,173,55,132,30,91,193,114,232,9,147,32,186,73,211,96,250,27,129,50,168,237,119,196,94,191,37,150,12,28,134,53,175,78,212,103,253,184,34,145,11,234,112,195,89,227,121,202,80,177,43,152,2,71,221,110,244,21,143,60,166,182,44,159,5,228,126,205,87,18,136,59,161,64,218,105,243,146,8,187,33,192,90,233,115,54,172,31,133,100,254,77,215,199,93,238,116,149,15,188,38,99,249,74,208,49,171,24,130,56,162,17,139,106,240,67,217,156,6,181,47,206,84,231,125,109,247,68,222,63,165,22,140,201,83,224,122,155,1,178,40,219,65,242,104,137,19,160,58,127,229,86,204,45,183,4,158,142,20,167,61,220,70,245,111,42,176,3,153,120,226,81,203,113,235,88,194,35,185,10,144,213,79,252,102,135,29,174,52,36,190,13,151,118,236,95,197,128,26,169,51,210,72,251,97}, + {0,155,43,176,86,205,125,230,172,55,135,28,250,97,209,74,69,222,110,245,19,136,56,163,233,114,194,89,191,36,148,15,138,17,161,58,220,71,247,108,38,189,13,150,112,235,91,192,207,84,228,127,153,2,178,41,99,248,72,211,53,174,30,133,9,146,34,185,95,196,116,239,165,62,142,21,243,104,216,67,76,215,103,252,26,129,49,170,224,123,203,80,182,45,157,6,131,24,168,51,213,78,254,101,47,180,4,159,121,226,82,201,198,93,237,118,144,11,187,32,106,241,65,218,60,167,23,140,18,137,57,162,68,223,111,244,190,37,149,14,232,115,195,88,87,204,124,231,1,154,42,177,251,96,208,75,173,54,134,29,152,3,179,40,206,85,229,126,52,175,31,132,98,249,73,210,221,70,246,109,139,16,160,59,113,234,90,193,39,188,12,151,27,128,48,171,77,214,102,253,183,44,156,7,225,122,202,81,94,197,117,238,8,147,35,184,242,105,217,66,164,63,143,20,145,10,186,33,199,92,236,119,61,166,22,141,107,240,64,219,212,79,255,100,130,25,169,50,120,227,83,200,46,181,5,158}, + {0,156,37,185,74,214,111,243,148,8,177,45,222,66,251,103,53,169,16,140,127,227,90,198,161,61,132,24,235,119,206,82,106,246,79,211,32,188,5,153,254,98,219,71,180,40,145,13,95,195,122,230,21,137,48,172,203,87,238,114,129,29,164,56,212,72,241,109,158,2,187,39,64,220,101,249,10,150,47,179,225,125,196,88,171,55,142,18,117,233,80,204,63,163,26,134,190,34,155,7,244,104,209,77,42,182,15,147,96,252,69,217,139,23,174,50,193,93,228,120,31,131,58,166,85,201,112,236,181,41,144,12,255,99,218,70,33,189,4,152,107,247,78,210,128,28,165,57,202,86,239,115,20,136,49,173,94,194,123,231,223,67,250,102,149,9,176,44,75,215,110,242,1,157,36,184,234,118,207,83,160,60,133,25,126,226,91,199,52,168,17,141,97,253,68,216,43,183,14,146,245,105,208,76,191,35,154,6,84,200,113,237,30,130,59,167,192,92,229,121,138,22,175,51,11,151,46,178,65,221,100,248,159,3,186,38,213,73,240,108,62,162,27,135,116,232,81,205,170,54,143,19,224,124,197,89}, + {0,157,39,186,78,211,105,244,156,1,187,38,210,79,245,104,37,184,2,159,107,246,76,209,185,36,158,3,247,106,208,77,74,215,109,240,4,153,35,190,214,75,241,108,152,5,191,34,111,242,72,213,33,188,6,155,243,110,212,73,189,32,154,7,148,9,179,46,218,71,253,96,8,149,47,178,70,219,97,252,177,44,150,11,255,98,216,69,45,176,10,151,99,254,68,217,222,67,249,100,144,13,183,42,66,223,101,248,12,145,43,182,251,102,220,65,181,40,146,15,103,250,64,221,41,180,14,147,53,168,18,143,123,230,92,193,169,52,142,19,231,122,192,93,16,141,55,170,94,195,121,228,140,17,171,54,194,95,229,120,127,226,88,197,49,172,22,139,227,126,196,89,173,48,138,23,90,199,125,224,20,137,51,174,198,91,225,124,136,21,175,50,161,60,134,27,239,114,200,85,61,160,26,135,115,238,84,201,132,25,163,62,202,87,237,112,24,133,63,162,86,203,113,236,235,118,204,81,165,56,130,31,119,234,80,205,57,164,30,131,206,83,233,116,128,29,167,58,82,207,117,232,28,129,59,166}, + {0,158,33,191,66,220,99,253,132,26,165,59,198,88,231,121,21,139,52,170,87,201,118,232,145,15,176,46,211,77,242,108,42,180,11,149,104,246,73,215,174,48,143,17,236,114,205,83,63,161,30,128,125,227,92,194,187,37,154,4,249,103,216,70,84,202,117,235,22,136,55,169,208,78,241,111,146,12,179,45,65,223,96,254,3,157,34,188,197,91,228,122,135,25,166,56,126,224,95,193,60,162,29,131,250,100,219,69,184,38,153,7,107,245,74,212,41,183,8,150,239,113,206,80,173,51,140,18,168,54,137,23,234,116,203,85,44,178,13,147,110,240,79,209,189,35,156,2,255,97,222,64,57,167,24,134,123,229,90,196,130,28,163,61,192,94,225,127,6,152,39,185,68,218,101,251,151,9,182,40,213,75,244,106,19,141,50,172,81,207,112,238,252,98,221,67,190,32,159,1,120,230,89,199,58,164,27,133,233,119,200,86,171,53,138,20,109,243,76,210,47,177,14,144,214,72,247,105,148,10,181,43,82,204,115,237,16,142,49,175,195,93,226,124,129,31,160,62,71,217,102,248,5,155,36,186}, + {0,159,35,188,70,217,101,250,140,19,175,48,202,85,233,118,5,154,38,185,67,220,96,255,137,22,170,53,207,80,236,115,10,149,41,182,76,211,111,240,134,25,165,58,192,95,227,124,15,144,44,179,73,214,106,245,131,28,160,63,197,90,230,121,20,139,55,168,82,205,113,238,152,7,187,36,222,65,253,98,17,142,50,173,87,200,116,235,157,2,190,33,219,68,248,103,30,129,61,162,88,199,123,228,146,13,177,46,212,75,247,104,27,132,56,167,93,194,126,225,151,8,180,43,209,78,242,109,40,183,11,148,110,241,77,210,164,59,135,24,226,125,193,94,45,178,14,145,107,244,72,215,161,62,130,29,231,120,196,91,34,189,1,158,100,251,71,216,174,49,141,18,232,119,203,84,39,184,4,155,97,254,66,221,171,52,136,23,237,114,206,81,60,163,31,128,122,229,89,198,176,47,147,12,246,105,213,74,57,166,26,133,127,224,92,195,181,42,150,9,243,108,208,79,54,169,21,138,112,239,83,204,186,37,153,6,252,99,223,64,51,172,16,143,117,234,86,201,191,32,156,3,249,102,218,69}, + {0,160,93,253,186,26,231,71,105,201,52,148,211,115,142,46,210,114,143,47,104,200,53,149,187,27,230,70,1,161,92,252,185,25,228,68,3,163,94,254,208,112,141,45,106,202,55,151,107,203,54,150,209,113,140,44,2,162,95,255,184,24,229,69,111,207,50,146,213,117,136,40,6,166,91,251,188,28,225,65,189,29,224,64,7,167,90,250,212,116,137,41,110,206,51,147,214,118,139,43,108,204,49,145,191,31,226,66,5,165,88,248,4,164,89,249,190,30,227,67,109,205,48,144,215,119,138,42,222,126,131,35,100,196,57,153,183,23,234,74,13,173,80,240,12,172,81,241,182,22,235,75,101,197,56,152,223,127,130,34,103,199,58,154,221,125,128,32,14,174,83,243,180,20,233,73,181,21,232,72,15,175,82,242,220,124,129,33,102,198,59,155,177,17,236,76,11,171,86,246,216,120,133,37,98,194,63,159,99,195,62,158,217,121,132,36,10,170,87,247,176,16,237,77,8,168,85,245,178,18,239,79,97,193,60,156,219,123,134,38,218,122,135,39,96,192,61,157,179,19,238,78,9,169,84,244}, + {0,161,95,254,190,31,225,64,97,192,62,159,223,126,128,33,194,99,157,60,124,221,35,130,163,2,252,93,29,188,66,227,153,56,198,103,39,134,120,217,248,89,167,6,70,231,25,184,91,250,4,165,229,68,186,27,58,155,101,196,132,37,219,122,47,142,112,209,145,48,206,111,78,239,17,176,240,81,175,14,237,76,178,19,83,242,12,173,140,45,211,114,50,147,109,204,182,23,233,72,8,169,87,246,215,118,136,41,105,200,54,151,116,213,43,138,202,107,149,52,21,180,74,235,171,10,244,85,94,255,1,160,224,65,191,30,63,158,96,193,129,32,222,127,156,61,195,98,34,131,125,220,253,92,162,3,67,226,28,189,199,102,152,57,121,216,38,135,166,7,249,88,24,185,71,230,5,164,90,251,187,26,228,69,100,197,59,154,218,123,133,36,113,208,46,143,207,110,144,49,16,177,79,238,174,15,241,80,179,18,236,77,13,172,82,243,210,115,141,44,108,205,51,146,232,73,183,22,86,247,9,168,137,40,214,119,55,150,104,201,42,139,117,212,148,53,203,106,75,234,20,181,245,84,170,11}, + {0,162,89,251,178,16,235,73,121,219,32,130,203,105,146,48,242,80,171,9,64,226,25,187,139,41,210,112,57,155,96,194,249,91,160,2,75,233,18,176,128,34,217,123,50,144,107,201,11,169,82,240,185,27,224,66,114,208,43,137,192,98,153,59,239,77,182,20,93,255,4,166,150,52,207,109,36,134,125,223,29,191,68,230,175,13,246,84,100,198,61,159,214,116,143,45,22,180,79,237,164,6,253,95,111,205,54,148,221,127,132,38,228,70,189,31,86,244,15,173,157,63,196,102,47,141,118,212,195,97,154,56,113,211,40,138,186,24,227,65,8,170,81,243,49,147,104,202,131,33,218,120,72,234,17,179,250,88,163,1,58,152,99,193,136,42,209,115,67,225,26,184,241,83,168,10,200,106,145,51,122,216,35,129,177,19,232,74,3,161,90,248,44,142,117,215,158,60,199,101,85,247,12,174,231,69,190,28,222,124,135,37,108,206,53,151,167,5,254,92,21,183,76,238,213,119,140,46,103,197,62,156,172,14,245,87,30,188,71,229,39,133,126,220,149,55,204,110,94,252,7,165,236,78,181,23}, + {0,163,91,248,182,21,237,78,113,210,42,137,199,100,156,63,226,65,185,26,84,247,15,172,147,48,200,107,37,134,126,221,217,122,130,33,111,204,52,151,168,11,243,80,30,189,69,230,59,152,96,195,141,46,214,117,74,233,17,178,252,95,167,4,175,12,244,87,25,186,66,225,222,125,133,38,104,203,51,144,77,238,22,181,251,88,160,3,60,159,103,196,138,41,209,114,118,213,45,142,192,99,155,56,7,164,92,255,177,18,234,73,148,55,207,108,34,129,121,218,229,70,190,29,83,240,8,171,67,224,24,187,245,86,174,13,50,145,105,202,132,39,223,124,161,2,250,89,23,180,76,239,208,115,139,40,102,197,61,158,154,57,193,98,44,143,119,212,235,72,176,19,93,254,6,165,120,219,35,128,206,109,149,54,9,170,82,241,191,28,228,71,236,79,183,20,90,249,1,162,157,62,198,101,43,136,112,211,14,173,85,246,184,27,227,64,127,220,36,135,201,106,146,49,53,150,110,205,131,32,216,123,68,231,31,188,242,81,169,10,215,116,140,47,97,194,58,153,166,5,253,94,16,179,75,232}, + {0,164,85,241,170,14,255,91,73,237,28,184,227,71,182,18,146,54,199,99,56,156,109,201,219,127,142,42,113,213,36,128,57,157,108,200,147,55,198,98,112,212,37,129,218,126,143,43,171,15,254,90,1,165,84,240,226,70,183,19,72,236,29,185,114,214,39,131,216,124,141,41,59,159,110,202,145,53,196,96,224,68,181,17,74,238,31,187,169,13,252,88,3,167,86,242,75,239,30,186,225,69,180,16,2,166,87,243,168,12,253,89,217,125,140,40,115,215,38,130,144,52,197,97,58,158,111,203,228,64,177,21,78,234,27,191,173,9,248,92,7,163,82,246,118,210,35,135,220,120,137,45,63,155,106,206,149,49,192,100,221,121,136,44,119,211,34,134,148,48,193,101,62,154,107,207,79,235,26,190,229,65,176,20,6,162,83,247,172,8,249,93,150,50,195,103,60,152,105,205,223,123,138,46,117,209,32,132,4,160,81,245,174,10,251,95,77,233,24,188,231,67,178,22,175,11,250,94,5,161,80,244,230,66,179,23,76,232,25,189,61,153,104,204,151,51,194,102,116,208,33,133,222,122,139,47}, + {0,165,87,242,174,11,249,92,65,228,22,179,239,74,184,29,130,39,213,112,44,137,123,222,195,102,148,49,109,200,58,159,25,188,78,235,183,18,224,69,88,253,15,170,246,83,161,4,155,62,204,105,53,144,98,199,218,127,141,40,116,209,35,134,50,151,101,192,156,57,203,110,115,214,36,129,221,120,138,47,176,21,231,66,30,187,73,236,241,84,166,3,95,250,8,173,43,142,124,217,133,32,210,119,106,207,61,152,196,97,147,54,169,12,254,91,7,162,80,245,232,77,191,26,70,227,17,180,100,193,51,150,202,111,157,56,37,128,114,215,139,46,220,121,230,67,177,20,72,237,31,186,167,2,240,85,9,172,94,251,125,216,42,143,211,118,132,33,60,153,107,206,146,55,197,96,255,90,168,13,81,244,6,163,190,27,233,76,16,181,71,226,86,243,1,164,248,93,175,10,23,178,64,229,185,28,238,75,212,113,131,38,122,223,45,136,149,48,194,103,59,158,108,201,79,234,24,189,225,68,182,19,14,171,89,252,160,5,247,82,205,104,154,63,99,198,52,145,140,41,219,126,34,135,117,208}, + {0,166,81,247,162,4,243,85,89,255,8,174,251,93,170,12,178,20,227,69,16,182,65,231,235,77,186,28,73,239,24,190,121,223,40,142,219,125,138,44,32,134,113,215,130,36,211,117,203,109,154,60,105,207,56,158,146,52,195,101,48,150,97,199,242,84,163,5,80,246,1,167,171,13,250,92,9,175,88,254,64,230,17,183,226,68,179,21,25,191,72,238,187,29,234,76,139,45,218,124,41,143,120,222,210,116,131,37,112,214,33,135,57,159,104,206,155,61,202,108,96,198,49,151,194,100,147,53,249,95,168,14,91,253,10,172,160,6,241,87,2,164,83,245,75,237,26,188,233,79,184,30,18,180,67,229,176,22,225,71,128,38,209,119,34,132,115,213,217,127,136,46,123,221,42,140,50,148,99,197,144,54,193,103,107,205,58,156,201,111,152,62,11,173,90,252,169,15,248,94,82,244,3,165,240,86,161,7,185,31,232,78,27,189,74,236,224,70,177,23,66,228,19,181,114,212,35,133,208,118,129,39,43,141,122,220,137,47,216,126,192,102,145,55,98,196,51,149,153,63,200,110,59,157,106,204}, + {0,167,83,244,166,1,245,82,81,246,2,165,247,80,164,3,162,5,241,86,4,163,87,240,243,84,160,7,85,242,6,161,89,254,10,173,255,88,172,11,8,175,91,252,174,9,253,90,251,92,168,15,93,250,14,169,170,13,249,94,12,171,95,248,178,21,225,70,20,179,71,224,227,68,176,23,69,226,22,177,16,183,67,228,182,17,229,66,65,230,18,181,231,64,180,19,235,76,184,31,77,234,30,185,186,29,233,78,28,187,79,232,73,238,26,189,239,72,188,27,24,191,75,236,190,25,237,74,121,222,42,141,223,120,140,43,40,143,123,220,142,41,221,122,219,124,136,47,125,218,46,137,138,45,217,126,44,139,127,216,32,135,115,212,134,33,213,114,113,214,34,133,215,112,132,35,130,37,209,118,36,131,119,208,211,116,128,39,117,210,38,129,203,108,152,63,109,202,62,153,154,61,201,110,60,155,111,200,105,206,58,157,207,104,156,59,56,159,107,204,158,57,205,106,146,53,193,102,52,147,103,192,195,100,144,55,101,194,54,145,48,151,99,196,150,49,197,98,97,198,50,149,199,96,148,51}, + {0,168,77,229,154,50,215,127,41,129,100,204,179,27,254,86,82,250,31,183,200,96,133,45,123,211,54,158,225,73,172,4,164,12,233,65,62,150,115,219,141,37,192,104,23,191,90,242,246,94,187,19,108,196,33,137,223,119,146,58,69,237,8,160,85,253,24,176,207,103,130,42,124,212,49,153,230,78,171,3,7,175,74,226,157,53,208,120,46,134,99,203,180,28,249,81,241,89,188,20,107,195,38,142,216,112,149,61,66,234,15,167,163,11,238,70,57,145,116,220,138,34,199,111,16,184,93,245,170,2,231,79,48,152,125,213,131,43,206,102,25,177,84,252,248,80,181,29,98,202,47,135,209,121,156,52,75,227,6,174,14,166,67,235,148,60,217,113,39,143,106,194,189,21,240,88,92,244,17,185,198,110,139,35,117,221,56,144,239,71,162,10,255,87,178,26,101,205,40,128,214,126,155,51,76,228,1,169,173,5,224,72,55,159,122,210,132,44,201,97,30,182,83,251,91,243,22,190,193,105,140,36,114,218,63,151,232,64,165,13,9,161,68,236,147,59,222,118,32,136,109,197,186,18,247,95}, + {0,169,79,230,158,55,209,120,33,136,110,199,191,22,240,89,66,235,13,164,220,117,147,58,99,202,44,133,253,84,178,27,132,45,203,98,26,179,85,252,165,12,234,67,59,146,116,221,198,111,137,32,88,241,23,190,231,78,168,1,121,208,54,159,21,188,90,243,139,34,196,109,52,157,123,210,170,3,229,76,87,254,24,177,201,96,134,47,118,223,57,144,232,65,167,14,145,56,222,119,15,166,64,233,176,25,255,86,46,135,97,200,211,122,156,53,77,228,2,171,242,91,189,20,108,197,35,138,42,131,101,204,180,29,251,82,11,162,68,237,149,60,218,115,104,193,39,142,246,95,185,16,73,224,6,175,215,126,152,49,174,7,225,72,48,153,127,214,143,38,192,105,17,184,94,247,236,69,163,10,114,219,61,148,205,100,130,43,83,250,28,181,63,150,112,217,161,8,238,71,30,183,81,248,128,41,207,102,125,212,50,155,227,74,172,5,92,245,19,186,194,107,141,36,187,18,244,93,37,140,106,195,154,51,213,124,4,173,75,226,249,80,182,31,103,206,40,129,216,113,151,62,70,239,9,160}, + {0,170,73,227,146,56,219,113,57,147,112,218,171,1,226,72,114,216,59,145,224,74,169,3,75,225,2,168,217,115,144,58,228,78,173,7,118,220,63,149,221,119,148,62,79,229,6,172,150,60,223,117,4,174,77,231,175,5,230,76,61,151,116,222,213,127,156,54,71,237,14,164,236,70,165,15,126,212,55,157,167,13,238,68,53,159,124,214,158,52,215,125,12,166,69,239,49,155,120,210,163,9,234,64,8,162,65,235,154,48,211,121,67,233,10,160,209,123,152,50,122,208,51,153,232,66,161,11,183,29,254,84,37,143,108,198,142,36,199,109,28,182,85,255,197,111,140,38,87,253,30,180,252,86,181,31,110,196,39,141,83,249,26,176,193,107,136,34,106,192,35,137,248,82,177,27,33,139,104,194,179,25,250,80,24,178,81,251,138,32,195,105,98,200,43,129,240,90,185,19,91,241,18,184,201,99,128,42,16,186,89,243,130,40,203,97,41,131,96,202,187,17,242,88,134,44,207,101,20,190,93,247,191,21,246,92,45,135,100,206,244,94,189,23,102,204,47,133,205,103,132,46,95,245,22,188}, + {0,171,75,224,150,61,221,118,49,154,122,209,167,12,236,71,98,201,41,130,244,95,191,20,83,248,24,179,197,110,142,37,196,111,143,36,82,249,25,178,245,94,190,21,99,200,40,131,166,13,237,70,48,155,123,208,151,60,220,119,1,170,74,225,149,62,222,117,3,168,72,227,164,15,239,68,50,153,121,210,247,92,188,23,97,202,42,129,198,109,141,38,80,251,27,176,81,250,26,177,199,108,140,39,96,203,43,128,246,93,189,22,51,152,120,211,165,14,238,69,2,169,73,226,148,63,223,116,55,156,124,215,161,10,234,65,6,173,77,230,144,59,219,112,85,254,30,181,195,104,136,35,100,207,47,132,242,89,185,18,243,88,184,19,101,206,46,133,194,105,137,34,84,255,31,180,145,58,218,113,7,172,76,231,160,11,235,64,54,157,125,214,162,9,233,66,52,159,127,212,147,56,216,115,5,174,78,229,192,107,139,32,86,253,29,182,241,90,186,17,103,204,44,135,102,205,45,134,240,91,187,16,87,252,28,183,193,106,138,33,4,175,79,228,146,57,217,114,53,158,126,213,163,8,232,67}, + {0,172,69,233,138,38,207,99,9,165,76,224,131,47,198,106,18,190,87,251,152,52,221,113,27,183,94,242,145,61,212,120,36,136,97,205,174,2,235,71,45,129,104,196,167,11,226,78,54,154,115,223,188,16,249,85,63,147,122,214,181,25,240,92,72,228,13,161,194,110,135,43,65,237,4,168,203,103,142,34,90,246,31,179,208,124,149,57,83,255,22,186,217,117,156,48,108,192,41,133,230,74,163,15,101,201,32,140,239,67,170,6,126,210,59,151,244,88,177,29,119,219,50,158,253,81,184,20,144,60,213,121,26,182,95,243,153,53,220,112,19,191,86,250,130,46,199,107,8,164,77,225,139,39,206,98,1,173,68,232,180,24,241,93,62,146,123,215,189,17,248,84,55,155,114,222,166,10,227,79,44,128,105,197,175,3,234,70,37,137,96,204,216,116,157,49,82,254,23,187,209,125,148,56,91,247,30,178,202,102,143,35,64,236,5,169,195,111,134,42,73,229,12,160,252,80,185,21,118,218,51,159,245,89,176,28,127,211,58,150,238,66,171,7,100,200,33,141,231,75,162,14,109,193,40,132}, + {0,173,71,234,142,35,201,100,1,172,70,235,143,34,200,101,2,175,69,232,140,33,203,102,3,174,68,233,141,32,202,103,4,169,67,238,138,39,205,96,5,168,66,239,139,38,204,97,6,171,65,236,136,37,207,98,7,170,64,237,137,36,206,99,8,165,79,226,134,43,193,108,9,164,78,227,135,42,192,109,10,167,77,224,132,41,195,110,11,166,76,225,133,40,194,111,12,161,75,230,130,47,197,104,13,160,74,231,131,46,196,105,14,163,73,228,128,45,199,106,15,162,72,229,129,44,198,107,16,189,87,250,158,51,217,116,17,188,86,251,159,50,216,117,18,191,85,248,156,49,219,118,19,190,84,249,157,48,218,119,20,185,83,254,154,55,221,112,21,184,82,255,155,54,220,113,22,187,81,252,152,53,223,114,23,186,80,253,153,52,222,115,24,181,95,242,150,59,209,124,25,180,94,243,151,58,208,125,26,183,93,240,148,57,211,126,27,182,92,241,149,56,210,127,28,177,91,246,146,63,213,120,29,176,90,247,147,62,212,121,30,179,89,244,144,61,215,122,31,178,88,245,145,60,214,123}, + {0,174,65,239,130,44,195,109,25,183,88,246,155,53,218,116,50,156,115,221,176,30,241,95,43,133,106,196,169,7,232,70,100,202,37,139,230,72,167,9,125,211,60,146,255,81,190,16,86,248,23,185,212,122,149,59,79,225,14,160,205,99,140,34,200,102,137,39,74,228,11,165,209,127,144,62,83,253,18,188,250,84,187,21,120,214,57,151,227,77,162,12,97,207,32,142,172,2,237,67,46,128,111,193,181,27,244,90,55,153,118,216,158,48,223,113,28,178,93,243,135,41,198,104,5,171,68,234,141,35,204,98,15,161,78,224,148,58,213,123,22,184,87,249,191,17,254,80,61,147,124,210,166,8,231,73,36,138,101,203,233,71,168,6,107,197,42,132,240,94,177,31,114,220,51,157,219,117,154,52,89,247,24,182,194,108,131,45,64,238,1,175,69,235,4,170,199,105,134,40,92,242,29,179,222,112,159,49,119,217,54,152,245,91,180,26,110,192,47,129,236,66,173,3,33,143,96,206,163,13,226,76,56,150,121,215,186,20,251,85,19,189,82,252,145,63,208,126,10,164,75,229,136,38,201,103}, + {0,175,67,236,134,41,197,106,17,190,82,253,151,56,212,123,34,141,97,206,164,11,231,72,51,156,112,223,181,26,246,89,68,235,7,168,194,109,129,46,85,250,22,185,211,124,144,63,102,201,37,138,224,79,163,12,119,216,52,155,241,94,178,29,136,39,203,100,14,161,77,226,153,54,218,117,31,176,92,243,170,5,233,70,44,131,111,192,187,20,248,87,61,146,126,209,204,99,143,32,74,229,9,166,221,114,158,49,91,244,24,183,238,65,173,2,104,199,43,132,255,80,188,19,121,214,58,149,13,162,78,225,139,36,200,103,28,179,95,240,154,53,217,118,47,128,108,195,169,6,234,69,62,145,125,210,184,23,251,84,73,230,10,165,207,96,140,35,88,247,27,180,222,113,157,50,107,196,40,135,237,66,174,1,122,213,57,150,252,83,191,16,133,42,198,105,3,172,64,239,148,59,215,120,18,189,81,254,167,8,228,75,33,142,98,205,182,25,245,90,48,159,115,220,193,110,130,45,71,232,4,171,208,127,147,60,86,249,21,186,227,76,160,15,101,202,38,137,242,93,177,30,116,219,55,152}, + {0,176,125,205,250,74,135,55,233,89,148,36,19,163,110,222,207,127,178,2,53,133,72,248,38,150,91,235,220,108,161,17,131,51,254,78,121,201,4,180,106,218,23,167,144,32,237,93,76,252,49,129,182,6,203,123,165,21,216,104,95,239,34,146,27,171,102,214,225,81,156,44,242,66,143,63,8,184,117,197,212,100,169,25,46,158,83,227,61,141,64,240,199,119,186,10,152,40,229,85,98,210,31,175,113,193,12,188,139,59,246,70,87,231,42,154,173,29,208,96,190,14,195,115,68,244,57,137,54,134,75,251,204,124,177,1,223,111,162,18,37,149,88,232,249,73,132,52,3,179,126,206,16,160,109,221,234,90,151,39,181,5,200,120,79,255,50,130,92,236,33,145,166,22,219,107,122,202,7,183,128,48,253,77,147,35,238,94,105,217,20,164,45,157,80,224,215,103,170,26,196,116,185,9,62,142,67,243,226,82,159,47,24,168,101,213,11,187,118,198,241,65,140,60,174,30,211,99,84,228,41,153,71,247,58,138,189,13,192,112,97,209,28,172,155,43,230,86,136,56,245,69,114,194,15,191}, + {0,177,127,206,254,79,129,48,225,80,158,47,31,174,96,209,223,110,160,17,33,144,94,239,62,143,65,240,192,113,191,14,163,18,220,109,93,236,34,147,66,243,61,140,188,13,195,114,124,205,3,178,130,51,253,76,157,44,226,83,99,210,28,173,91,234,36,149,165,20,218,107,186,11,197,116,68,245,59,138,132,53,251,74,122,203,5,180,101,212,26,171,155,42,228,85,248,73,135,54,6,183,121,200,25,168,102,215,231,86,152,41,39,150,88,233,217,104,166,23,198,119,185,8,56,137,71,246,182,7,201,120,72,249,55,134,87,230,40,153,169,24,214,103,105,216,22,167,151,38,232,89,136,57,247,70,118,199,9,184,21,164,106,219,235,90,148,37,244,69,139,58,10,187,117,196,202,123,181,4,52,133,75,250,43,154,84,229,213,100,170,27,237,92,146,35,19,162,108,221,12,189,115,194,242,67,141,60,50,131,77,252,204,125,179,2,211,98,172,29,45,156,82,227,78,255,49,128,176,1,207,126,175,30,208,97,81,224,46,159,145,32,238,95,111,222,16,161,112,193,15,190,142,63,241,64}, + {0,178,121,203,242,64,139,57,249,75,128,50,11,185,114,192,239,93,150,36,29,175,100,214,22,164,111,221,228,86,157,47,195,113,186,8,49,131,72,250,58,136,67,241,200,122,177,3,44,158,85,231,222,108,167,21,213,103,172,30,39,149,94,236,155,41,226,80,105,219,16,162,98,208,27,169,144,34,233,91,116,198,13,191,134,52,255,77,141,63,244,70,127,205,6,180,88,234,33,147,170,24,211,97,161,19,216,106,83,225,42,152,183,5,206,124,69,247,60,142,78,252,55,133,188,14,197,119,43,153,82,224,217,107,160,18,210,96,171,25,32,146,89,235,196,118,189,15,54,132,79,253,61,143,68,246,207,125,182,4,232,90,145,35,26,168,99,209,17,163,104,218,227,81,154,40,7,181,126,204,245,71,140,62,254,76,135,53,12,190,117,199,176,2,201,123,66,240,59,137,73,251,48,130,187,9,194,112,95,237,38,148,173,31,212,102,166,20,223,109,84,230,45,159,115,193,10,184,129,51,248,74,138,56,243,65,120,202,1,179,156,46,229,87,110,220,23,165,101,215,28,174,151,37,238,92}, + {0,179,123,200,246,69,141,62,241,66,138,57,7,180,124,207,255,76,132,55,9,186,114,193,14,189,117,198,248,75,131,48,227,80,152,43,21,166,110,221,18,161,105,218,228,87,159,44,28,175,103,212,234,89,145,34,237,94,150,37,27,168,96,211,219,104,160,19,45,158,86,229,42,153,81,226,220,111,167,20,36,151,95,236,210,97,169,26,213,102,174,29,35,144,88,235,56,139,67,240,206,125,181,6,201,122,178,1,63,140,68,247,199,116,188,15,49,130,74,249,54,133,77,254,192,115,187,8,171,24,208,99,93,238,38,149,90,233,33,146,172,31,215,100,84,231,47,156,162,17,217,106,165,22,222,109,83,224,40,155,72,251,51,128,190,13,197,118,185,10,194,113,79,252,52,135,183,4,204,127,65,242,58,137,70,245,61,142,176,3,203,120,112,195,11,184,134,53,253,78,129,50,250,73,119,196,12,191,143,60,244,71,121,202,2,177,126,205,5,182,136,59,243,64,147,32,232,91,101,214,30,173,98,209,25,170,148,39,239,92,108,223,23,164,154,41,225,82,157,46,230,85,107,216,16,163}, + {0,180,117,193,234,94,159,43,201,125,188,8,35,151,86,226,143,59,250,78,101,209,16,164,70,242,51,135,172,24,217,109,3,183,118,194,233,93,156,40,202,126,191,11,32,148,85,225,140,56,249,77,102,210,19,167,69,241,48,132,175,27,218,110,6,178,115,199,236,88,153,45,207,123,186,14,37,145,80,228,137,61,252,72,99,215,22,162,64,244,53,129,170,30,223,107,5,177,112,196,239,91,154,46,204,120,185,13,38,146,83,231,138,62,255,75,96,212,21,161,67,247,54,130,169,29,220,104,12,184,121,205,230,82,147,39,197,113,176,4,47,155,90,238,131,55,246,66,105,221,28,168,74,254,63,139,160,20,213,97,15,187,122,206,229,81,144,36,198,114,179,7,44,152,89,237,128,52,245,65,106,222,31,171,73,253,60,136,163,23,214,98,10,190,127,203,224,84,149,33,195,119,182,2,41,157,92,232,133,49,240,68,111,219,26,174,76,248,57,141,166,18,211,103,9,189,124,200,227,87,150,34,192,116,181,1,42,158,95,235,134,50,243,71,108,216,25,173,79,251,58,142,165,17,208,100}, + {0,181,119,194,238,91,153,44,193,116,182,3,47,154,88,237,159,42,232,93,113,196,6,179,94,235,41,156,176,5,199,114,35,150,84,225,205,120,186,15,226,87,149,32,12,185,123,206,188,9,203,126,82,231,37,144,125,200,10,191,147,38,228,81,70,243,49,132,168,29,223,106,135,50,240,69,105,220,30,171,217,108,174,27,55,130,64,245,24,173,111,218,246,67,129,52,101,208,18,167,139,62,252,73,164,17,211,102,74,255,61,136,250,79,141,56,20,161,99,214,59,142,76,249,213,96,162,23,140,57,251,78,98,215,21,160,77,248,58,143,163,22,212,97,19,166,100,209,253,72,138,63,210,103,165,16,60,137,75,254,175,26,216,109,65,244,54,131,110,219,25,172,128,53,247,66,48,133,71,242,222,107,169,28,241,68,134,51,31,170,104,221,202,127,189,8,36,145,83,230,11,190,124,201,229,80,146,39,85,224,34,151,187,14,204,121,148,33,227,86,122,207,13,184,233,92,158,43,7,178,112,197,40,157,95,234,198,115,177,4,118,195,1,180,152,45,239,90,183,2,192,117,89,236,46,155}, + {0,182,113,199,226,84,147,37,217,111,168,30,59,141,74,252,175,25,222,104,77,251,60,138,118,192,7,177,148,34,229,83,67,245,50,132,161,23,208,102,154,44,235,93,120,206,9,191,236,90,157,43,14,184,127,201,53,131,68,242,215,97,166,16,134,48,247,65,100,210,21,163,95,233,46,152,189,11,204,122,41,159,88,238,203,125,186,12,240,70,129,55,18,164,99,213,197,115,180,2,39,145,86,224,28,170,109,219,254,72,143,57,106,220,27,173,136,62,249,79,179,5,194,116,81,231,32,150,17,167,96,214,243,69,130,52,200,126,185,15,42,156,91,237,190,8,207,121,92,234,45,155,103,209,22,160,133,51,244,66,82,228,35,149,176,6,193,119,139,61,250,76,105,223,24,174,253,75,140,58,31,169,110,216,36,146,85,227,198,112,183,1,151,33,230,80,117,195,4,178,78,248,63,137,172,26,221,107,56,142,73,255,218,108,171,29,225,87,144,38,3,181,114,196,212,98,165,19,54,128,71,241,13,187,124,202,239,89,158,40,123,205,10,188,153,47,232,94,162,20,211,101,64,246,49,135}, + {0,183,115,196,230,81,149,34,209,102,162,21,55,128,68,243,191,8,204,123,89,238,42,157,110,217,29,170,136,63,251,76,99,212,16,167,133,50,246,65,178,5,193,118,84,227,39,144,220,107,175,24,58,141,73,254,13,186,126,201,235,92,152,47,198,113,181,2,32,151,83,228,23,160,100,211,241,70,130,53,121,206,10,189,159,40,236,91,168,31,219,108,78,249,61,138,165,18,214,97,67,244,48,135,116,195,7,176,146,37,225,86,26,173,105,222,252,75,143,56,203,124,184,15,45,154,94,233,145,38,226,85,119,192,4,179,64,247,51,132,166,17,213,98,46,153,93,234,200,127,187,12,255,72,140,59,25,174,106,221,242,69,129,54,20,163,103,208,35,148,80,231,197,114,182,1,77,250,62,137,171,28,216,111,156,43,239,88,122,205,9,190,87,224,36,147,177,6,194,117,134,49,245,66,96,215,19,164,232,95,155,44,14,185,125,202,57,142,74,253,223,104,172,27,52,131,71,240,210,101,161,22,229,82,150,33,3,180,112,199,139,60,248,79,109,218,30,169,90,237,41,158,188,11,207,120}, + {0,184,109,213,218,98,183,15,169,17,196,124,115,203,30,166,79,247,34,154,149,45,248,64,230,94,139,51,60,132,81,233,158,38,243,75,68,252,41,145,55,143,90,226,237,85,128,56,209,105,188,4,11,179,102,222,120,192,21,173,162,26,207,119,33,153,76,244,251,67,150,46,136,48,229,93,82,234,63,135,110,214,3,187,180,12,217,97,199,127,170,18,29,165,112,200,191,7,210,106,101,221,8,176,22,174,123,195,204,116,161,25,240,72,157,37,42,146,71,255,89,225,52,140,131,59,238,86,66,250,47,151,152,32,245,77,235,83,134,62,49,137,92,228,13,181,96,216,215,111,186,2,164,28,201,113,126,198,19,171,220,100,177,9,6,190,107,211,117,205,24,160,175,23,194,122,147,43,254,70,73,241,36,156,58,130,87,239,224,88,141,53,99,219,14,182,185,1,212,108,202,114,167,31,16,168,125,197,44,148,65,249,246,78,155,35,133,61,232,80,95,231,50,138,253,69,144,40,39,159,74,242,84,236,57,129,142,54,227,91,178,10,223,103,104,208,5,189,27,163,118,206,193,121,172,20}, + {0,185,111,214,222,103,177,8,161,24,206,119,127,198,16,169,95,230,48,137,129,56,238,87,254,71,145,40,32,153,79,246,190,7,209,104,96,217,15,182,31,166,112,201,193,120,174,23,225,88,142,55,63,134,80,233,64,249,47,150,158,39,241,72,97,216,14,183,191,6,208,105,192,121,175,22,30,167,113,200,62,135,81,232,224,89,143,54,159,38,240,73,65,248,46,151,223,102,176,9,1,184,110,215,126,199,17,168,160,25,207,118,128,57,239,86,94,231,49,136,33,152,78,247,255,70,144,41,194,123,173,20,28,165,115,202,99,218,12,181,189,4,210,107,157,36,242,75,67,250,44,149,60,133,83,234,226,91,141,52,124,197,19,170,162,27,205,116,221,100,178,11,3,186,108,213,35,154,76,245,253,68,146,43,130,59,237,84,92,229,51,138,163,26,204,117,125,196,18,171,2,187,109,212,220,101,179,10,252,69,147,42,34,155,77,244,93,228,50,139,131,58,236,85,29,164,114,203,195,122,172,21,188,5,211,106,98,219,13,180,66,251,45,148,156,37,243,74,227,90,140,53,61,132,82,235}, + {0,186,105,211,210,104,187,1,185,3,208,106,107,209,2,184,111,213,6,188,189,7,212,110,214,108,191,5,4,190,109,215,222,100,183,13,12,182,101,223,103,221,14,180,181,15,220,102,177,11,216,98,99,217,10,176,8,178,97,219,218,96,179,9,161,27,200,114,115,201,26,160,24,162,113,203,202,112,163,25,206,116,167,29,28,166,117,207,119,205,30,164,165,31,204,118,127,197,22,172,173,23,196,126,198,124,175,21,20,174,125,199,16,170,121,195,194,120,171,17,169,19,192,122,123,193,18,168,95,229,54,140,141,55,228,94,230,92,143,53,52,142,93,231,48,138,89,227,226,88,139,49,137,51,224,90,91,225,50,136,129,59,232,82,83,233,58,128,56,130,81,235,234,80,131,57,238,84,135,61,60,134,85,239,87,237,62,132,133,63,236,86,254,68,151,45,44,150,69,255,71,253,46,148,149,47,252,70,145,43,248,66,67,249,42,144,40,146,65,251,250,64,147,41,32,154,73,243,242,72,155,33,153,35,240,74,75,241,34,152,79,245,38,156,157,39,244,78,246,76,159,37,36,158,77,247}, + {0,187,107,208,214,109,189,6,177,10,218,97,103,220,12,183,127,196,20,175,169,18,194,121,206,117,165,30,24,163,115,200,254,69,149,46,40,147,67,248,79,244,36,159,153,34,242,73,129,58,234,81,87,236,60,135,48,139,91,224,230,93,141,54,225,90,138,49,55,140,92,231,80,235,59,128,134,61,237,86,158,37,245,78,72,243,35,152,47,148,68,255,249,66,146,41,31,164,116,207,201,114,162,25,174,21,197,126,120,195,19,168,96,219,11,176,182,13,221,102,209,106,186,1,7,188,108,215,223,100,180,15,9,178,98,217,110,213,5,190,184,3,211,104,160,27,203,112,118,205,29,166,17,170,122,193,199,124,172,23,33,154,74,241,247,76,156,39,144,43,251,64,70,253,45,150,94,229,53,142,136,51,227,88,239,84,132,63,57,130,82,233,62,133,85,238,232,83,131,56,143,52,228,95,89,226,50,137,65,250,42,145,151,44,252,71,240,75,155,32,38,157,77,246,192,123,171,16,22,173,125,198,113,202,26,161,167,28,204,119,191,4,212,111,105,210,2,185,14,181,101,222,216,99,179,8}, + {0,188,101,217,202,118,175,19,137,53,236,80,67,255,38,154,15,179,106,214,197,121,160,28,134,58,227,95,76,240,41,149,30,162,123,199,212,104,177,13,151,43,242,78,93,225,56,132,17,173,116,200,219,103,190,2,152,36,253,65,82,238,55,139,60,128,89,229,246,74,147,47,181,9,208,108,127,195,26,166,51,143,86,234,249,69,156,32,186,6,223,99,112,204,21,169,34,158,71,251,232,84,141,49,171,23,206,114,97,221,4,184,45,145,72,244,231,91,130,62,164,24,193,125,110,210,11,183,120,196,29,161,178,14,215,107,241,77,148,40,59,135,94,226,119,203,18,174,189,1,216,100,254,66,155,39,52,136,81,237,102,218,3,191,172,16,201,117,239,83,138,54,37,153,64,252,105,213,12,176,163,31,198,122,224,92,133,57,42,150,79,243,68,248,33,157,142,50,235,87,205,113,168,20,7,187,98,222,75,247,46,146,129,61,228,88,194,126,167,27,8,180,109,209,90,230,63,131,144,44,245,73,211,111,182,10,25,165,124,192,85,233,48,140,159,35,250,70,220,96,185,5,22,170,115,207}, + {0,189,103,218,206,115,169,20,129,60,230,91,79,242,40,149,31,162,120,197,209,108,182,11,158,35,249,68,80,237,55,138,62,131,89,228,240,77,151,42,191,2,216,101,113,204,22,171,33,156,70,251,239,82,136,53,160,29,199,122,110,211,9,180,124,193,27,166,178,15,213,104,253,64,154,39,51,142,84,233,99,222,4,185,173,16,202,119,226,95,133,56,44,145,75,246,66,255,37,152,140,49,235,86,195,126,164,25,13,176,106,215,93,224,58,135,147,46,244,73,220,97,187,6,18,175,117,200,248,69,159,34,54,139,81,236,121,196,30,163,183,10,208,109,231,90,128,61,41,148,78,243,102,219,1,188,168,21,207,114,198,123,161,28,8,181,111,210,71,250,32,157,137,52,238,83,217,100,190,3,23,170,112,205,88,229,63,130,150,43,241,76,132,57,227,94,74,247,45,144,5,184,98,223,203,118,172,17,155,38,252,65,85,232,50,143,26,167,125,192,212,105,179,14,186,7,221,96,116,201,19,174,59,134,92,225,245,72,146,47,165,24,194,127,107,214,12,177,36,153,67,254,234,87,141,48}, + {0,190,97,223,194,124,163,29,153,39,248,70,91,229,58,132,47,145,78,240,237,83,140,50,182,8,215,105,116,202,21,171,94,224,63,129,156,34,253,67,199,121,166,24,5,187,100,218,113,207,16,174,179,13,210,108,232,86,137,55,42,148,75,245,188,2,221,99,126,192,31,161,37,155,68,250,231,89,134,56,147,45,242,76,81,239,48,142,10,180,107,213,200,118,169,23,226,92,131,61,32,158,65,255,123,197,26,164,185,7,216,102,205,115,172,18,15,177,110,208,84,234,53,139,150,40,247,73,101,219,4,186,167,25,198,120,252,66,157,35,62,128,95,225,74,244,43,149,136,54,233,87,211,109,178,12,17,175,112,206,59,133,90,228,249,71,152,38,162,28,195,125,96,222,1,191,20,170,117,203,214,104,183,9,141,51,236,82,79,241,46,144,217,103,184,6,27,165,122,196,64,254,33,159,130,60,227,93,246,72,151,41,52,138,85,235,111,209,14,176,173,19,204,114,135,57,230,88,69,251,36,154,30,160,127,193,220,98,189,3,168,22,201,119,106,212,11,181,49,143,80,238,243,77,146,44}, + {0,191,99,220,198,121,165,26,145,46,242,77,87,232,52,139,63,128,92,227,249,70,154,37,174,17,205,114,104,215,11,180,126,193,29,162,184,7,219,100,239,80,140,51,41,150,74,245,65,254,34,157,135,56,228,91,208,111,179,12,22,169,117,202,252,67,159,32,58,133,89,230,109,210,14,177,171,20,200,119,195,124,160,31,5,186,102,217,82,237,49,142,148,43,247,72,130,61,225,94,68,251,39,152,19,172,112,207,213,106,182,9,189,2,222,97,123,196,24,167,44,147,79,240,234,85,137,54,229,90,134,57,35,156,64,255,116,203,23,168,178,13,209,110,218,101,185,6,28,163,127,192,75,244,40,151,141,50,238,81,155,36,248,71,93,226,62,129,10,181,105,214,204,115,175,16,164,27,199,120,98,221,1,190,53,138,86,233,243,76,144,47,25,166,122,197,223,96,188,3,136,55,235,84,78,241,45,146,38,153,69,250,224,95,131,60,183,8,212,107,113,206,18,173,103,216,4,187,161,30,194,125,246,73,149,42,48,143,83,236,88,231,59,132,158,33,253,66,201,118,170,21,15,176,108,211}, + {0,192,157,93,39,231,186,122,78,142,211,19,105,169,244,52,156,92,1,193,187,123,38,230,210,18,79,143,245,53,104,168,37,229,184,120,2,194,159,95,107,171,246,54,76,140,209,17,185,121,36,228,158,94,3,195,247,55,106,170,208,16,77,141,74,138,215,23,109,173,240,48,4,196,153,89,35,227,190,126,214,22,75,139,241,49,108,172,152,88,5,197,191,127,34,226,111,175,242,50,72,136,213,21,33,225,188,124,6,198,155,91,243,51,110,174,212,20,73,137,189,125,32,224,154,90,7,199,148,84,9,201,179,115,46,238,218,26,71,135,253,61,96,160,8,200,149,85,47,239,178,114,70,134,219,27,97,161,252,60,177,113,44,236,150,86,11,203,255,63,98,162,216,24,69,133,45,237,176,112,10,202,151,87,99,163,254,62,68,132,217,25,222,30,67,131,249,57,100,164,144,80,13,205,183,119,42,234,66,130,223,31,101,165,248,56,12,204,145,81,43,235,182,118,251,59,102,166,220,28,65,129,181,117,40,232,146,82,15,207,103,167,250,58,64,128,221,29,41,233,180,116,14,206,147,83}, + {0,193,159,94,35,226,188,125,70,135,217,24,101,164,250,59,140,77,19,210,175,110,48,241,202,11,85,148,233,40,118,183,5,196,154,91,38,231,185,120,67,130,220,29,96,161,255,62,137,72,22,215,170,107,53,244,207,14,80,145,236,45,115,178,10,203,149,84,41,232,182,119,76,141,211,18,111,174,240,49,134,71,25,216,165,100,58,251,192,1,95,158,227,34,124,189,15,206,144,81,44,237,179,114,73,136,214,23,106,171,245,52,131,66,28,221,160,97,63,254,197,4,90,155,230,39,121,184,20,213,139,74,55,246,168,105,82,147,205,12,113,176,238,47,152,89,7,198,187,122,36,229,222,31,65,128,253,60,98,163,17,208,142,79,50,243,173,108,87,150,200,9,116,181,235,42,157,92,2,195,190,127,33,224,219,26,68,133,248,57,103,166,30,223,129,64,61,252,162,99,88,153,199,6,123,186,228,37,146,83,13,204,177,112,46,239,212,21,75,138,247,54,104,169,27,218,132,69,56,249,167,102,93,156,194,3,126,191,225,32,151,86,8,201,180,117,43,234,209,16,78,143,242,51,109,172}, + {0,194,153,91,47,237,182,116,94,156,199,5,113,179,232,42,188,126,37,231,147,81,10,200,226,32,123,185,205,15,84,150,101,167,252,62,74,136,211,17,59,249,162,96,20,214,141,79,217,27,64,130,246,52,111,173,135,69,30,220,168,106,49,243,202,8,83,145,229,39,124,190,148,86,13,207,187,121,34,224,118,180,239,45,89,155,192,2,40,234,177,115,7,197,158,92,175,109,54,244,128,66,25,219,241,51,104,170,222,28,71,133,19,209,138,72,60,254,165,103,77,143,212,22,98,160,251,57,137,75,16,210,166,100,63,253,215,21,78,140,248,58,97,163,53,247,172,110,26,216,131,65,107,169,242,48,68,134,221,31,236,46,117,183,195,1,90,152,178,112,43,233,157,95,4,198,80,146,201,11,127,189,230,36,14,204,151,85,33,227,184,122,67,129,218,24,108,174,245,55,29,223,132,70,50,240,171,105,255,61,102,164,208,18,73,139,161,99,56,250,142,76,23,213,38,228,191,125,9,203,144,82,120,186,225,35,87,149,206,12,154,88,3,193,181,119,44,238,196,6,93,159,235,41,114,176}, + {0,195,155,88,43,232,176,115,86,149,205,14,125,190,230,37,172,111,55,244,135,68,28,223,250,57,97,162,209,18,74,137,69,134,222,29,110,173,245,54,19,208,136,75,56,251,163,96,233,42,114,177,194,1,89,154,191,124,36,231,148,87,15,204,138,73,17,210,161,98,58,249,220,31,71,132,247,52,108,175,38,229,189,126,13,206,150,85,112,179,235,40,91,152,192,3,207,12,84,151,228,39,127,188,153,90,2,193,178,113,41,234,99,160,248,59,72,139,211,16,53,246,174,109,30,221,133,70,9,202,146,81,34,225,185,122,95,156,196,7,116,183,239,44,165,102,62,253,142,77,21,214,243,48,104,171,216,27,67,128,76,143,215,20,103,164,252,63,26,217,129,66,49,242,170,105,224,35,123,184,203,8,80,147,182,117,45,238,157,94,6,197,131,64,24,219,168,107,51,240,213,22,78,141,254,61,101,166,47,236,180,119,4,199,159,92,121,186,226,33,82,145,201,10,198,5,93,158,237,46,118,181,144,83,11,200,187,120,32,227,106,169,241,50,65,130,218,25,60,255,167,100,23,212,140,79}, + {0,196,149,81,55,243,162,102,110,170,251,63,89,157,204,8,220,24,73,141,235,47,126,186,178,118,39,227,133,65,16,212,165,97,48,244,146,86,7,195,203,15,94,154,252,56,105,173,121,189,236,40,78,138,219,31,23,211,130,70,32,228,181,113,87,147,194,6,96,164,245,49,57,253,172,104,14,202,155,95,139,79,30,218,188,120,41,237,229,33,112,180,210,22,71,131,242,54,103,163,197,1,80,148,156,88,9,205,171,111,62,250,46,234,187,127,25,221,140,72,64,132,213,17,119,179,226,38,174,106,59,255,153,93,12,200,192,4,85,145,247,51,98,166,114,182,231,35,69,129,208,20,28,216,137,77,43,239,190,122,11,207,158,90,60,248,169,109,101,161,240,52,82,150,199,3,215,19,66,134,224,36,117,177,185,125,44,232,142,74,27,223,249,61,108,168,206,10,91,159,151,83,2,198,160,100,53,241,37,225,176,116,18,214,135,67,75,143,222,26,124,184,233,45,92,152,201,13,107,175,254,58,50,246,167,99,5,193,144,84,128,68,21,209,183,115,34,230,238,42,123,191,217,29,76,136}, + {0,197,151,82,51,246,164,97,102,163,241,52,85,144,194,7,204,9,91,158,255,58,104,173,170,111,61,248,153,92,14,203,133,64,18,215,182,115,33,228,227,38,116,177,208,21,71,130,73,140,222,27,122,191,237,40,47,234,184,125,28,217,139,78,23,210,128,69,36,225,179,118,113,180,230,35,66,135,213,16,219,30,76,137,232,45,127,186,189,120,42,239,142,75,25,220,146,87,5,192,161,100,54,243,244,49,99,166,199,2,80,149,94,155,201,12,109,168,250,63,56,253,175,106,11,206,156,89,46,235,185,124,29,216,138,79,72,141,223,26,123,190,236,41,226,39,117,176,209,20,70,131,132,65,19,214,183,114,32,229,171,110,60,249,152,93,15,202,205,8,90,159,254,59,105,172,103,162,240,53,84,145,195,6,1,196,150,83,50,247,165,96,57,252,174,107,10,207,157,88,95,154,200,13,108,169,251,62,245,48,98,167,198,3,81,148,147,86,4,193,160,101,55,242,188,121,43,238,143,74,24,221,218,31,77,136,233,44,126,187,112,181,231,34,67,134,212,17,22,211,129,68,37,224,178,119}, + {0,198,145,87,63,249,174,104,126,184,239,41,65,135,208,22,252,58,109,171,195,5,82,148,130,68,19,213,189,123,44,234,229,35,116,178,218,28,75,141,155,93,10,204,164,98,53,243,25,223,136,78,38,224,183,113,103,161,246,48,88,158,201,15,215,17,70,128,232,46,121,191,169,111,56,254,150,80,7,193,43,237,186,124,20,210,133,67,85,147,196,2,106,172,251,61,50,244,163,101,13,203,156,90,76,138,221,27,115,181,226,36,206,8,95,153,241,55,96,166,176,118,33,231,143,73,30,216,179,117,34,228,140,74,29,219,205,11,92,154,242,52,99,165,79,137,222,24,112,182,225,39,49,247,160,102,14,200,159,89,86,144,199,1,105,175,248,62,40,238,185,127,23,209,134,64,170,108,59,253,149,83,4,194,212,18,69,131,235,45,122,188,100,162,245,51,91,157,202,12,26,220,139,77,37,227,180,114,152,94,9,207,167,97,54,240,230,32,119,177,217,31,72,142,129,71,16,214,190,120,47,233,255,57,110,168,192,6,81,151,125,187,236,42,66,132,211,21,3,197,146,84,60,250,173,107}, + {0,199,147,84,59,252,168,111,118,177,229,34,77,138,222,25,236,43,127,184,215,16,68,131,154,93,9,206,161,102,50,245,197,2,86,145,254,57,109,170,179,116,32,231,136,79,27,220,41,238,186,125,18,213,129,70,95,152,204,11,100,163,247,48,151,80,4,195,172,107,63,248,225,38,114,181,218,29,73,142,123,188,232,47,64,135,211,20,13,202,158,89,54,241,165,98,82,149,193,6,105,174,250,61,36,227,183,112,31,216,140,75,190,121,45,234,133,66,22,209,200,15,91,156,243,52,96,167,51,244,160,103,8,207,155,92,69,130,214,17,126,185,237,42,223,24,76,139,228,35,119,176,169,110,58,253,146,85,1,198,246,49,101,162,205,10,94,153,128,71,19,212,187,124,40,239,26,221,137,78,33,230,178,117,108,171,255,56,87,144,196,3,164,99,55,240,159,88,12,203,210,21,65,134,233,46,122,189,72,143,219,28,115,180,224,39,62,249,173,106,5,194,150,81,97,166,242,53,90,157,201,14,23,208,132,67,44,235,191,120,141,74,30,217,182,113,37,226,251,60,104,175,192,7,83,148}, + {0,200,141,69,7,207,138,66,14,198,131,75,9,193,132,76,28,212,145,89,27,211,150,94,18,218,159,87,21,221,152,80,56,240,181,125,63,247,178,122,54,254,187,115,49,249,188,116,36,236,169,97,35,235,174,102,42,226,167,111,45,229,160,104,112,184,253,53,119,191,250,50,126,182,243,59,121,177,244,60,108,164,225,41,107,163,230,46,98,170,239,39,101,173,232,32,72,128,197,13,79,135,194,10,70,142,203,3,65,137,204,4,84,156,217,17,83,155,222,22,90,146,215,31,93,149,208,24,224,40,109,165,231,47,106,162,238,38,99,171,233,33,100,172,252,52,113,185,251,51,118,190,242,58,127,183,245,61,120,176,216,16,85,157,223,23,82,154,214,30,91,147,209,25,92,148,196,12,73,129,195,11,78,134,202,2,71,143,205,5,64,136,144,88,29,213,151,95,26,210,158,86,19,219,153,81,20,220,140,68,1,201,139,67,6,206,130,74,15,199,133,77,8,192,168,96,37,237,175,103,34,234,166,110,43,227,161,105,44,228,180,124,57,241,179,123,62,246,186,114,55,255,189,117,48,248}, + {0,201,143,70,3,202,140,69,6,207,137,64,5,204,138,67,12,197,131,74,15,198,128,73,10,195,133,76,9,192,134,79,24,209,151,94,27,210,148,93,30,215,145,88,29,212,146,91,20,221,155,82,23,222,152,81,18,219,157,84,17,216,158,87,48,249,191,118,51,250,188,117,54,255,185,112,53,252,186,115,60,245,179,122,63,246,176,121,58,243,181,124,57,240,182,127,40,225,167,110,43,226,164,109,46,231,161,104,45,228,162,107,36,237,171,98,39,238,168,97,34,235,173,100,33,232,174,103,96,169,239,38,99,170,236,37,102,175,233,32,101,172,234,35,108,165,227,42,111,166,224,41,106,163,229,44,105,160,230,47,120,177,247,62,123,178,244,61,126,183,241,56,125,180,242,59,116,189,251,50,119,190,248,49,114,187,253,52,113,184,254,55,80,153,223,22,83,154,220,21,86,159,217,16,85,156,218,19,92,149,211,26,95,150,208,25,90,147,213,28,89,144,214,31,72,129,199,14,75,130,196,13,78,135,193,8,77,132,194,11,68,141,203,2,71,142,200,1,66,139,205,4,65,136,206,7}, + {0,202,137,67,15,197,134,76,30,212,151,93,17,219,152,82,60,246,181,127,51,249,186,112,34,232,171,97,45,231,164,110,120,178,241,59,119,189,254,52,102,172,239,37,105,163,224,42,68,142,205,7,75,129,194,8,90,144,211,25,85,159,220,22,240,58,121,179,255,53,118,188,238,36,103,173,225,43,104,162,204,6,69,143,195,9,74,128,210,24,91,145,221,23,84,158,136,66,1,203,135,77,14,196,150,92,31,213,153,83,16,218,180,126,61,247,187,113,50,248,170,96,35,233,165,111,44,230,253,55,116,190,242,56,123,177,227,41,106,160,236,38,101,175,193,11,72,130,206,4,71,141,223,21,86,156,208,26,89,147,133,79,12,198,138,64,3,201,155,81,18,216,148,94,29,215,185,115,48,250,182,124,63,245,167,109,46,228,168,98,33,235,13,199,132,78,2,200,139,65,19,217,154,80,28,214,149,95,49,251,184,114,62,244,183,125,47,229,166,108,32,234,169,99,117,191,252,54,122,176,243,57,107,161,226,40,100,174,237,39,73,131,192,10,70,140,207,5,87,157,222,20,88,146,209,27}, + {0,203,139,64,11,192,128,75,22,221,157,86,29,214,150,93,44,231,167,108,39,236,172,103,58,241,177,122,49,250,186,113,88,147,211,24,83,152,216,19,78,133,197,14,69,142,206,5,116,191,255,52,127,180,244,63,98,169,233,34,105,162,226,41,176,123,59,240,187,112,48,251,166,109,45,230,173,102,38,237,156,87,23,220,151,92,28,215,138,65,1,202,129,74,10,193,232,35,99,168,227,40,104,163,254,53,117,190,245,62,126,181,196,15,79,132,207,4,68,143,210,25,89,146,217,18,82,153,125,182,246,61,118,189,253,54,107,160,224,43,96,171,235,32,81,154,218,17,90,145,209,26,71,140,204,7,76,135,199,12,37,238,174,101,46,229,165,110,51,248,184,115,56,243,179,120,9,194,130,73,2,201,137,66,31,212,148,95,20,223,159,84,205,6,70,141,198,13,77,134,219,16,80,155,208,27,91,144,225,42,106,161,234,33,97,170,247,60,124,183,252,55,119,188,149,94,30,213,158,85,21,222,131,72,8,195,136,67,3,200,185,114,50,249,178,121,57,242,175,100,36,239,164,111,47,228}, + {0,204,133,73,23,219,146,94,46,226,171,103,57,245,188,112,92,144,217,21,75,135,206,2,114,190,247,59,101,169,224,44,184,116,61,241,175,99,42,230,150,90,19,223,129,77,4,200,228,40,97,173,243,63,118,186,202,6,79,131,221,17,88,148,109,161,232,36,122,182,255,51,67,143,198,10,84,152,209,29,49,253,180,120,38,234,163,111,31,211,154,86,8,196,141,65,213,25,80,156,194,14,71,139,251,55,126,178,236,32,105,165,137,69,12,192,158,82,27,215,167,107,34,238,176,124,53,249,218,22,95,147,205,1,72,132,244,56,113,189,227,47,102,170,134,74,3,207,145,93,20,216,168,100,45,225,191,115,58,246,98,174,231,43,117,185,240,60,76,128,201,5,91,151,222,18,62,242,187,119,41,229,172,96,16,220,149,89,7,203,130,78,183,123,50,254,160,108,37,233,153,85,28,208,142,66,11,199,235,39,110,162,252,48,121,181,197,9,64,140,210,30,87,155,15,195,138,70,24,212,157,81,33,237,164,104,54,250,179,127,83,159,214,26,68,136,193,13,125,177,248,52,106,166,239,35}, + {0,205,135,74,19,222,148,89,38,235,161,108,53,248,178,127,76,129,203,6,95,146,216,21,106,167,237,32,121,180,254,51,152,85,31,210,139,70,12,193,190,115,57,244,173,96,42,231,212,25,83,158,199,10,64,141,242,63,117,184,225,44,102,171,45,224,170,103,62,243,185,116,11,198,140,65,24,213,159,82,97,172,230,43,114,191,245,56,71,138,192,13,84,153,211,30,181,120,50,255,166,107,33,236,147,94,20,217,128,77,7,202,249,52,126,179,234,39,109,160,223,18,88,149,204,1,75,134,90,151,221,16,73,132,206,3,124,177,251,54,111,162,232,37,22,219,145,92,5,200,130,79,48,253,183,122,35,238,164,105,194,15,69,136,209,28,86,155,228,41,99,174,247,58,112,189,142,67,9,196,157,80,26,215,168,101,47,226,187,118,60,241,119,186,240,61,100,169,227,46,81,156,214,27,66,143,197,8,59,246,188,113,40,229,175,98,29,208,154,87,14,195,137,68,239,34,104,165,252,49,123,182,201,4,78,131,218,23,93,144,163,110,36,233,176,125,55,250,133,72,2,207,150,91,17,220}, + {0,206,129,79,31,209,158,80,62,240,191,113,33,239,160,110,124,178,253,51,99,173,226,44,66,140,195,13,93,147,220,18,248,54,121,183,231,41,102,168,198,8,71,137,217,23,88,150,132,74,5,203,155,85,26,212,186,116,59,245,165,107,36,234,237,35,108,162,242,60,115,189,211,29,82,156,204,2,77,131,145,95,16,222,142,64,15,193,175,97,46,224,176,126,49,255,21,219,148,90,10,196,139,69,43,229,170,100,52,250,181,123,105,167,232,38,118,184,247,57,87,153,214,24,72,134,201,7,199,9,70,136,216,22,89,151,249,55,120,182,230,40,103,169,187,117,58,244,164,106,37,235,133,75,4,202,154,84,27,213,63,241,190,112,32,238,161,111,1,207,128,78,30,208,159,81,67,141,194,12,92,146,221,19,125,179,252,50,98,172,227,45,42,228,171,101,53,251,180,122,20,218,149,91,11,197,138,68,86,152,215,25,73,135,200,6,104,166,233,39,119,185,246,56,210,28,83,157,205,3,76,130,236,34,109,163,243,61,114,188,174,96,47,225,177,127,48,254,144,94,17,223,143,65,14,192}, + {0,207,131,76,27,212,152,87,54,249,181,122,45,226,174,97,108,163,239,32,119,184,244,59,90,149,217,22,65,142,194,13,216,23,91,148,195,12,64,143,238,33,109,162,245,58,118,185,180,123,55,248,175,96,44,227,130,77,1,206,153,86,26,213,173,98,46,225,182,121,53,250,155,84,24,215,128,79,3,204,193,14,66,141,218,21,89,150,247,56,116,187,236,35,111,160,117,186,246,57,110,161,237,34,67,140,192,15,88,151,219,20,25,214,154,85,2,205,129,78,47,224,172,99,52,251,183,120,71,136,196,11,92,147,223,16,113,190,242,61,106,165,233,38,43,228,168,103,48,255,179,124,29,210,158,81,6,201,133,74,159,80,28,211,132,75,7,200,169,102,42,229,178,125,49,254,243,60,112,191,232,39,107,164,197,10,70,137,222,17,93,146,234,37,105,166,241,62,114,189,220,19,95,144,199,8,68,139,134,73,5,202,157,82,30,209,176,127,51,252,171,100,40,231,50,253,177,126,41,230,170,101,4,203,135,72,31,208,156,83,94,145,221,18,69,138,198,9,104,167,235,36,115,188,240,63}, + {0,208,189,109,103,183,218,10,206,30,115,163,169,121,20,196,129,81,60,236,230,54,91,139,79,159,242,34,40,248,149,69,31,207,162,114,120,168,197,21,209,1,108,188,182,102,11,219,158,78,35,243,249,41,68,148,80,128,237,61,55,231,138,90,62,238,131,83,89,137,228,52,240,32,77,157,151,71,42,250,191,111,2,210,216,8,101,181,113,161,204,28,22,198,171,123,33,241,156,76,70,150,251,43,239,63,82,130,136,88,53,229,160,112,29,205,199,23,122,170,110,190,211,3,9,217,180,100,124,172,193,17,27,203,166,118,178,98,15,223,213,5,104,184,253,45,64,144,154,74,39,247,51,227,142,94,84,132,233,57,99,179,222,14,4,212,185,105,173,125,16,192,202,26,119,167,226,50,95,143,133,85,56,232,44,252,145,65,75,155,246,38,66,146,255,47,37,245,152,72,140,92,49,225,235,59,86,134,195,19,126,174,164,116,25,201,13,221,176,96,106,186,215,7,93,141,224,48,58,234,135,87,147,67,46,254,244,36,73,153,220,12,97,177,187,107,6,214,18,194,175,127,117,165,200,24}, + {0,209,191,110,99,178,220,13,198,23,121,168,165,116,26,203,145,64,46,255,242,35,77,156,87,134,232,57,52,229,139,90,63,238,128,81,92,141,227,50,249,40,70,151,154,75,37,244,174,127,17,192,205,28,114,163,104,185,215,6,11,218,180,101,126,175,193,16,29,204,162,115,184,105,7,214,219,10,100,181,239,62,80,129,140,93,51,226,41,248,150,71,74,155,245,36,65,144,254,47,34,243,157,76,135,86,56,233,228,53,91,138,208,1,111,190,179,98,12,221,22,199,169,120,117,164,202,27,252,45,67,146,159,78,32,241,58,235,133,84,89,136,230,55,109,188,210,3,14,223,177,96,171,122,20,197,200,25,119,166,195,18,124,173,160,113,31,206,5,212,186,107,102,183,217,8,82,131,237,60,49,224,142,95,148,69,43,250,247,38,72,153,130,83,61,236,225,48,94,143,68,149,251,42,39,246,152,73,19,194,172,125,112,161,207,30,213,4,106,187,182,103,9,216,189,108,2,211,222,15,97,176,123,170,196,21,24,201,167,118,44,253,147,66,79,158,240,33,234,59,85,132,137,88,54,231}, + {0,210,185,107,111,189,214,4,222,12,103,181,177,99,8,218,161,115,24,202,206,28,119,165,127,173,198,20,16,194,169,123,95,141,230,52,48,226,137,91,129,83,56,234,238,60,87,133,254,44,71,149,145,67,40,250,32,242,153,75,79,157,246,36,190,108,7,213,209,3,104,186,96,178,217,11,15,221,182,100,31,205,166,116,112,162,201,27,193,19,120,170,174,124,23,197,225,51,88,138,142,92,55,229,63,237,134,84,80,130,233,59,64,146,249,43,47,253,150,68,158,76,39,245,241,35,72,154,97,179,216,10,14,220,183,101,191,109,6,212,208,2,105,187,192,18,121,171,175,125,22,196,30,204,167,117,113,163,200,26,62,236,135,85,81,131,232,58,224,50,89,139,143,93,54,228,159,77,38,244,240,34,73,155,65,147,248,42,46,252,151,69,223,13,102,180,176,98,9,219,1,211,184,106,110,188,215,5,126,172,199,21,17,195,168,122,160,114,25,203,207,29,118,164,128,82,57,235,239,61,86,132,94,140,231,53,49,227,136,90,33,243,152,74,78,156,247,37,255,45,70,148,144,66,41,251}, + {0,211,187,104,107,184,208,3,214,5,109,190,189,110,6,213,177,98,10,217,218,9,97,178,103,180,220,15,12,223,183,100,127,172,196,23,20,199,175,124,169,122,18,193,194,17,121,170,206,29,117,166,165,118,30,205,24,203,163,112,115,160,200,27,254,45,69,150,149,70,46,253,40,251,147,64,67,144,248,43,79,156,244,39,36,247,159,76,153,74,34,241,242,33,73,154,129,82,58,233,234,57,81,130,87,132,236,63,60,239,135,84,48,227,139,88,91,136,224,51,230,53,93,142,141,94,54,229,225,50,90,137,138,89,49,226,55,228,140,95,92,143,231,52,80,131,235,56,59,232,128,83,134,85,61,238,237,62,86,133,158,77,37,246,245,38,78,157,72,155,243,32,35,240,152,75,47,252,148,71,68,151,255,44,249,42,66,145,146,65,41,250,31,204,164,119,116,167,207,28,201,26,114,161,162,113,25,202,174,125,21,198,197,22,126,173,120,171,195,16,19,192,168,123,96,179,219,8,11,216,176,99,182,101,13,222,221,14,102,181,209,2,106,185,186,105,1,210,7,212,188,111,108,191,215,4}, + {0,212,181,97,119,163,194,22,238,58,91,143,153,77,44,248,193,21,116,160,182,98,3,215,47,251,154,78,88,140,237,57,159,75,42,254,232,60,93,137,113,165,196,16,6,210,179,103,94,138,235,63,41,253,156,72,176,100,5,209,199,19,114,166,35,247,150,66,84,128,225,53,205,25,120,172,186,110,15,219,226,54,87,131,149,65,32,244,12,216,185,109,123,175,206,26,188,104,9,221,203,31,126,170,82,134,231,51,37,241,144,68,125,169,200,28,10,222,191,107,147,71,38,242,228,48,81,133,70,146,243,39,49,229,132,80,168,124,29,201,223,11,106,190,135,83,50,230,240,36,69,145,105,189,220,8,30,202,171,127,217,13,108,184,174,122,27,207,55,227,130,86,64,148,245,33,24,204,173,121,111,187,218,14,246,34,67,151,129,85,52,224,101,177,208,4,18,198,167,115,139,95,62,234,252,40,73,157,164,112,17,197,211,7,102,178,74,158,255,43,61,233,136,92,250,46,79,155,141,89,56,236,20,192,161,117,99,183,214,2,59,239,142,90,76,152,249,45,213,1,96,180,162,118,23,195}, + {0,213,183,98,115,166,196,17,230,51,81,132,149,64,34,247,209,4,102,179,162,119,21,192,55,226,128,85,68,145,243,38,191,106,8,221,204,25,123,174,89,140,238,59,42,255,157,72,110,187,217,12,29,200,170,127,136,93,63,234,251,46,76,153,99,182,212,1,16,197,167,114,133,80,50,231,246,35,65,148,178,103,5,208,193,20,118,163,84,129,227,54,39,242,144,69,220,9,107,190,175,122,24,205,58,239,141,88,73,156,254,43,13,216,186,111,126,171,201,28,235,62,92,137,152,77,47,250,198,19,113,164,181,96,2,215,32,245,151,66,83,134,228,49,23,194,160,117,100,177,211,6,241,36,70,147,130,87,53,224,121,172,206,27,10,223,189,104,159,74,40,253,236,57,91,142,168,125,31,202,219,14,108,185,78,155,249,44,61,232,138,95,165,112,18,199,214,3,97,180,67,150,244,33,48,229,135,82,116,161,195,22,7,210,176,101,146,71,37,240,225,52,86,131,26,207,173,120,105,188,222,11,252,41,75,158,143,90,56,237,203,30,124,169,184,109,15,218,45,248,154,79,94,139,233,60}, + {0,214,177,103,127,169,206,24,254,40,79,153,129,87,48,230,225,55,80,134,158,72,47,249,31,201,174,120,96,182,209,7,223,9,110,184,160,118,17,199,33,247,144,70,94,136,239,57,62,232,143,89,65,151,240,38,192,22,113,167,191,105,14,216,163,117,18,196,220,10,109,187,93,139,236,58,34,244,147,69,66,148,243,37,61,235,140,90,188,106,13,219,195,21,114,164,124,170,205,27,3,213,178,100,130,84,51,229,253,43,76,154,157,75,44,250,226,52,83,133,99,181,210,4,28,202,173,123,91,141,234,60,36,242,149,67,165,115,20,194,218,12,107,189,186,108,11,221,197,19,116,162,68,146,245,35,59,237,138,92,132,82,53,227,251,45,74,156,122,172,203,29,5,211,180,98,101,179,212,2,26,204,171,125,155,77,42,252,228,50,85,131,248,46,73,159,135,81,54,224,6,208,183,97,121,175,200,30,25,207,168,126,102,176,215,1,231,49,86,128,152,78,41,255,39,241,150,64,88,142,233,63,217,15,104,190,166,112,23,193,198,16,119,161,185,111,8,222,56,238,137,95,71,145,246,32}, + {0,215,179,100,123,172,200,31,246,33,69,146,141,90,62,233,241,38,66,149,138,93,57,238,7,208,180,99,124,171,207,24,255,40,76,155,132,83,55,224,9,222,186,109,114,165,193,22,14,217,189,106,117,162,198,17,248,47,75,156,131,84,48,231,227,52,80,135,152,79,43,252,21,194,166,113,110,185,221,10,18,197,161,118,105,190,218,13,228,51,87,128,159,72,44,251,28,203,175,120,103,176,212,3,234,61,89,142,145,70,34,245,237,58,94,137,150,65,37,242,27,204,168,127,96,183,211,4,219,12,104,191,160,119,19,196,45,250,158,73,86,129,229,50,42,253,153,78,81,134,226,53,220,11,111,184,167,112,20,195,36,243,151,64,95,136,236,59,210,5,97,182,169,126,26,205,213,2,102,177,174,121,29,202,35,244,144,71,88,143,235,60,56,239,139,92,67,148,240,39,206,25,125,170,181,98,6,209,201,30,122,173,178,101,1,214,63,232,140,91,68,147,247,32,199,16,116,163,188,107,15,216,49,230,130,85,74,157,249,46,54,225,133,82,77,154,254,41,192,23,115,164,187,108,8,223}, + {0,216,173,117,71,159,234,50,142,86,35,251,201,17,100,188,1,217,172,116,70,158,235,51,143,87,34,250,200,16,101,189,2,218,175,119,69,157,232,48,140,84,33,249,203,19,102,190,3,219,174,118,68,156,233,49,141,85,32,248,202,18,103,191,4,220,169,113,67,155,238,54,138,82,39,255,205,21,96,184,5,221,168,112,66,154,239,55,139,83,38,254,204,20,97,185,6,222,171,115,65,153,236,52,136,80,37,253,207,23,98,186,7,223,170,114,64,152,237,53,137,81,36,252,206,22,99,187,8,208,165,125,79,151,226,58,134,94,43,243,193,25,108,180,9,209,164,124,78,150,227,59,135,95,42,242,192,24,109,181,10,210,167,127,77,149,224,56,132,92,41,241,195,27,110,182,11,211,166,126,76,148,225,57,133,93,40,240,194,26,111,183,12,212,161,121,75,147,230,62,130,90,47,247,197,29,104,176,13,213,160,120,74,146,231,63,131,91,46,246,196,28,105,177,14,214,163,123,73,145,228,60,128,88,45,245,199,31,106,178,15,215,162,122,72,144,229,61,129,89,44,244,198,30,107,179}, + {0,217,175,118,67,154,236,53,134,95,41,240,197,28,106,179,17,200,190,103,82,139,253,36,151,78,56,225,212,13,123,162,34,251,141,84,97,184,206,23,164,125,11,210,231,62,72,145,51,234,156,69,112,169,223,6,181,108,26,195,246,47,89,128,68,157,235,50,7,222,168,113,194,27,109,180,129,88,46,247,85,140,250,35,22,207,185,96,211,10,124,165,144,73,63,230,102,191,201,16,37,252,138,83,224,57,79,150,163,122,12,213,119,174,216,1,52,237,155,66,241,40,94,135,178,107,29,196,136,81,39,254,203,18,100,189,14,215,161,120,77,148,226,59,153,64,54,239,218,3,117,172,31,198,176,105,92,133,243,42,170,115,5,220,233,48,70,159,44,245,131,90,111,182,192,25,187,98,20,205,248,33,87,142,61,228,146,75,126,167,209,8,204,21,99,186,143,86,32,249,74,147,229,60,9,208,166,127,221,4,114,171,158,71,49,232,91,130,244,45,24,193,183,110,238,55,65,152,173,116,2,219,104,177,199,30,43,242,132,93,255,38,80,137,188,101,19,202,121,160,214,15,58,227,149,76}, + {0,218,169,115,79,149,230,60,158,68,55,237,209,11,120,162,33,251,136,82,110,180,199,29,191,101,22,204,240,42,89,131,66,152,235,49,13,215,164,126,220,6,117,175,147,73,58,224,99,185,202,16,44,246,133,95,253,39,84,142,178,104,27,193,132,94,45,247,203,17,98,184,26,192,179,105,85,143,252,38,165,127,12,214,234,48,67,153,59,225,146,72,116,174,221,7,198,28,111,181,137,83,32,250,88,130,241,43,23,205,190,100,231,61,78,148,168,114,1,219,121,163,208,10,54,236,159,69,21,207,188,102,90,128,243,41,139,81,34,248,196,30,109,183,52,238,157,71,123,161,210,8,170,112,3,217,229,63,76,150,87,141,254,36,24,194,177,107,201,19,96,186,134,92,47,245,118,172,223,5,57,227,144,74,232,50,65,155,167,125,14,212,145,75,56,226,222,4,119,173,15,213,166,124,64,154,233,51,176,106,25,195,255,37,86,140,46,244,135,93,97,187,200,18,211,9,122,160,156,70,53,239,77,151,228,62,2,216,171,113,242,40,91,129,189,103,20,206,108,182,197,31,35,249,138,80}, + {0,219,171,112,75,144,224,59,150,77,61,230,221,6,118,173,49,234,154,65,122,161,209,10,167,124,12,215,236,55,71,156,98,185,201,18,41,242,130,89,244,47,95,132,191,100,20,207,83,136,248,35,24,195,179,104,197,30,110,181,142,85,37,254,196,31,111,180,143,84,36,255,82,137,249,34,25,194,178,105,245,46,94,133,190,101,21,206,99,184,200,19,40,243,131,88,166,125,13,214,237,54,70,157,48,235,155,64,123,160,208,11,151,76,60,231,220,7,119,172,1,218,170,113,74,145,225,58,149,78,62,229,222,5,117,174,3,216,168,115,72,147,227,56,164,127,15,212,239,52,68,159,50,233,153,66,121,162,210,9,247,44,92,135,188,103,23,204,97,186,202,17,42,241,129,90,198,29,109,182,141,86,38,253,80,139,251,32,27,192,176,107,81,138,250,33,26,193,177,106,199,28,108,183,140,87,39,252,96,187,203,16,43,240,128,91,246,45,93,134,189,102,22,205,51,232,152,67,120,163,211,8,165,126,14,213,238,53,69,158,2,217,169,114,73,146,226,57,148,79,63,228,223,4,116,175}, + {0,220,165,121,87,139,242,46,174,114,11,215,249,37,92,128,65,157,228,56,22,202,179,111,239,51,74,150,184,100,29,193,130,94,39,251,213,9,112,172,44,240,137,85,123,167,222,2,195,31,102,186,148,72,49,237,109,177,200,20,58,230,159,67,25,197,188,96,78,146,235,55,183,107,18,206,224,60,69,153,88,132,253,33,15,211,170,118,246,42,83,143,161,125,4,216,155,71,62,226,204,16,105,181,53,233,144,76,98,190,199,27,218,6,127,163,141,81,40,244,116,168,209,13,35,255,134,90,50,238,151,75,101,185,192,28,156,64,57,229,203,23,110,178,115,175,214,10,36,248,129,93,221,1,120,164,138,86,47,243,176,108,21,201,231,59,66,158,30,194,187,103,73,149,236,48,241,45,84,136,166,122,3,223,95,131,250,38,8,212,173,113,43,247,142,82,124,160,217,5,133,89,32,252,210,14,119,171,106,182,207,19,61,225,152,68,196,24,97,189,147,79,54,234,169,117,12,208,254,34,91,135,7,219,162,126,80,140,245,41,232,52,77,145,191,99,26,198,70,154,227,63,17,205,180,104}, + {0,221,167,122,83,142,244,41,166,123,1,220,245,40,82,143,81,140,246,43,2,223,165,120,247,42,80,141,164,121,3,222,162,127,5,216,241,44,86,139,4,217,163,126,87,138,240,45,243,46,84,137,160,125,7,218,85,136,242,47,6,219,161,124,89,132,254,35,10,215,173,112,255,34,88,133,172,113,11,214,8,213,175,114,91,134,252,33,174,115,9,212,253,32,90,135,251,38,92,129,168,117,15,210,93,128,250,39,14,211,169,116,170,119,13,208,249,36,94,131,12,209,171,118,95,130,248,37,178,111,21,200,225,60,70,155,20,201,179,110,71,154,224,61,227,62,68,153,176,109,23,202,69,152,226,63,22,203,177,108,16,205,183,106,67,158,228,57,182,107,17,204,229,56,66,159,65,156,230,59,18,207,181,104,231,58,64,157,180,105,19,206,235,54,76,145,184,101,31,194,77,144,234,55,30,195,185,100,186,103,29,192,233,52,78,147,28,193,187,102,79,146,232,53,73,148,238,51,26,199,189,96,239,50,72,149,188,97,27,198,24,197,191,98,75,150,236,49,190,99,25,196,237,48,74,151}, + {0,222,161,127,95,129,254,32,190,96,31,193,225,63,64,158,97,191,192,30,62,224,159,65,223,1,126,160,128,94,33,255,194,28,99,189,157,67,60,226,124,162,221,3,35,253,130,92,163,125,2,220,252,34,93,131,29,195,188,98,66,156,227,61,153,71,56,230,198,24,103,185,39,249,134,88,120,166,217,7,248,38,89,135,167,121,6,216,70,152,231,57,25,199,184,102,91,133,250,36,4,218,165,123,229,59,68,154,186,100,27,197,58,228,155,69,101,187,196,26,132,90,37,251,219,5,122,164,47,241,142,80,112,174,209,15,145,79,48,238,206,16,111,177,78,144,239,49,17,207,176,110,240,46,81,143,175,113,14,208,237,51,76,146,178,108,19,205,83,141,242,44,12,210,173,115,140,82,45,243,211,13,114,172,50,236,147,77,109,179,204,18,182,104,23,201,233,55,72,150,8,214,169,119,87,137,246,40,215,9,118,168,136,86,41,247,105,183,200,22,54,232,151,73,116,170,213,11,43,245,138,84,202,20,107,181,149,75,52,234,21,203,180,106,74,148,235,53,171,117,10,212,244,42,85,139}, + {0,223,163,124,91,132,248,39,182,105,21,202,237,50,78,145,113,174,210,13,42,245,137,86,199,24,100,187,156,67,63,224,226,61,65,158,185,102,26,197,84,139,247,40,15,208,172,115,147,76,48,239,200,23,107,180,37,250,134,89,126,161,221,2,217,6,122,165,130,93,33,254,111,176,204,19,52,235,151,72,168,119,11,212,243,44,80,143,30,193,189,98,69,154,230,57,59,228,152,71,96,191,195,28,141,82,46,241,214,9,117,170,74,149,233,54,17,206,178,109,252,35,95,128,167,120,4,219,175,112,12,211,244,43,87,136,25,198,186,101,66,157,225,62,222,1,125,162,133,90,38,249,104,183,203,20,51,236,144,79,77,146,238,49,22,201,181,106,251,36,88,135,160,127,3,220,60,227,159,64,103,184,196,27,138,85,41,246,209,14,114,173,118,169,213,10,45,242,142,81,192,31,99,188,155,68,56,231,7,216,164,123,92,131,255,32,177,110,18,205,234,53,73,150,148,75,55,232,207,16,108,179,34,253,129,94,121,166,218,5,229,58,70,153,190,97,29,194,83,140,240,47,8,215,171,116}, + {0,224,221,61,167,71,122,154,83,179,142,110,244,20,41,201,166,70,123,155,1,225,220,60,245,21,40,200,82,178,143,111,81,177,140,108,246,22,43,203,2,226,223,63,165,69,120,152,247,23,42,202,80,176,141,109,164,68,121,153,3,227,222,62,162,66,127,159,5,229,216,56,241,17,44,204,86,182,139,107,4,228,217,57,163,67,126,158,87,183,138,106,240,16,45,205,243,19,46,206,84,180,137,105,160,64,125,157,7,231,218,58,85,181,136,104,242,18,47,207,6,230,219,59,161,65,124,156,89,185,132,100,254,30,35,195,10,234,215,55,173,77,112,144,255,31,34,194,88,184,133,101,172,76,113,145,11,235,214,54,8,232,213,53,175,79,114,146,91,187,134,102,252,28,33,193,174,78,115,147,9,233,212,52,253,29,32,192,90,186,135,103,251,27,38,198,92,188,129,97,168,72,117,149,15,239,210,50,93,189,128,96,250,26,39,199,14,238,211,51,169,73,116,148,170,74,119,151,13,237,208,48,249,25,36,196,94,190,131,99,12,236,209,49,171,75,118,150,95,191,130,98,248,24,37,197}, + {0,225,223,62,163,66,124,157,91,186,132,101,248,25,39,198,182,87,105,136,21,244,202,43,237,12,50,211,78,175,145,112,113,144,174,79,210,51,13,236,42,203,245,20,137,104,86,183,199,38,24,249,100,133,187,90,156,125,67,162,63,222,224,1,226,3,61,220,65,160,158,127,185,88,102,135,26,251,197,36,84,181,139,106,247,22,40,201,15,238,208,49,172,77,115,146,147,114,76,173,48,209,239,14,200,41,23,246,107,138,180,85,37,196,250,27,134,103,89,184,126,159,161,64,221,60,2,227,217,56,6,231,122,155,165,68,130,99,93,188,33,192,254,31,111,142,176,81,204,45,19,242,52,213,235,10,151,118,72,169,168,73,119,150,11,234,212,53,243,18,44,205,80,177,143,110,30,255,193,32,189,92,98,131,69,164,154,123,230,7,57,216,59,218,228,5,152,121,71,166,96,129,191,94,195,34,28,253,141,108,82,179,46,207,241,16,214,55,9,232,117,148,170,75,74,171,149,116,233,8,54,215,17,240,206,47,178,83,109,140,252,29,35,194,95,190,128,97,167,70,120,153,4,229,219,58}, + {0,226,217,59,175,77,118,148,67,161,154,120,236,14,53,215,134,100,95,189,41,203,240,18,197,39,28,254,106,136,179,81,17,243,200,42,190,92,103,133,82,176,139,105,253,31,36,198,151,117,78,172,56,218,225,3,212,54,13,239,123,153,162,64,34,192,251,25,141,111,84,182,97,131,184,90,206,44,23,245,164,70,125,159,11,233,210,48,231,5,62,220,72,170,145,115,51,209,234,8,156,126,69,167,112,146,169,75,223,61,6,228,181,87,108,142,26,248,195,33,246,20,47,205,89,187,128,98,68,166,157,127,235,9,50,208,7,229,222,60,168,74,113,147,194,32,27,249,109,143,180,86,129,99,88,186,46,204,247,21,85,183,140,110,250,24,35,193,22,244,207,45,185,91,96,130,211,49,10,232,124,158,165,71,144,114,73,171,63,221,230,4,102,132,191,93,201,43,16,242,37,199,252,30,138,104,83,177,224,2,57,219,79,173,150,116,163,65,122,152,12,238,213,55,119,149,174,76,216,58,1,227,52,214,237,15,155,121,66,160,241,19,40,202,94,188,135,101,178,80,107,137,29,255,196,38}, + {0,227,219,56,171,72,112,147,75,168,144,115,224,3,59,216,150,117,77,174,61,222,230,5,221,62,6,229,118,149,173,78,49,210,234,9,154,121,65,162,122,153,161,66,209,50,10,233,167,68,124,159,12,239,215,52,236,15,55,212,71,164,156,127,98,129,185,90,201,42,18,241,41,202,242,17,130,97,89,186,244,23,47,204,95,188,132,103,191,92,100,135,20,247,207,44,83,176,136,107,248,27,35,192,24,251,195,32,179,80,104,139,197,38,30,253,110,141,181,86,142,109,85,182,37,198,254,29,196,39,31,252,111,140,180,87,143,108,84,183,36,199,255,28,82,177,137,106,249,26,34,193,25,250,194,33,178,81,105,138,245,22,46,205,94,189,133,102,190,93,101,134,21,246,206,45,99,128,184,91,200,43,19,240,40,203,243,16,131,96,88,187,166,69,125,158,13,238,214,53,237,14,54,213,70,165,157,126,48,211,235,8,155,120,64,163,123,152,160,67,208,51,11,232,151,116,76,175,60,223,231,4,220,63,7,228,119,148,172,79,1,226,218,57,170,73,113,146,74,169,145,114,225,2,58,217}, + {0,228,213,49,183,83,98,134,115,151,166,66,196,32,17,245,230,2,51,215,81,181,132,96,149,113,64,164,34,198,247,19,209,53,4,224,102,130,179,87,162,70,119,147,21,241,192,36,55,211,226,6,128,100,85,177,68,160,145,117,243,23,38,194,191,91,106,142,8,236,221,57,204,40,25,253,123,159,174,74,89,189,140,104,238,10,59,223,42,206,255,27,157,121,72,172,110,138,187,95,217,61,12,232,29,249,200,44,170,78,127,155,136,108,93,185,63,219,234,14,251,31,46,202,76,168,153,125,99,135,182,82,212,48,1,229,16,244,197,33,167,67,114,150,133,97,80,180,50,214,231,3,246,18,35,199,65,165,148,112,178,86,103,131,5,225,208,52,193,37,20,240,118,146,163,71,84,176,129,101,227,7,54,210,39,195,242,22,144,116,69,161,220,56,9,237,107,143,190,90,175,75,122,158,24,252,205,41,58,222,239,11,141,105,88,188,73,173,156,120,254,26,43,207,13,233,216,60,186,94,111,139,126,154,171,79,201,45,28,248,235,15,62,218,92,184,137,109,152,124,77,169,47,203,250,30}, + {0,229,215,50,179,86,100,129,123,158,172,73,200,45,31,250,246,19,33,196,69,160,146,119,141,104,90,191,62,219,233,12,241,20,38,195,66,167,149,112,138,111,93,184,57,220,238,11,7,226,208,53,180,81,99,134,124,153,171,78,207,42,24,253,255,26,40,205,76,169,155,126,132,97,83,182,55,210,224,5,9,236,222,59,186,95,109,136,114,151,165,64,193,36,22,243,14,235,217,60,189,88,106,143,117,144,162,71,198,35,17,244,248,29,47,202,75,174,156,121,131,102,84,177,48,213,231,2,227,6,52,209,80,181,135,98,152,125,79,170,43,206,252,25,21,240,194,39,166,67,113,148,110,139,185,92,221,56,10,239,18,247,197,32,161,68,118,147,105,140,190,91,218,63,13,232,228,1,51,214,87,178,128,101,159,122,72,173,44,201,251,30,28,249,203,46,175,74,120,157,103,130,176,85,212,49,3,230,234,15,61,216,89,188,142,107,145,116,70,163,34,199,245,16,237,8,58,223,94,187,137,108,150,115,65,164,37,192,242,23,27,254,204,41,168,77,127,154,96,133,183,82,211,54,4,225}, + {0,230,209,55,191,89,110,136,99,133,178,84,220,58,13,235,198,32,23,241,121,159,168,78,165,67,116,146,26,252,203,45,145,119,64,166,46,200,255,25,242,20,35,197,77,171,156,122,87,177,134,96,232,14,57,223,52,210,229,3,139,109,90,188,63,217,238,8,128,102,81,183,92,186,141,107,227,5,50,212,249,31,40,206,70,160,151,113,154,124,75,173,37,195,244,18,174,72,127,153,17,247,192,38,205,43,28,250,114,148,163,69,104,142,185,95,215,49,6,224,11,237,218,60,180,82,101,131,126,152,175,73,193,39,16,246,29,251,204,42,162,68,115,149,184,94,105,143,7,225,214,48,219,61,10,236,100,130,181,83,239,9,62,216,80,182,129,103,140,106,93,187,51,213,226,4,41,207,248,30,150,112,71,161,74,172,155,125,245,19,36,194,65,167,144,118,254,24,47,201,34,196,243,21,157,123,76,170,135,97,86,176,56,222,233,15,228,2,53,211,91,189,138,108,208,54,1,231,111,137,190,88,179,85,98,132,12,234,221,59,22,240,199,33,169,79,120,158,117,147,164,66,202,44,27,253}, + {0,231,211,52,187,92,104,143,107,140,184,95,208,55,3,228,214,49,5,226,109,138,190,89,189,90,110,137,6,225,213,50,177,86,98,133,10,237,217,62,218,61,9,238,97,134,178,85,103,128,180,83,220,59,15,232,12,235,223,56,183,80,100,131,127,152,172,75,196,35,23,240,20,243,199,32,175,72,124,155,169,78,122,157,18,245,193,38,194,37,17,246,121,158,170,77,206,41,29,250,117,146,166,65,165,66,118,145,30,249,205,42,24,255,203,44,163,68,112,151,115,148,160,71,200,47,27,252,254,25,45,202,69,162,150,113,149,114,70,161,46,201,253,26,40,207,251,28,147,116,64,167,67,164,144,119,248,31,43,204,79,168,156,123,244,19,39,192,36,195,247,16,159,120,76,171,153,126,74,173,34,197,241,22,242,21,33,198,73,174,154,125,129,102,82,181,58,221,233,14,234,13,57,222,81,182,130,101,87,176,132,99,236,11,63,216,60,219,239,8,135,96,84,179,48,215,227,4,139,108,88,191,91,188,136,111,224,7,51,212,230,1,53,210,93,186,142,105,141,106,94,185,54,209,229,2}, + {0,232,205,37,135,111,74,162,19,251,222,54,148,124,89,177,38,206,235,3,161,73,108,132,53,221,248,16,178,90,127,151,76,164,129,105,203,35,6,238,95,183,146,122,216,48,21,253,106,130,167,79,237,5,32,200,121,145,180,92,254,22,51,219,152,112,85,189,31,247,210,58,139,99,70,174,12,228,193,41,190,86,115,155,57,209,244,28,173,69,96,136,42,194,231,15,212,60,25,241,83,187,158,118,199,47,10,226,64,168,141,101,242,26,63,215,117,157,184,80,225,9,44,196,102,142,171,67,45,197,224,8,170,66,103,143,62,214,243,27,185,81,116,156,11,227,198,46,140,100,65,169,24,240,213,61,159,119,82,186,97,137,172,68,230,14,43,195,114,154,191,87,245,29,56,208,71,175,138,98,192,40,13,229,84,188,153,113,211,59,30,246,181,93,120,144,50,218,255,23,166,78,107,131,33,201,236,4,147,123,94,182,20,252,217,49,128,104,77,165,7,239,202,34,249,17,52,220,126,150,179,91,234,2,39,207,109,133,160,72,223,55,18,250,88,176,149,125,204,36,1,233,75,163,134,110}, + {0,233,207,38,131,106,76,165,27,242,212,61,152,113,87,190,54,223,249,16,181,92,122,147,45,196,226,11,174,71,97,136,108,133,163,74,239,6,32,201,119,158,184,81,244,29,59,210,90,179,149,124,217,48,22,255,65,168,142,103,194,43,13,228,216,49,23,254,91,178,148,125,195,42,12,229,64,169,143,102,238,7,33,200,109,132,162,75,245,28,58,211,118,159,185,80,180,93,123,146,55,222,248,17,175,70,96,137,44,197,227,10,130,107,77,164,1,232,206,39,153,112,86,191,26,243,213,60,173,68,98,139,46,199,225,8,182,95,121,144,53,220,250,19,155,114,84,189,24,241,215,62,128,105,79,166,3,234,204,37,193,40,14,231,66,171,141,100,218,51,21,252,89,176,150,127,247,30,56,209,116,157,187,82,236,5,35,202,111,134,160,73,117,156,186,83,246,31,57,208,110,135,161,72,237,4,34,203,67,170,140,101,192,41,15,230,88,177,151,126,219,50,20,253,25,240,214,63,154,115,85,188,2,235,205,36,129,104,78,167,47,198,224,9,172,69,99,138,52,221,251,18,183,94,120,145}, + {0,234,201,35,143,101,70,172,3,233,202,32,140,102,69,175,6,236,207,37,137,99,64,170,5,239,204,38,138,96,67,169,12,230,197,47,131,105,74,160,15,229,198,44,128,106,73,163,10,224,195,41,133,111,76,166,9,227,192,42,134,108,79,165,24,242,209,59,151,125,94,180,27,241,210,56,148,126,93,183,30,244,215,61,145,123,88,178,29,247,212,62,146,120,91,177,20,254,221,55,155,113,82,184,23,253,222,52,152,114,81,187,18,248,219,49,157,119,84,190,17,251,216,50,158,116,87,189,48,218,249,19,191,85,118,156,51,217,250,16,188,86,117,159,54,220,255,21,185,83,112,154,53,223,252,22,186,80,115,153,60,214,245,31,179,89,122,144,63,213,246,28,176,90,121,147,58,208,243,25,181,95,124,150,57,211,240,26,182,92,127,149,40,194,225,11,167,77,110,132,43,193,226,8,164,78,109,135,46,196,231,13,161,75,104,130,45,199,228,14,162,72,107,129,36,206,237,7,171,65,98,136,39,205,238,4,168,66,97,139,34,200,235,1,173,71,100,142,33,203,232,2,174,68,103,141}, + {0,235,203,32,139,96,64,171,11,224,192,43,128,107,75,160,22,253,221,54,157,118,86,189,29,246,214,61,150,125,93,182,44,199,231,12,167,76,108,135,39,204,236,7,172,71,103,140,58,209,241,26,177,90,122,145,49,218,250,17,186,81,113,154,88,179,147,120,211,56,24,243,83,184,152,115,216,51,19,248,78,165,133,110,197,46,14,229,69,174,142,101,206,37,5,238,116,159,191,84,255,20,52,223,127,148,180,95,244,31,63,212,98,137,169,66,233,2,34,201,105,130,162,73,226,9,41,194,176,91,123,144,59,208,240,27,187,80,112,155,48,219,251,16,166,77,109,134,45,198,230,13,173,70,102,141,38,205,237,6,156,119,87,188,23,252,220,55,151,124,92,183,28,247,215,60,138,97,65,170,1,234,202,33,129,106,74,161,10,225,193,42,232,3,35,200,99,136,168,67,227,8,40,195,104,131,163,72,254,21,53,222,117,158,190,85,245,30,62,213,126,149,181,94,196,47,15,228,79,164,132,111,207,36,4,239,68,175,143,100,210,57,25,242,89,178,146,121,217,50,18,249,82,185,153,114}, + {0,236,197,41,151,123,82,190,51,223,246,26,164,72,97,141,102,138,163,79,241,29,52,216,85,185,144,124,194,46,7,235,204,32,9,229,91,183,158,114,255,19,58,214,104,132,173,65,170,70,111,131,61,209,248,20,153,117,92,176,14,226,203,39,133,105,64,172,18,254,215,59,182,90,115,159,33,205,228,8,227,15,38,202,116,152,177,93,208,60,21,249,71,171,130,110,73,165,140,96,222,50,27,247,122,150,191,83,237,1,40,196,47,195,234,6,184,84,125,145,28,240,217,53,139,103,78,162,23,251,210,62,128,108,69,169,36,200,225,13,179,95,118,154,113,157,180,88,230,10,35,207,66,174,135,107,213,57,16,252,219,55,30,242,76,160,137,101,232,4,45,193,127,147,186,86,189,81,120,148,42,198,239,3,142,98,75,167,25,245,220,48,146,126,87,187,5,233,192,44,161,77,100,136,54,218,243,31,244,24,49,221,99,143,166,74,199,43,2,238,80,188,149,121,94,178,155,119,201,37,12,224,109,129,168,68,250,22,63,211,56,212,253,17,175,67,106,134,11,231,206,34,156,112,89,181}, + {0,237,199,42,147,126,84,185,59,214,252,17,168,69,111,130,118,155,177,92,229,8,34,207,77,160,138,103,222,51,25,244,236,1,43,198,127,146,184,85,215,58,16,253,68,169,131,110,154,119,93,176,9,228,206,35,161,76,102,139,50,223,245,24,197,40,2,239,86,187,145,124,254,19,57,212,109,128,170,71,179,94,116,153,32,205,231,10,136,101,79,162,27,246,220,49,41,196,238,3,186,87,125,144,18,255,213,56,129,108,70,171,95,178,152,117,204,33,11,230,100,137,163,78,247,26,48,221,151,122,80,189,4,233,195,46,172,65,107,134,63,210,248,21,225,12,38,203,114,159,181,88,218,55,29,240,73,164,142,99,123,150,188,81,232,5,47,194,64,173,135,106,211,62,20,249,13,224,202,39,158,115,89,180,54,219,241,28,165,72,98,143,82,191,149,120,193,44,6,235,105,132,174,67,250,23,61,208,36,201,227,14,183,90,112,157,31,242,216,53,140,97,75,166,190,83,121,148,45,192,234,7,133,104,66,175,22,251,209,60,200,37,15,226,91,182,156,113,243,30,52,217,96,141,167,74}, + {0,238,193,47,159,113,94,176,35,205,226,12,188,82,125,147,70,168,135,105,217,55,24,246,101,139,164,74,250,20,59,213,140,98,77,163,19,253,210,60,175,65,110,128,48,222,241,31,202,36,11,229,85,187,148,122,233,7,40,198,118,152,183,89,5,235,196,42,154,116,91,181,38,200,231,9,185,87,120,150,67,173,130,108,220,50,29,243,96,142,161,79,255,17,62,208,137,103,72,166,22,248,215,57,170,68,107,133,53,219,244,26,207,33,14,224,80,190,145,127,236,2,45,195,115,157,178,92,10,228,203,37,149,123,84,186,41,199,232,6,182,88,119,153,76,162,141,99,211,61,18,252,111,129,174,64,240,30,49,223,134,104,71,169,25,247,216,54,165,75,100,138,58,212,251,21,192,46,1,239,95,177,158,112,227,13,34,204,124,146,189,83,15,225,206,32,144,126,81,191,44,194,237,3,179,93,114,156,73,167,136,102,214,56,23,249,106,132,171,69,245,27,52,218,131,109,66,172,28,242,221,51,160,78,97,143,63,209,254,16,197,43,4,234,90,180,155,117,230,8,39,201,121,151,184,86}, + {0,239,195,44,155,116,88,183,43,196,232,7,176,95,115,156,86,185,149,122,205,34,14,225,125,146,190,81,230,9,37,202,172,67,111,128,55,216,244,27,135,104,68,171,28,243,223,48,250,21,57,214,97,142,162,77,209,62,18,253,74,165,137,102,69,170,134,105,222,49,29,242,110,129,173,66,245,26,54,217,19,252,208,63,136,103,75,164,56,215,251,20,163,76,96,143,233,6,42,197,114,157,177,94,194,45,1,238,89,182,154,117,191,80,124,147,36,203,231,8,148,123,87,184,15,224,204,35,138,101,73,166,17,254,210,61,161,78,98,141,58,213,249,22,220,51,31,240,71,168,132,107,247,24,52,219,108,131,175,64,38,201,229,10,189,82,126,145,13,226,206,33,150,121,85,186,112,159,179,92,235,4,40,199,91,180,152,119,192,47,3,236,207,32,12,227,84,187,151,120,228,11,39,200,127,144,188,83,153,118,90,181,2,237,193,46,178,93,113,158,41,198,234,5,99,140,160,79,248,23,59,212,72,167,139,100,211,60,16,255,53,218,246,25,174,65,109,130,30,241,221,50,133,106,70,169}, + {0,240,253,13,231,23,26,234,211,35,46,222,52,196,201,57,187,75,70,182,92,172,161,81,104,152,149,101,143,127,114,130,107,155,150,102,140,124,113,129,184,72,69,181,95,175,162,82,208,32,45,221,55,199,202,58,3,243,254,14,228,20,25,233,214,38,43,219,49,193,204,60,5,245,248,8,226,18,31,239,109,157,144,96,138,122,119,135,190,78,67,179,89,169,164,84,189,77,64,176,90,170,167,87,110,158,147,99,137,121,116,132,6,246,251,11,225,17,28,236,213,37,40,216,50,194,207,63,177,65,76,188,86,166,171,91,98,146,159,111,133,117,120,136,10,250,247,7,237,29,16,224,217,41,36,212,62,206,195,51,218,42,39,215,61,205,192,48,9,249,244,4,238,30,19,227,97,145,156,108,134,118,123,139,178,66,79,191,85,165,168,88,103,151,154,106,128,112,125,141,180,68,73,185,83,163,174,94,220,44,33,209,59,203,198,54,15,255,242,2,232,24,21,229,12,252,241,1,235,27,22,230,223,47,34,210,56,200,197,53,183,71,74,186,80,160,173,93,100,148,153,105,131,115,126,142}, + {0,241,255,14,227,18,28,237,219,42,36,213,56,201,199,54,171,90,84,165,72,185,183,70,112,129,143,126,147,98,108,157,75,186,180,69,168,89,87,166,144,97,111,158,115,130,140,125,224,17,31,238,3,242,252,13,59,202,196,53,216,41,39,214,150,103,105,152,117,132,138,123,77,188,178,67,174,95,81,160,61,204,194,51,222,47,33,208,230,23,25,232,5,244,250,11,221,44,34,211,62,207,193,48,6,247,249,8,229,20,26,235,118,135,137,120,149,100,106,155,173,92,82,163,78,191,177,64,49,192,206,63,210,35,45,220,234,27,21,228,9,248,246,7,154,107,101,148,121,136,134,119,65,176,190,79,162,83,93,172,122,139,133,116,153,104,102,151,161,80,94,175,66,179,189,76,209,32,46,223,50,195,205,60,10,251,245,4,233,24,22,231,167,86,88,169,68,181,187,74,124,141,131,114,159,110,96,145,12,253,243,2,239,30,16,225,215,38,40,217,52,197,203,58,236,29,19,226,15,254,240,1,55,198,200,57,212,37,43,218,71,182,184,73,164,85,91,170,156,109,99,146,127,142,128,113}, + {0,242,249,11,239,29,22,228,195,49,58,200,44,222,213,39,155,105,98,144,116,134,141,127,88,170,161,83,183,69,78,188,43,217,210,32,196,54,61,207,232,26,17,227,7,245,254,12,176,66,73,187,95,173,166,84,115,129,138,120,156,110,101,151,86,164,175,93,185,75,64,178,149,103,108,158,122,136,131,113,205,63,52,198,34,208,219,41,14,252,247,5,225,19,24,234,125,143,132,118,146,96,107,153,190,76,71,181,81,163,168,90,230,20,31,237,9,251,240,2,37,215,220,46,202,56,51,193,172,94,85,167,67,177,186,72,111,157,150,100,128,114,121,139,55,197,206,60,216,42,33,211,244,6,13,255,27,233,226,16,135,117,126,140,104,154,145,99,68,182,189,79,171,89,82,160,28,238,229,23,243,1,10,248,223,45,38,212,48,194,201,59,250,8,3,241,21,231,236,30,57,203,192,50,214,36,47,221,97,147,152,106,142,124,119,133,162,80,91,169,77,191,180,70,209,35,40,218,62,204,199,53,18,224,235,25,253,15,4,246,74,184,179,65,165,87,92,174,137,123,112,130,102,148,159,109}, + {0,243,251,8,235,24,16,227,203,56,48,195,32,211,219,40,139,120,112,131,96,147,155,104,64,179,187,72,171,88,80,163,11,248,240,3,224,19,27,232,192,51,59,200,43,216,208,35,128,115,123,136,107,152,144,99,75,184,176,67,160,83,91,168,22,229,237,30,253,14,6,245,221,46,38,213,54,197,205,62,157,110,102,149,118,133,141,126,86,165,173,94,189,78,70,181,29,238,230,21,246,5,13,254,214,37,45,222,61,206,198,53,150,101,109,158,125,142,134,117,93,174,166,85,182,69,77,190,44,223,215,36,199,52,60,207,231,20,28,239,12,255,247,4,167,84,92,175,76,191,183,68,108,159,151,100,135,116,124,143,39,212,220,47,204,63,55,196,236,31,23,228,7,244,252,15,172,95,87,164,71,180,188,79,103,148,156,111,140,127,119,132,58,201,193,50,209,34,42,217,241,2,10,249,26,233,225,18,177,66,74,185,90,169,161,82,122,137,129,114,145,98,106,153,49,194,202,57,218,41,33,210,250,9,1,242,17,226,234,25,186,73,65,178,81,162,170,89,113,130,138,121,154,105,97,146}, + {0,244,245,1,247,3,2,246,243,7,6,242,4,240,241,5,251,15,14,250,12,248,249,13,8,252,253,9,255,11,10,254,235,31,30,234,28,232,233,29,24,236,237,25,239,27,26,238,16,228,229,17,231,19,18,230,227,23,22,226,20,224,225,21,203,63,62,202,60,200,201,61,56,204,205,57,207,59,58,206,48,196,197,49,199,51,50,198,195,55,54,194,52,192,193,53,32,212,213,33,215,35,34,214,211,39,38,210,36,208,209,37,219,47,46,218,44,216,217,45,40,220,221,41,223,43,42,222,139,127,126,138,124,136,137,125,120,140,141,121,143,123,122,142,112,132,133,113,135,115,114,134,131,119,118,130,116,128,129,117,96,148,149,97,151,99,98,150,147,103,102,146,100,144,145,101,155,111,110,154,108,152,153,109,104,156,157,105,159,107,106,158,64,180,181,65,183,67,66,182,179,71,70,178,68,176,177,69,187,79,78,186,76,184,185,77,72,188,189,73,191,75,74,190,171,95,94,170,92,168,169,93,88,172,173,89,175,91,90,174,80,164,165,81,167,83,82,166,163,87,86,162,84,160,161,85}, + {0,245,247,2,243,6,4,241,251,14,12,249,8,253,255,10,235,30,28,233,24,237,239,26,16,229,231,18,227,22,20,225,203,62,60,201,56,205,207,58,48,197,199,50,195,54,52,193,32,213,215,34,211,38,36,209,219,46,44,217,40,221,223,42,139,126,124,137,120,141,143,122,112,133,135,114,131,118,116,129,96,149,151,98,147,102,100,145,155,110,108,153,104,157,159,106,64,181,183,66,179,70,68,177,187,78,76,185,72,189,191,74,171,94,92,169,88,173,175,90,80,165,167,82,163,86,84,161,11,254,252,9,248,13,15,250,240,5,7,242,3,246,244,1,224,21,23,226,19,230,228,17,27,238,236,25,232,29,31,234,192,53,55,194,51,198,196,49,59,206,204,57,200,61,63,202,43,222,220,41,216,45,47,218,208,37,39,210,35,214,212,33,128,117,119,130,115,134,132,113,123,142,140,121,136,125,127,138,107,158,156,105,152,109,111,154,144,101,103,146,99,150,148,97,75,190,188,73,184,77,79,186,176,69,71,178,67,182,180,65,160,85,87,162,83,166,164,81,91,174,172,89,168,93,95,170}, + {0,246,241,7,255,9,14,248,227,21,18,228,28,234,237,27,219,45,42,220,36,210,213,35,56,206,201,63,199,49,54,192,171,93,90,172,84,162,165,83,72,190,185,79,183,65,70,176,112,134,129,119,143,121,126,136,147,101,98,148,108,154,157,107,75,189,186,76,180,66,69,179,168,94,89,175,87,161,166,80,144,102,97,151,111,153,158,104,115,133,130,116,140,122,125,139,224,22,17,231,31,233,238,24,3,245,242,4,252,10,13,251,59,205,202,60,196,50,53,195,216,46,41,223,39,209,214,32,150,96,103,145,105,159,152,110,117,131,132,114,138,124,123,141,77,187,188,74,178,68,67,181,174,88,95,169,81,167,160,86,61,203,204,58,194,52,51,197,222,40,47,217,33,215,208,38,230,16,23,225,25,239,232,30,5,243,244,2,250,12,11,253,221,43,44,218,34,212,211,37,62,200,207,57,193,55,48,198,6,240,247,1,249,15,8,254,229,19,20,226,26,236,235,29,118,128,135,113,137,127,120,142,149,99,100,146,106,156,155,109,173,91,92,170,82,164,163,85,78,184,191,73,177,71,64,182}, + {0,247,243,4,251,12,8,255,235,28,24,239,16,231,227,20,203,60,56,207,48,199,195,52,32,215,211,36,219,44,40,223,139,124,120,143,112,135,131,116,96,151,147,100,155,108,104,159,64,183,179,68,187,76,72,191,171,92,88,175,80,167,163,84,11,252,248,15,240,7,3,244,224,23,19,228,27,236,232,31,192,55,51,196,59,204,200,63,43,220,216,47,208,39,35,212,128,119,115,132,123,140,136,127,107,156,152,111,144,103,99,148,75,188,184,79,176,71,67,180,160,87,83,164,91,172,168,95,22,225,229,18,237,26,30,233,253,10,14,249,6,241,245,2,221,42,46,217,38,209,213,34,54,193,197,50,205,58,62,201,157,106,110,153,102,145,149,98,118,129,133,114,141,122,126,137,86,161,165,82,173,90,94,169,189,74,78,185,70,177,181,66,29,234,238,25,230,17,21,226,246,1,5,242,13,250,254,9,214,33,37,210,45,218,222,41,61,202,206,57,198,49,53,194,150,97,101,146,109,154,158,105,125,138,142,121,134,113,117,130,93,170,174,89,166,81,85,162,182,65,69,178,77,186,190,73}, + {0,248,237,21,199,63,42,210,147,107,126,134,84,172,185,65,59,195,214,46,252,4,17,233,168,80,69,189,111,151,130,122,118,142,155,99,177,73,92,164,229,29,8,240,34,218,207,55,77,181,160,88,138,114,103,159,222,38,51,203,25,225,244,12,236,20,1,249,43,211,198,62,127,135,146,106,184,64,85,173,215,47,58,194,16,232,253,5,68,188,169,81,131,123,110,150,154,98,119,143,93,165,176,72,9,241,228,28,206,54,35,219,161,89,76,180,102,158,139,115,50,202,223,39,245,13,24,224,197,61,40,208,2,250,239,23,86,174,187,67,145,105,124,132,254,6,19,235,57,193,212,44,109,149,128,120,170,82,71,191,179,75,94,166,116,140,153,97,32,216,205,53,231,31,10,242,136,112,101,157,79,183,162,90,27,227,246,14,220,36,49,201,41,209,196,60,238,22,3,251,186,66,87,175,125,133,144,104,18,234,255,7,213,45,56,192,129,121,108,148,70,190,171,83,95,167,178,74,152,96,117,141,204,52,33,217,11,243,230,30,100,156,137,113,163,91,78,182,247,15,26,226,48,200,221,37}, + {0,249,239,22,195,58,44,213,155,98,116,141,88,161,183,78,43,210,196,61,232,17,7,254,176,73,95,166,115,138,156,101,86,175,185,64,149,108,122,131,205,52,34,219,14,247,225,24,125,132,146,107,190,71,81,168,230,31,9,240,37,220,202,51,172,85,67,186,111,150,128,121,55,206,216,33,244,13,27,226,135,126,104,145,68,189,171,82,28,229,243,10,223,38,48,201,250,3,21,236,57,192,214,47,97,152,142,119,162,91,77,180,209,40,62,199,18,235,253,4,74,179,165,92,137,112,102,159,69,188,170,83,134,127,105,144,222,39,49,200,29,228,242,11,110,151,129,120,173,84,66,187,245,12,26,227,54,207,217,32,19,234,252,5,208,41,63,198,136,113,103,158,75,178,164,93,56,193,215,46,251,2,20,237,163,90,76,181,96,153,143,118,233,16,6,255,42,211,197,60,114,139,157,100,177,72,94,167,194,59,45,212,1,248,238,23,89,160,182,79,154,99,117,140,191,70,80,169,124,133,147,106,36,221,203,50,231,30,8,241,148,109,123,130,87,174,184,65,15,246,224,25,204,53,35,218}, + {0,250,233,19,207,53,38,220,131,121,106,144,76,182,165,95,27,225,242,8,212,46,61,199,152,98,113,139,87,173,190,68,54,204,223,37,249,3,16,234,181,79,92,166,122,128,147,105,45,215,196,62,226,24,11,241,174,84,71,189,97,155,136,114,108,150,133,127,163,89,74,176,239,21,6,252,32,218,201,51,119,141,158,100,184,66,81,171,244,14,29,231,59,193,210,40,90,160,179,73,149,111,124,134,217,35,48,202,22,236,255,5,65,187,168,82,142,116,103,157,194,56,43,209,13,247,228,30,216,34,49,203,23,237,254,4,91,161,178,72,148,110,125,135,195,57,42,208,12,246,229,31,64,186,169,83,143,117,102,156,238,20,7,253,33,219,200,50,109,151,132,126,162,88,75,177,245,15,28,230,58,192,211,41,118,140,159,101,185,67,80,170,180,78,93,167,123,129,146,104,55,205,222,36,248,2,17,235,175,85,70,188,96,154,137,115,44,214,197,63,227,25,10,240,130,120,107,145,77,183,164,94,1,251,232,18,206,52,39,221,153,99,112,138,86,172,191,69,26,224,243,9,213,47,60,198}, + {0,251,235,16,203,48,32,219,139,112,96,155,64,187,171,80,11,240,224,27,192,59,43,208,128,123,107,144,75,176,160,91,22,237,253,6,221,38,54,205,157,102,118,141,86,173,189,70,29,230,246,13,214,45,61,198,150,109,125,134,93,166,182,77,44,215,199,60,231,28,12,247,167,92,76,183,108,151,135,124,39,220,204,55,236,23,7,252,172,87,71,188,103,156,140,119,58,193,209,42,241,10,26,225,177,74,90,161,122,129,145,106,49,202,218,33,250,1,17,234,186,65,81,170,113,138,154,97,88,163,179,72,147,104,120,131,211,40,56,195,24,227,243,8,83,168,184,67,152,99,115,136,216,35,51,200,19,232,248,3,78,181,165,94,133,126,110,149,197,62,46,213,14,245,229,30,69,190,174,85,142,117,101,158,206,53,37,222,5,254,238,21,116,143,159,100,191,68,84,175,255,4,20,239,52,207,223,36,127,132,148,111,180,79,95,164,244,15,31,228,63,196,212,47,98,153,137,114,169,82,66,185,233,18,2,249,34,217,201,50,105,146,130,121,162,89,73,178,226,25,9,242,41,210,194,57}, + {0,252,229,25,215,43,50,206,179,79,86,170,100,152,129,125,123,135,158,98,172,80,73,181,200,52,45,209,31,227,250,6,246,10,19,239,33,221,196,56,69,185,160,92,146,110,119,139,141,113,104,148,90,166,191,67,62,194,219,39,233,21,12,240,241,13,20,232,38,218,195,63,66,190,167,91,149,105,112,140,138,118,111,147,93,161,184,68,57,197,220,32,238,18,11,247,7,251,226,30,208,44,53,201,180,72,81,173,99,159,134,122,124,128,153,101,171,87,78,178,207,51,42,214,24,228,253,1,255,3,26,230,40,212,205,49,76,176,169,85,155,103,126,130,132,120,97,157,83,175,182,74,55,203,210,46,224,28,5,249,9,245,236,16,222,34,59,199,186,70,95,163,109,145,136,116,114,142,151,107,165,89,64,188,193,61,36,216,22,234,243,15,14,242,235,23,217,37,60,192,189,65,88,164,106,150,143,115,117,137,144,108,162,94,71,187,198,58,35,223,17,237,244,8,248,4,29,225,47,211,202,54,75,183,174,82,156,96,121,133,131,127,102,154,84,168,177,77,48,204,213,41,231,27,2,254}, + {0,253,231,26,211,46,52,201,187,70,92,161,104,149,143,114,107,150,140,113,184,69,95,162,208,45,55,202,3,254,228,25,214,43,49,204,5,248,226,31,109,144,138,119,190,67,89,164,189,64,90,167,110,147,137,116,6,251,225,28,213,40,50,207,177,76,86,171,98,159,133,120,10,247,237,16,217,36,62,195,218,39,61,192,9,244,238,19,97,156,134,123,178,79,85,168,103,154,128,125,180,73,83,174,220,33,59,198,15,242,232,21,12,241,235,22,223,34,56,197,183,74,80,173,100,153,131,126,127,130,152,101,172,81,75,182,196,57,35,222,23,234,240,13,20,233,243,14,199,58,32,221,175,82,72,181,124,129,155,102,169,84,78,179,122,135,157,96,18,239,245,8,193,60,38,219,194,63,37,216,17,236,246,11,121,132,158,99,170,87,77,176,206,51,41,212,29,224,250,7,117,136,146,111,166,91,65,188,165,88,66,191,118,139,145,108,30,227,249,4,205,48,42,215,24,229,255,2,203,54,44,209,163,94,68,185,112,141,151,106,115,142,148,105,160,93,71,186,200,53,47,210,27,230,252,1}, + {0,254,225,31,223,33,62,192,163,93,66,188,124,130,157,99,91,165,186,68,132,122,101,155,248,6,25,231,39,217,198,56,182,72,87,169,105,151,136,118,21,235,244,10,202,52,43,213,237,19,12,242,50,204,211,45,78,176,175,81,145,111,112,142,113,143,144,110,174,80,79,177,210,44,51,205,13,243,236,18,42,212,203,53,245,11,20,234,137,119,104,150,86,168,183,73,199,57,38,216,24,230,249,7,100,154,133,123,187,69,90,164,156,98,125,131,67,189,162,92,63,193,222,32,224,30,1,255,226,28,3,253,61,195,220,34,65,191,160,94,158,96,127,129,185,71,88,166,102,152,135,121,26,228,251,5,197,59,36,218,84,170,181,75,139,117,106,148,247,9,22,232,40,214,201,55,15,241,238,16,208,46,49,207,172,82,77,179,115,141,146,108,147,109,114,140,76,178,173,83,48,206,209,47,239,17,14,240,200,54,41,215,23,233,246,8,107,149,138,116,180,74,85,171,37,219,196,58,250,4,27,229,134,120,103,153,89,167,184,70,126,128,159,97,161,95,64,190,221,35,60,194,2,252,227,29}, + {0,255,227,28,219,36,56,199,171,84,72,183,112,143,147,108,75,180,168,87,144,111,115,140,224,31,3,252,59,196,216,39,150,105,117,138,77,178,174,81,61,194,222,33,230,25,5,250,221,34,62,193,6,249,229,26,118,137,149,106,173,82,78,177,49,206,210,45,234,21,9,246,154,101,121,134,65,190,162,93,122,133,153,102,161,94,66,189,209,46,50,205,10,245,233,22,167,88,68,187,124,131,159,96,12,243,239,16,215,40,52,203,236,19,15,240,55,200,212,43,71,184,164,91,156,99,127,128,98,157,129,126,185,70,90,165,201,54,42,213,18,237,241,14,41,214,202,53,242,13,17,238,130,125,97,158,89,166,186,69,244,11,23,232,47,208,204,51,95,160,188,67,132,123,103,152,191,64,92,163,100,155,135,120,20,235,247,8,207,48,44,211,83,172,176,79,136,119,107,148,248,7,27,228,35,220,192,63,24,231,251,4,195,60,32,223,179,76,80,175,104,151,139,116,197,58,38,217,30,225,253,2,110,145,141,114,181,74,86,169,142,113,109,146,85,170,182,73,37,218,198,57,254,1,29,226} +}; + + +/* + * addmul() computes dst[] = dst[] + c * src[] + * This is used often, so better optimize it! Currently the loop is + * unrolled 16 times, a good value for 486 and pentium-class machines. + * The case c=0 is also optimized, whereas c=1 is not. These + * calls are unfrequent in my typical apps so I did not bother. + */ +void of_galois_field_2_8_addmul1 (gf *dst1, gf *src1, gf c, int sz); + +/* + * computes C = AB where A is n*k, B is k*m, C is n*m + */ +void of_galois_field_2_8_matmul (gf *a, gf *b, gf *c, int n, int k, int m); +int of_galois_field_2_8_invert_mat (of_galois_field_code_cb_t* ofcb, gf *src, int k); +int of_galois_field_2_8_invert_vdm (of_galois_field_code_cb_t* ofcb, gf *src, int k); + +#endif //OF_USE_GALOIS_FIELD_CODES_UTILS + +#endif //OF_GALOIS_FIELD_ALGEBRA_2_4_H diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/of_galois_field_code.c b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/of_galois_field_code.c new file mode 100644 index 0000000..898de1a --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/of_galois_field_code.c @@ -0,0 +1,368 @@ +/* $Id: of_galois_field_code.c 185 2014-07-15 09:57:16Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "../of_reed-solomon_gf_2_m_includes.h" + + +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + + +gf of_modnn(of_galois_field_code_cb_t* ofcb,INT32 x) +{ + UINT16 field_size = ofcb->field_size; + while (x >= field_size) + { + x -= field_size; + x = (x >> ofcb->m) + (x & field_size); + } + return x; +} + +void of_rs_2m_display_gf(of_galois_field_code_cb_t* ofcb) +{ + OF_ENTER_FUNCTION + int i; + for (i = 0; i <= ofcb->field_size; i++) { + printf("i=%i,log(i)=%i,exp(i)=%i,exp(log(i))=%i\n",i,ofcb->of_rs_gf_log[i],ofcb->of_rs_gf_exp[i],ofcb->of_rs_gf_exp[ofcb->of_rs_gf_log[i]]); + } + OF_EXIT_FUNCTION +} + + +/* + * shuffle move src packets in their position + */ +static int +of_rs_2m_shuffle (gf *pkt[], int index[], int k) +{ + OF_ENTER_FUNCTION + int i; + + for (i = 0 ; i < k ;) + { + if (index[i] >= k || index[i] == i) + i++ ; + else + { + /* + * put pkt in the right position (first check for conflicts). + */ + int c = index[i] ; + + if (index[c] == c) + { + OF_EXIT_FUNCTION + return 1 ; + } + SWAP (index[i], index[c], int) ; + SWAP (pkt[i], pkt[c], gf *) ; + } + } + OF_EXIT_FUNCTION + return 0 ; +} + + +void of_rs_2m_release(of_galois_field_code_cb_t* ofcb) +{ + OF_ENTER_FUNCTION + if (ofcb->enc_matrix != NULL) + { + of_free(ofcb->enc_matrix); + ofcb->enc_matrix=NULL; + } + if (ofcb->dec_matrix != NULL) + { + of_free(ofcb->dec_matrix); + ofcb->dec_matrix=NULL; + } + OF_EXIT_FUNCTION +} + + +of_status_t of_rs_2m_build_encoding_matrix(of_galois_field_code_cb_t* ofcb) +{ + OF_ENTER_FUNCTION + gf *tmp_m, *p; + UINT32 k,r,col,row; + k=ofcb->nb_source_symbols; + r = ofcb->nb_repair_symbols; + if ((ofcb->enc_matrix = of_malloc((k+r)*(k))) == NULL) + { + goto no_mem; + } + /* cast the pointer (a 64 bit integer on LP64 systems) to uintptr_t first, and then + * truncate it to keep only the lowest 32 bits. Works the same on both 32 bit and 64 + * bit systems */ + ofcb->magic = ( (FEC_MAGIC ^ k) ^ (k+r)) ^ ((uintptr_t)(ofcb->enc_matrix) & 0xFFFFFFFF); + + if ((tmp_m = of_malloc((k+r)*(k))) == NULL) + { + goto no_mem; + } + /* + * fill the matrix with powers of field elements, starting from 0. + * The first row is special, cannot be computed with exp. table. + */ + tmp_m[0] = 1 ; + for (col = 1; col < k ; col++) + tmp_m[col] = 0 ; + for (p = tmp_m + k, row = 0; row < k+r - 1 ; row++, p += k) + { + for (col = 0 ; col < k ; col ++) + switch(ofcb->m) { + case 4: + p[col] = of_gf_2_4_exp[of_modnn (ofcb,row*col) ]; + break; + case 8: + p[col] = of_gf_2_8_exp[of_modnn (ofcb,row*col) ]; + break; + } + } + + /* + * quick code to build systematic matrix: invert the top + * k*k vandermonde matrix, multiply right the bottom n-k rows + * by the inverse, and construct the identity matrix at the top. + */ + switch(ofcb->m) { + case 4: + of_galois_field_2_4_invert_vdm(ofcb, tmp_m, k); + of_galois_field_2_4_matmul(tmp_m + k*k, tmp_m, ofcb->enc_matrix + k*k, r, k, k); + break; + case 8: + of_galois_field_2_8_invert_vdm(ofcb, tmp_m, k); + of_galois_field_2_8_matmul(tmp_m + k*k, tmp_m, ofcb->enc_matrix + k*k, r, k, k); + break; + } + /* + * the upper matrix is I so do not bother with a slow multiply + */ + bzero (ofcb->enc_matrix, k*k*sizeof (gf)); + for (p = ofcb->enc_matrix, col = 0 ; col < k ; col++, p += k + 1) + *p = 1 ; + + of_free (tmp_m); + + OF_EXIT_FUNCTION + return OF_STATUS_OK; + no_mem: + OF_PRINT_ERROR(("out of memory\n")); + error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + + +#ifdef OF_USE_DECODER +of_status_t of_rs_2m_build_decoding_matrix(of_galois_field_code_cb_t* ofcb, int *index) +{ + OF_ENTER_FUNCTION + UINT32 k,r,i; + gf *p; + k = ofcb->nb_source_symbols; + r = ofcb->nb_repair_symbols; + if ((ofcb->dec_matrix = of_malloc((k)*(k))) == NULL) + { + goto no_mem; + } + for (i = 0, p = ofcb->dec_matrix ; i < k ; i++, p += k) + { +#if 1 /* this is simply an optimization, not very useful indeed */ + if (index[i] < k) + { + bzero (p, k*sizeof (gf)); + p[i] = 1 ; + } + else +#endif + if (index[i] < (k+r)) + bcopy (& (ofcb->enc_matrix[index[i]*k]), p, k*sizeof (gf)); + else + { + OF_PRINT_ERROR ( ("decode: invalid index %d (max %d)\n", + index[i], k+r - 1)) + of_free (ofcb->dec_matrix); + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR ; + } + } + int result; + switch (ofcb->m) + { + case 4: + result = of_galois_field_2_4_invert_mat(ofcb, ofcb->dec_matrix, k); + break; + case 8: + result = of_galois_field_2_8_invert_mat(ofcb, ofcb->dec_matrix, k); + break; + } + if (result) + { + of_free (ofcb->dec_matrix); + ofcb->dec_matrix = NULL ; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +no_mem: + OF_PRINT_ERROR(("out of memory\n")); +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + + +of_status_t of_rs_2m_decode (of_galois_field_code_cb_t* ofcb, gf *_pkt[], int index[], int sz) +{ + OF_ENTER_FUNCTION + gf **pkt = (gf**) _pkt; /* VR */ + gf **new_pkt ; + int row, col, k = ofcb->nb_source_symbols ; + + if (ofcb->m > 8) + sz /= 2 ; + if (of_rs_2m_shuffle (pkt, index, k)) + { + /* error if true */ + OF_EXIT_FUNCTION + return OF_STATUS_ERROR ; + } + if (of_rs_2m_build_decoding_matrix (ofcb, index) != OF_STATUS_OK) + { + OF_PRINT_ERROR(("of_rs_2m_decode : cannot build decoding matrix.")) + goto error; + } + + /* + * do the actual decoding + */ + new_pkt = (gf **) of_malloc (k * sizeof (gf *)); + for (row = 0 ; row < k ; row++) + { + if (index[row] >= k) + { + new_pkt[row] = (gf *) of_calloc (sz, sizeof (gf)); + for (col = 0 ; col < k ; col++) + { + if (ofcb->dec_matrix[row*k + col] != 0) + { + switch (ofcb->m) + { + case 4: + of_galois_field_2_4_addmul1_compact(new_pkt[row], pkt[col], ofcb->dec_matrix[row*k + col], sz); + break; + case 8: + // no addmul1 compact form for GF(2^8) + of_galois_field_2_8_addmul1(new_pkt[row], pkt[col], ofcb->dec_matrix[row*k + col], sz); + break; + } + } + } + } + } +//#if 0 + /* + * move pkts to their final destination + * Warning: this function does not update the index[] table to contain + * the actual reconstructed packet index. + */ + for (row = 0 ; row < k ; row++) + { + if (index[row] >= k) + { + bcopy (new_pkt[row], pkt[row], sz*sizeof (gf)); + of_free (new_pkt[row]); + } + } +//#endif + of_free (new_pkt); + of_free(ofcb->dec_matrix); + ofcb->dec_matrix = NULL; + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} +#endif + + +#ifdef OF_USE_ENCODER +of_status_t of_rs_2m_encode(of_galois_field_code_cb_t* ofcb,gf *_src[], gf *_fec, int index, int sz) +{ + OF_ENTER_FUNCTION + gf **src = (gf**) _src; /* VR */ + gf *fec = (gf*) _fec; /* VR */ + int i, k = ofcb->nb_source_symbols ; + gf *p ; + + if (ofcb->m > 8) + sz /= 2 ; + + if (index < k) + { + bcopy (src[index], fec, sz * sizeof(gf)); + } + else if (index < (ofcb->nb_source_symbols + ofcb->nb_repair_symbols)) + { + p = & (ofcb->enc_matrix[index*k]); + bzero (fec, sz * sizeof (gf)); + for (i = 0; i < k ; i++) + { + if (p[i] != 0 ) + { + switch(ofcb->m) + { + case 4: + of_galois_field_2_4_addmul1_compact(fec, src[i], p[i], sz); + break; + case 8: + of_galois_field_2_8_addmul1(fec, src[i], p[i], sz); + break; + } + } + } + return OF_STATUS_OK; + } + else + { + OF_PRINT_ERROR (("Invalid index %d (max %d)\n", index, ofcb->nb_source_symbols+ofcb->nb_repair_symbols - 1)) + } + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} +#endif + +#endif //OF_USE_GALOIS_FIELD_CODES_UTILS diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/of_galois_field_code.h b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/of_galois_field_code.h new file mode 100644 index 0000000..fbe1af2 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/galois_field_codes_utils/of_galois_field_code.h @@ -0,0 +1,104 @@ +/* $Id: of_galois_field_code.h 148 2014-07-08 08:01:56Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef GALOIS_FIELD_CODE_H +#define GALOIS_FIELD_CODE_H + +#include "../of_reed-solomon_gf_2_m_includes.h" + +#define bcmp(s1 ,s2, n) memcmp((s1), (s2), (size_t)(n)) + +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + +#define FEC_MAGIC 0xFECC0DEC + + +/* + * Primitive polynomials - see Lin & Costello, Appendix A, + * and Lee & Messerschmitt, p. 453. + */ +#if 0 +static const char *of_rs_allPp[] = /* GF_BITS polynomial */ +{ + NULL, /* 0 no code */ + NULL, /* 1 no code */ + "111", /* 2 1+x+x^2 */ + "1101", /* 3 1+x+x^3 */ + "11001", /* 4 1+x+x^4 */ + "101001", /* 5 1+x^2+x^5 */ + "1100001", /* 6 1+x+x^6 */ + "10010001", /* 7 1 + x^3 + x^7 */ + "101110001", /* 8 1+x^2+x^3+x^4+x^8 */ + "1000100001", /* 9 1+x^4+x^9 */ + "10010000001", /* 10 1+x^3+x^10 */ + "101000000001", /* 11 1+x^2+x^11 */ + "1100101000001", /* 12 1+x+x^4+x^6+x^12 */ + "11011000000001", /* 13 1+x+x^3+x^4+x^13 */ + "110000100010001", /* 14 1+x+x^6+x^10+x^14 */ + "1100000000000001", /* 15 1+x+x^15 */ + "11010000000010001" /* 16 1+x+x^3+x^12+x^16 */ +}; +#endif + +/** + * Galois-Field-Code stable codec specific control block structure. + */ +typedef of_rs_2_m_cb_t of_galois_field_code_cb_t; /* XXX: the two types are synonymous in fact! */ + +/** + * just a helper to init all we need to use GF + */ +of_status_t of_rs_2m_init(of_galois_field_code_cb_t* ofcb); + +/** + * and the helper to release memory + */ +void of_rs_2m_release(of_galois_field_code_cb_t* ofcb); + +/** + * even if only decoder is defined, we need an encoding matrix. + */ +of_status_t of_rs_2m_build_encoding_matrix(of_galois_field_code_cb_t* ofcb); + +#ifdef OF_USE_DECODER +of_status_t of_rs_2m_build_decoding_matrix(of_galois_field_code_cb_t* ofcb,int* index); +of_status_t of_rs_2m_decode(of_galois_field_code_cb_t* ofcb,gf *pkt[], int index[], int sz); +#endif + +#ifdef OF_USE_ENCODER +of_status_t of_rs_2m_encode(of_galois_field_code_cb_t* ofcb,gf *_src[], gf *_fec, int index, int sz); +#endif + +#endif //OF_USE_GALOIS_FIELD_CODES_UTILS + +#endif //GALOIS_FIELD_CODE_H diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_codec_profile.h b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_codec_profile.h new file mode 100644 index 0000000..678ffe1 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_codec_profile.h @@ -0,0 +1,61 @@ +/* $Id: of_codec_profile.h 152 2014-07-08 14:01:42Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + + + +/****** GENERAL SETUP OPTIONS; EDIT AS APPROPRIATE ****************************/ + +#define OF_USE_REED_SOLOMON_2_M_CODEC + +#ifdef OF_DEBUG +/* additional parameter for memory statistic purposes */ +#define MEM_STATS_ARG ,ofcb->stats +#define MEM_STATS ,stats +#else +#define MEM_STATS_ARG +#define MEM_STATS +#endif + + +/** + * This parameter can be used to force 32 bits computations in addmull1 + */ +//#define OF_RS_2M_USE_32BITS + + +/** + * Maximum m value for the GF(2^m) field. + * WARNING: for the moment, only m=4 and 8 are supported! + */ +#define OF_REED_SOLOMON_2_M_MAX_M 8 + diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m.h b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m.h new file mode 100644 index 0000000..d0e3d0b --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m.h @@ -0,0 +1,312 @@ +/* $Id: of_reed-solomon_gf_2_m.h 182 2014-07-15 09:27:51Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + +#ifndef OF_REED_SOLOMON_GF_2_M_H +#define OF_REED_SOLOMON_GF_2_M_H + + + +/** + * Reed-Solomon stable codec specific control block structure. + */ +typedef struct of_rs_2_m_cb +{ +/************************************************************************************ + * of_rs_2_m_cb * + ***********************************************************************************/ +/************************************************************************************ + * of_cb_t * + ***********************************************************************************/ + of_codec_id_t codec_id; /* must begin with fec_codec_id */ + of_codec_type_t codec_type; /* must be 2nd item */ + UINT32 nb_source_symbols; /** k parameter (AKA code dimension). */ + UINT32 nb_repair_symbols; /** r = n - k parameter. */ + UINT32 encoding_symbol_length; /** symbol length. */ +/***********************************************************************************/ + + UINT16 m; /* in theory between 2..16. Currently only values 4 and 8 are supported */ + UINT16 field_size; /* 2^m */ + gf* of_rs_gf_exp; /* index->poly form conversion table. */ + int* of_rs_gf_log; /* Poly->index form conversion table. */ + gf* of_rs_inverse; /* inverse of field elem. */ + gf** of_gf_mul_table; /* table of 2 numbers multiplication. */ + +//#ifdef OF_USE_ENCODER + /** + * Encoding matrix (G). + * The encoding matrix is computed starting with a Vandermonde matrix, + * and then transforming it into a systematic matrix. + */ + gf *enc_matrix ; +//#endif +#ifdef OF_USE_DECODER + /** + * Decoding matrix (k*k). + */ + gf *dec_matrix; +#endif +/***********************************************************************************/ + + UINT32 magic; + + /** Maximum number of source symbols supported by this codec for practical reasons. */ + UINT32 max_nb_source_symbols; + /** Maximum number of encoding symbols supported by this codec for practical reasons. */ + UINT32 max_nb_encoding_symbols; + /* maximum m value in GF(2^m) supported by the codec */ + UINT16 max_m; + UINT32 nb_encoding_symbols; +#ifdef OF_USE_DECODER + /* + * decoder specific variables. + */ + /** + * Table of available source and repair symbols. This table is ordered, no matter + * the symbol arrival order. + */ + void ** available_symbols_tab; + /** Number of available source and repair symbols. This is the number of entries in + * the available_symbols_tab tables. */ + UINT32 nb_available_symbols; + /** Number of available source symbols. */ + UINT32 nb_available_source_symbols; + bool decoding_finished; /** true as soon as decoding completed. */ +#endif /* OF_USE_DECODER */ + + + /** callbacks for this codec. */ + void* (*decoded_source_symbol_callback) (void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi); /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi); /* encoding symbol ID in {0..k-1} */ + void* context_4_callback; + +} of_rs_2_m_cb_t; + + +/* + * API function prototypes. + */ + /** + * This function create the codec instance for the Reed-Solomon codec. + * + * @fn of_status_t of_rs_2_m_create_codec_instance (of_rs_2_m_cb_t** of_cb) + * @brief create a Reed-Solomon codec instance + * @param of_cb (IN/OUT) address of the pointer to a Reed-Solomon codec control block. This pointer is updated + * by this function. + * In case of success, it points to a session structure allocated by the + * library. In case of failure it points to NULL. + * @return Error status. The ofcb pointer is updated according to the success return + * status. + */ +of_status_t of_rs_2_m_create_codec_instance (of_rs_2_m_cb_t** of_cb); + +/** + * This function releases all the internal resources used by this FEC codec instance. + * None of the source symbol buffers will be free'ed by this function, even those decoded by + * the library if any, regardless of whether a callback has been registered or not. It's the + * responsibility of the caller to free them. + * + * @fn of_status_t of_rs_2_m_release_codec_instance (of_rs_2_m_cb_t* ofcb) + * @brief release all resources used by the codec + * @param ofcb (IN) Pointer to the control block. + * @return Error status. + */ +of_status_t of_rs_2_m_release_codec_instance (of_rs_2_m_cb_t* ofcb); + +/** + * + * @fn of_status_t of_rs_2_m_set_fec_parameters (of_rs_2_m_cb_t* ofcb, of_rs_parameters_t* params) + * @brief set all the FEC codec parameters (e.g. k, n, or symbol size) + * @param ofcb (IN) Pointer to the control block. + * @param params (IN) pointer to a structure containing the FEC parameters associated to + * a specific FEC codec. + * @return Error status. + */ +of_status_t of_rs_2_m_set_fec_parameters (of_rs_2_m_cb_t* ofcb, + of_rs_2_m_parameters_t* params); + +/** + * @fn of_status_t of_rs_2_m_set_callback_functions (of_rs_2_m_cb_t *ofcb,void* (*decoded_source_symbol_callback) + * (void *context,UINT32 size,UINT32 esi), void* (*decoded_repair_symbol_callback) + * (void *context,UINT32 size,UINT32 esi),void* context_4_callback) + * @brief set various callbock functions (see header of_open_fec_api.h) + * @param ofcb (IN) Pointer to the session. + * + * @param decoded_source_symbol_callback + * (IN) Pointer to the function, within the application, that + * needs to be called each time a source symbol is decoded. + * If this callback is not initialized, the symbol is managed + * internally. + * + * @param decoded_repair_symbol_callback + * (IN) Pointer to the function, within the application, that + * needs to be called each time a repair symbol is decoded. + * If this callback is not initialized, the symbol is managed + * internally. + * + * @param context_4_callback (IN) Pointer to the application-specific context that will be + * passed to the callback function (if any). This context is not + * interpreted by this function. + * + * @return Completion status (LDPC_OK or LDPC_ERROR). + */ +of_status_t of_rs_2_m_set_callback_functions (of_rs_2_m_cb_t* ofcb, + void* (*decoded_source_symbol_callback) (void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* context_4_callback); + +#ifdef OF_USE_ENCODER +/** + * @fn of_status_t of_rs_2_m_build_repair_symbol (of_rs_2_m_cb_t* ofcb, void* encoding_symbols_tab[], UINT32 esi_of_symbol_to_build) + * @brief build a repair symbol (encoder only) + * @param ofcb (IN) Pointer to the session. + * @param encoding_symbols_tab (IN/OUT) table of source and repair symbols. + * The entry for the repair symbol to build can either point + * to a buffer allocated by the application, or let to NULL + * meaning that of_build_repair_symbol will allocate memory. + * @param esi_of_symbol_to_build + * (IN) encoding symbol ID of the repair symbol to build in + * {k..n-1} + * @return Error status. + */ +of_status_t of_rs_2_m_build_repair_symbol (of_rs_2_m_cb_t* ofcb, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build); +#endif //OF_USE_ENCODER + +#ifdef OF_USE_DECODER +/** + * @fn of_status_t of_rs_2_m_decode_with_new_symbol (of_rs_2_m_cb_t* ofcb, void* const new_symbol_buf, UINT32 new_symbol_esi) + * @brief (try to) decode with a newly received symbol + * @param ofcb (IN) Pointer to the session. + * @param new_symbol (IN) Pointer to the encoding symbol now available (i.e. a new + * symbol received by the application, or a decoded symbol in case + * of a recursive call). + * @param new_symbol_esi (IN) Encoding symbol ID of the newly symbol available, in {0..n-1}. + * @return Error status (NB: this function does not return OF_STATUS_FAILURE). + */ +of_status_t of_rs_2_m_decode_with_new_symbol (of_rs_2_m_cb_t* ofcb, + void* new_symbol, + UINT32 new_symbol_esi); + +/** + * @fn of_status_t of_rs_2_m_set_available_symbols (of_rs_2_m_cb_t* ofcb, void* const encoding_symbols_tab[]); + * @brief inform the decoder of all the available (received) symbols + * @param ofcb (IN) Pointer to the session. + * @param encoding_symbols_tab (IN) Pointer to the available encoding symbols table. To each + * available symbol the corresponding entry in the table must point + * to the associated buffer. Entries set to NULL are interpreted as + * corresponding to erased symbols. + * @return Error status. + */ +of_status_t of_rs_2_m_set_available_symbols (of_rs_2_m_cb_t* ofcb, + void* const encoding_symbols_tab[]); + +/** + * @fn of_status_t of_rs_2_m_finish_decoding (of_rs_2_m_cb_t* ofcb) + * @brief finish decoding with available symbols + * @param ofcb (IN) Pointer to the session. + * @return Error status. Returns OF_STATUS_FAILURE if decoding failed, or + * OF_STATUS_OK if decoding succeeded, or OF_STATUS_*_ERROR in case + * of (fatal) error. + */ +of_status_t of_rs_2_m_finish_decoding (of_rs_2_m_cb_t* ofcb); + +/** + * @fn bool of_rs_2_m_is_decoding_complete (of_rs_2_m_cb_t* ofcb) + * @brief check if decoding is finished + * @param ofcb (IN) Pointer to the session. + * @return Boolean. Warning, this is one of the very functions of the library that + * does not return an error status. + */ +bool of_rs_2_m_is_decoding_complete (of_rs_2_m_cb_t* ofcb); + +/** + * @fn of_status_t of_rs_2_m_get_source_symbols_tab (of_rs_2_m_cb_t* ofcb, void* source_symbols_tab[]) + * @brief get the table of available source symbols (after decoding) + * @param ofcb (IN) Pointer to the session. + * @param source_symbols_tab (IN/OUT) table, that will be filled by the library and returned + * to the application. + * @return Error status. + */ +of_status_t of_rs_2_m_get_source_symbols_tab (of_rs_2_m_cb_t* ofcb, + void* source_symbols_tab[]); + +#endif //OF_USE_DECODER + +/** + * @fn of_status_t of_rs_2_m_set_control_parameter (of_rs_2_m_cb_t* ofcb,UINT32 type,void* value,UINT32 length) + * @brief set a specific FEC parameter + * @param ofcb (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID specific. + * @param value (IN) Pointer to the value of the parameter. The type of the object pointed + * is FEC codec ID specific. + * @param length (IN) length of pointer + * @return Error status. + */ +of_status_t of_rs_2_m_set_control_parameter (of_rs_2_m_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length); + +/** + * @fn of_status_t of_rs_2_m_get_control_parameter (of_rs_2_m_cb_t* ofcb,UINT32 type,void* value,UINT32 length) + * @brief get a specific FEC parameter + * @param ofcb (IN) Pointer to the session. + * @param type (IN) Type of parameter. This type is FEC codec ID specific. + * @param value (IN/OUT) Pointer to the value of the parameter. The type of the object + * pointed is FEC codec ID specific. This function updates the value object + * accordingly. The application, who knows the FEC codec ID, is responsible + * to allocating the approriate object pointed by the value pointer. + * @param length (IN) length of pointer + * @return Error status. + */ +of_status_t of_rs_2_m_get_control_parameter (of_rs_2_m_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length); + + + +#endif //OF_REED_SOLOMON_GF_2_M_H + +#endif /* #ifdef OF_USE_REED_SOLOMON_CODEC_2_M */ diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m_api.c b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m_api.c new file mode 100644 index 0000000..c03a579 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m_api.c @@ -0,0 +1,663 @@ +/* $Id: of_reed-solomon_gf_2_m_api.c 186 2014-07-16 07:17:53Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#include "of_reed-solomon_gf_2_m_includes.h" + + +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + + +of_status_t of_rs_2_m_create_codec_instance (of_rs_2_m_cb_t** of_cb) +{ + of_codec_type_t codec_type; /* temporary value */ + of_rs_2_m_cb_t *cb; + + OF_ENTER_FUNCTION + cb = (of_rs_2_m_cb_t*) of_realloc (*of_cb, sizeof (of_rs_2_m_cb_t)); + *of_cb = cb; + /* realloc does not initialize the additional buffer space, so do that manually, + * then re-initialize a few parameters */ + codec_type = cb->codec_type; + memset(cb, 0, sizeof(*cb)); + cb->codec_type = codec_type; + cb->codec_id = OF_CODEC_REED_SOLOMON_GF_2_M_STABLE; + /** + * max nb source symbols and max nb encoding symbols are computed + * in the of_rs_2_m_set_fec_parameters function (m is needed). + */ + cb->max_m = OF_REED_SOLOMON_2_M_MAX_M; /* init it immediately... */ + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_rs_2_m_release_codec_instance (of_rs_2_m_cb_t* ofcb) +{ + OF_ENTER_FUNCTION + of_rs_2m_release((of_galois_field_code_cb_t*)ofcb); +#ifdef OF_USE_DECODER + if (ofcb->available_symbols_tab != NULL) + { + of_free(ofcb->available_symbols_tab); + ofcb->available_symbols_tab = NULL; + } +#endif /* OF_USE_DECODER */ +#ifdef OF_DEBUG /* { */ + OF_TRACE_LVL(1, ("\tTo be added: Reed-Solomon GF(2^4): total of %ld bytes for precalculated tables (incl. %ld for the optimized mult table)\n", + sizeof(of_gf_2_4_log) + sizeof(of_gf_2_4_exp) + sizeof(of_gf_2_4_inv) + sizeof(of_gf_2_4_mul_table) + sizeof(of_gf_2_4_opt_mul_table), sizeof(of_gf_2_4_opt_mul_table))) + OF_TRACE_LVL(1, ("\tTo be added: Reed-Solomon GF(2^8): total of %ld bytes for precalculated tables (incl. %ld for mult table)\n", + sizeof(of_gf_2_8_log) + sizeof(of_gf_2_8_exp) + sizeof(of_gf_2_8_inv) + sizeof(of_gf_2_8_mul_table), sizeof(of_gf_2_8_mul_table))) +#endif /* } OF_DEBUG */ + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +of_status_t of_rs_2_m_set_fec_parameters (of_rs_2_m_cb_t* ofcb, + of_rs_2_m_parameters_t* params) +{ + OF_ENTER_FUNCTION + ofcb->m = params->m; + if ((ofcb->m != 4) && (ofcb->m != 8)) { + OF_PRINT_ERROR(("ERROR: invalid m parameter (must be 4 or 8)")); + goto error; + } + ofcb->field_size = (1 << ofcb->m) - 1; + ofcb->max_nb_encoding_symbols = ofcb->max_nb_source_symbols = ofcb->field_size; + if ((ofcb->nb_source_symbols = params->nb_source_symbols) > ofcb->max_nb_source_symbols) { + OF_PRINT_ERROR(("ERROR: invalid nb_source_symbols parameter (got %d, maximum is %d)", + ofcb->nb_source_symbols, ofcb->max_nb_source_symbols)) + goto error; + } + ofcb->nb_source_symbols = params->nb_source_symbols; + ofcb->nb_repair_symbols = params->nb_repair_symbols; + ofcb->encoding_symbol_length = params->encoding_symbol_length; + ofcb->nb_encoding_symbols = ofcb->nb_source_symbols + ofcb->nb_repair_symbols; +#ifdef OF_USE_DECODER + ofcb->available_symbols_tab = (void**) of_calloc (ofcb->nb_encoding_symbols, sizeof (void*)); + ofcb->nb_available_symbols = 0; + ofcb->nb_available_source_symbols = 0; +#endif /* OF_USE_DECODER */ + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_FATAL_ERROR; +} + + +of_status_t of_rs_2_m_set_callback_functions (of_rs_2_m_cb_t* ofcb, + void* (*decoded_source_symbol_callback) (void *context, + UINT32 size, /* size of decoded source symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* (*decoded_repair_symbol_callback) (void *context, + UINT32 size, /* size of decoded repair symbol */ + UINT32 esi), /* encoding symbol ID in {0..k-1} */ + void* context_4_callback) +{ + ofcb->decoded_source_symbol_callback = decoded_source_symbol_callback; + ofcb->decoded_repair_symbol_callback = decoded_repair_symbol_callback; + ofcb->context_4_callback = context_4_callback; + if (ofcb->decoded_repair_symbol_callback != NULL) + { + OF_PRINT_ERROR(("WARNING, the decoded repair symbol callback is never called with Reed-Solomon codes, since those repair symbols are never decoded\n")) + } + return OF_STATUS_OK; +} + + +#ifdef OF_USE_ENCODER + +of_status_t of_rs_2_m_build_repair_symbol (of_rs_2_m_cb_t* ofcb, + void* encoding_symbols_tab[], + UINT32 esi_of_symbol_to_build) +{ + OF_ENTER_FUNCTION + if (esi_of_symbol_to_build < ofcb->nb_source_symbols || esi_of_symbol_to_build >= ofcb->nb_encoding_symbols) + { + OF_PRINT_ERROR(("ERROR: bad esi of encoding symbol (%d)\n", esi_of_symbol_to_build)) + goto error; + } + if (encoding_symbols_tab[esi_of_symbol_to_build] == NULL) + { + if ((encoding_symbols_tab[esi_of_symbol_to_build] = of_calloc (1, ofcb->encoding_symbol_length)) == NULL) + { + OF_PRINT_ERROR(("ERROR: no memory\n")) + goto error; + } + } + if (ofcb->enc_matrix == NULL) + { + if (of_rs_2m_build_encoding_matrix((of_galois_field_code_cb_t*)ofcb) != OF_STATUS_OK) + { + OF_PRINT_ERROR(("ERROR: creating encoding matrix failed\n")) + goto error; + } + } + if (of_rs_2m_encode((of_galois_field_code_cb_t*) ofcb, (gf**)encoding_symbols_tab, + encoding_symbols_tab[esi_of_symbol_to_build], esi_of_symbol_to_build, + ofcb->encoding_symbol_length) != OF_STATUS_OK) + { + OF_PRINT_ERROR(("ERROR: of_rs_encode failed\n")) + goto error; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} +#endif //OF_USE_ENCODER + + +#ifdef OF_USE_DECODER +of_status_t of_rs_2_m_decode_with_new_symbol (of_rs_2_m_cb_t* ofcb, + void* new_symbol, + UINT32 new_symbol_esi) +{ + OF_ENTER_FUNCTION + if (ofcb->decoding_finished) + { + OF_TRACE_LVL(2, ("%s: decoding already done\n", __FUNCTION__)); + return OF_STATUS_OK; + } + if (ofcb->available_symbols_tab[new_symbol_esi] != NULL) + { + /* duplicated symbol, ignore */ + OF_TRACE_LVL(2, ("%s: symbol (esi=%d) duplicated\n", __FUNCTION__, new_symbol_esi)); + goto end; + } + ofcb->available_symbols_tab[new_symbol_esi] = new_symbol; + ofcb->nb_available_symbols++; + if (new_symbol_esi < ofcb->nb_source_symbols) + { + /* remember a new source symbol is available */ + ofcb->nb_available_source_symbols++; + } + + if (ofcb->nb_available_source_symbols == ofcb->nb_source_symbols) + { + /* we received all the k source symbols, so it's finished */ + ofcb->decoding_finished = true; + OF_TRACE_LVL(2, ("%s: done, all source symbols have been received\n", __FUNCTION__)); + OF_EXIT_FUNCTION + return OF_STATUS_OK; + } + if (ofcb->nb_available_symbols >= ofcb->nb_source_symbols) + { + /* we received a sufficient number of symbols, so let's decode */ + if (of_rs_2_m_finish_decoding(ofcb) != OF_STATUS_OK) + { + OF_PRINT_ERROR(("ERROR: of_rs_decode failure\n")) + goto error; + } + ASSERT(ofcb->decoding_finished == true); + OF_TRACE_LVL(2, ("%s: done, decoding successful\n", __FUNCTION__)); + OF_EXIT_FUNCTION + return OF_STATUS_OK; + } +end: + OF_TRACE_LVL(2, ("%s: okay, but not yet finished\n", __FUNCTION__)); + OF_EXIT_FUNCTION + return OF_STATUS_OK; +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + + +of_status_t of_rs_2_m_set_available_symbols (of_rs_2_m_cb_t* ofcb, + void* const encoding_symbols_tab[]) +{ + UINT32 i; + + OF_ENTER_FUNCTION + ofcb->nb_available_symbols = 0; + ofcb->nb_available_source_symbols = 0; + for (i = 0; i < ofcb->nb_encoding_symbols; i++) + { + if ((ofcb->available_symbols_tab[i] = encoding_symbols_tab[i]) == NULL) + { + continue; + } + if (i < ofcb->nb_source_symbols) + { + ofcb->nb_available_source_symbols++; + } + ofcb->nb_available_symbols++; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +#if 0 /* new */ +of_status_t of_rs_2_m_finish_decoding (of_rs_2_m_cb_t* ofcb) +{ + UINT32 k; + UINT32 n; + char *tmp_buf[ofcb->nb_source_symbols];/* keep available source/repair symbol buffers here... */ + int tmp_esi[ofcb->nb_source_symbols]; /* ...and their esi here. In fact we only need k entries + * in these tables, but in order to avoid using malloc (time + * consumming), we use an automatic table of maximum size for + * both tmp_buf[] and tmp_esi[]. */ + INT32 tmp_idx; /* index in tmp_buf[] and tmp_esi[] tabs */ + void **ass_buf; /* tmp pointer to the current available source symbol entry in available_symbols_tab[] */ + UINT32 ass_esi; /* corresponding available source symbol ESI */ + void **ars_buf; /* tmp pointer to the current available repair symbol entry in available_symbols_tab[] */ + UINT32 ars_esi; /* corresponding available repair symbol ESI */ + + OF_ENTER_FUNCTION + if (ofcb->decoding_finished) + { + return OF_STATUS_OK; + } + k = ofcb->nb_source_symbols; + n = ofcb->nb_encoding_symbols; + if (ofcb->nb_available_symbols < k) + { + OF_PRINT_ERROR(("ERROR: nb received symbols < nb source symbols\n")) + OF_EXIT_FUNCTION + return OF_STATUS_FAILURE; + } + if (ofcb->nb_available_source_symbols == k) + { + /* we received all the k source symbols, so it's finished */ + ofcb->decoding_finished = true; + OF_EXIT_FUNCTION + return OF_STATUS_OK; + } + /* + * Because of of_rs_decode internal details, we put source symbols at their right location + * and fill in the gaps (i.e. erased source symbols) with repair symbols. + */ + ass_esi = 0; + ars_esi = k; + ass_buf = ofcb->available_symbols_tab; + ars_buf = ofcb->available_symbols_tab + k; + for (tmp_idx = 0; tmp_idx < k; tmp_idx++) + { + if (*ass_buf == NULL) + { + /* this source symbol is not available, replace it with a repair */ + while (*ars_buf == NULL) + { + ars_esi++; + ars_buf++; + } + OF_TRACE_LVL(2, ("of_rs_finish_decoding: copy repair with esi=%d in tmp_buf[%d]\n", + ars_esi, tmp_idx)) + tmp_buf[tmp_idx] = *ars_buf; + tmp_esi[tmp_idx] = ars_esi; + ars_esi++; + ars_buf++; + } + else + { + OF_TRACE_LVL(2, ("of_rs_finish_decoding: copy source with esi=%d in tmp_buf[%d]\n", + ars_esi, tmp_idx)) + tmp_buf[tmp_idx] = *ass_buf; + tmp_esi[tmp_idx] = ass_esi; + } + ass_esi++; + ass_buf++; + } +//#if 0 + for (tmp_idx = 0; tmp_idx < k; tmp_idx++) + { + OF_TRACE_LVL(2, ("Before of_rs_decode: esi=%d, k=%d, tmp_idx=%d\n", tmp_esi[tmp_idx], k, tmp_idx)) + } +//#endif + if (ofcb->enc_matrix == NULL) + { + if (of_rs_2m_build_encoding_matrix((of_galois_field_code_cb_t*)ofcb) != OF_STATUS_OK) + { + OF_PRINT_ERROR(("ERROR: creating encoding matrix failed")) + goto error; + } + } + if (of_rs_2m_decode((of_galois_field_code_cb_t*)ofcb, (gf**)tmp_buf, (int*)tmp_esi, ofcb->encoding_symbol_length) != OF_STATUS_OK) + { + OF_PRINT_ERROR(("ERROR: of_rs_decode failure\n")) + goto error; + } + ofcb->decoding_finished = true; +//#if 0 + for (tmp_idx = 0; tmp_idx < k; tmp_idx++) + { + OF_TRACE_LVL(2, ("After of_rs_decode: esi=%d, k=%d, tmp_idx=%d\n", tmp_esi[tmp_idx], k, tmp_idx)) + } +//#endif + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + +#else /* old follows */ + +of_status_t of_rs_2_m_finish_decoding (of_rs_2_m_cb_t* ofcb) +{ + UINT32 k; + UINT32 n; + char *tmp_buf[ofcb->nb_source_symbols];/* keep available source/repair symbol buffers here... */ + int tmp_esi[ofcb->nb_source_symbols]; /* ...and their esi here. In fact we only need k entries + * in these tables, but in order to avoid using malloc (time + * consumming), we use an automatic table of maximum size for + * both tmp_buf[] and tmp_esi[]. */ + INT32 tmp_idx; /* index in tmp_buf[] and tmp_esi[] tabs */ + char *large_buf = NULL; /* single large buffer where to copy all source/repair symbols */ + UINT32 off; /* offset, in unit of characters, in large_buf */ + void **ass_buf; /* tmp pointer to the current available source symbol entry in available_symbols_tab[] */ + UINT32 ass_esi; /* corresponding available source symbol ESI */ + void **ars_buf; /* tmp pointer to the current available repair symbol entry in available_symbols_tab[] */ + UINT32 ars_esi; /* corresponding available repair symbol ESI */ + + OF_ENTER_FUNCTION + if (ofcb->decoding_finished) + { + return OF_STATUS_OK; + } + k = ofcb->nb_source_symbols; + n = ofcb->nb_encoding_symbols; + //int *tmp_esi = (int*)malloc(ofcb->field_size*sizeof(int)); + //char ** tmp_buf = (char**)malloc(n*sizeof(char*)); // ???? WRT RS(255) + if (ofcb->nb_available_symbols < k) + { + OF_PRINT_ERROR(("ERROR: nb received symbols < nb source symbols\n")) + OF_EXIT_FUNCTION + return OF_STATUS_FAILURE; + } + if (ofcb->nb_available_source_symbols == k) + { + /* we received all the k source symbols, so it's finished */ + ofcb->decoding_finished = true; + OF_EXIT_FUNCTION + return OF_STATUS_OK; + } + /* + * Copy available source and repair symbols in a single large buffer first. + * NB: this is required by the current FEC codec which modifies + * the tmp_buf buffers!!! + */ + large_buf = (char *) of_malloc(k * ofcb->encoding_symbol_length); + if (large_buf == NULL) + { + goto no_mem; + } + /* Then remember the location of each symbol buffer */ + for (tmp_idx = 0, off = 0; tmp_idx < k; tmp_idx++, off += ofcb->encoding_symbol_length) { + tmp_buf[tmp_idx] = large_buf + off; + } + tmp_idx = 0; /* index in tmp_buf and tmp_esi tables */ + /* + * Copy all the available source symbols (it's essential for decoding speed purposes) and + * a sufficient number of repair symbols to the tmp_buf array. Copy data as well in the + * large_buf buffer. + * Because of of_rs_decode internal details, we put source symbols at their right location + * and fill in the gaps (i.e. erased source symbols) with repair symbols. + */ + ass_esi = 0; + ars_esi = k; + ass_buf = ofcb->available_symbols_tab; + ars_buf = ofcb->available_symbols_tab + k; + for (tmp_idx = 0; tmp_idx < k; tmp_idx++) + { + if (*ass_buf == NULL) + { + /* this source symbol is not available, replace it with a repair */ + while (*ars_buf == NULL) + { + ars_esi++; + ars_buf++; + } + OF_TRACE_LVL(2, ("of_rs_finish_decoding: copy repair with esi=%d in tmp_buf[%d]\n", + ars_esi, tmp_idx)) + memcpy(tmp_buf[tmp_idx], *ars_buf, ofcb->encoding_symbol_length); + tmp_esi[tmp_idx] = ars_esi; + ars_esi++; + ars_buf++; + } + else + { + OF_TRACE_LVL(2, ("of_rs_finish_decoding: copy source with esi=%d in tmp_buf[%d]\n", + ars_esi, tmp_idx)) + + int i; + for (i=0;iencoding_symbol_length;i++) { + } + memcpy(tmp_buf[tmp_idx], *ass_buf, ofcb->encoding_symbol_length); + tmp_esi[tmp_idx] = ass_esi; + } + ass_esi++; + ass_buf++; + } +#if 0 + for (tmp_idx = 0; tmp_idx < k; tmp_idx++) + { + OF_TRACE_LVL(2, ("Before of_rs_decode: esi=%d, k=%d, tmp_idx=%d\n", tmp_esi[tmp_idx], k, tmp_idx)) + } +#endif + if (ofcb->enc_matrix == NULL) + { + if (of_rs_2m_build_encoding_matrix((of_galois_field_code_cb_t*)ofcb) != OF_STATUS_OK) + { + OF_PRINT_ERROR(("ERROR: creating encoding matrix failed\n")) + goto error; + } + } + if (of_rs_2m_decode ((of_galois_field_code_cb_t*)ofcb, (gf**)tmp_buf, (int*)tmp_esi, ofcb->encoding_symbol_length) != OF_STATUS_OK) + { + OF_PRINT_ERROR(("ERROR: of_rs_decode failure\n")) + goto error; + } + ofcb->decoding_finished = true; +#if 0 + for (tmp_idx = 0; tmp_idx < k; tmp_idx++) + { + OF_TRACE_LVL(2, ("After of_rs_decode: esi=%d, k=%d, tmp_idx=%d\n", tmp_esi[tmp_idx], k, tmp_idx)) + } +#endif + /* + * finally update the source_symbols_tab table with the decoded source symbols. + */ + for (tmp_idx = 0; tmp_idx < k; tmp_idx++) + { + ASSERT(tmp_idx < k); + ass_buf = &(ofcb->available_symbols_tab[tmp_idx]); + if (*ass_buf != NULL) + { + /* nothing to do, this source symbol has already been received. */ + continue; + } + /* + * This is a new, decoded source symbol. + * First copy it into a permanent buffer. + * Call either the associated callback or allocate memory, and then + * copy the symbol content in it. + */ + if (ofcb->decoded_source_symbol_callback != NULL) + { + *ass_buf = ofcb->decoded_source_symbol_callback (ofcb->context_4_callback, + ofcb->encoding_symbol_length, tmp_idx); + } + else + { + *ass_buf = (void *) of_malloc (ofcb->encoding_symbol_length); + } + if (*ass_buf == NULL) + { + goto no_mem; + } + memcpy(*ass_buf, tmp_buf[tmp_idx], ofcb->encoding_symbol_length); + OF_TRACE_LVL(2, ("of_rs_finish_decoding: decoded source symbol esi=%d from tmp_buf[%d]\n", + tmp_idx, tmp_idx)) + } + of_free(large_buf); + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +no_mem: + OF_PRINT_ERROR(("ERROR: out of memory.\n")) + + error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} +#endif + + +bool of_rs_2_m_is_decoding_complete (of_rs_2_m_cb_t* ofcb) +{ + OF_ENTER_FUNCTION + OF_EXIT_FUNCTION + return ofcb->decoding_finished; +} + + +of_status_t of_rs_2_m_get_source_symbols_tab (of_rs_2_m_cb_t* ofcb, + void* source_symbols_tab[]) +{ + OF_ENTER_FUNCTION + if (of_rs_2_m_is_decoding_complete(ofcb) == false) + { + OF_PRINT_ERROR(("ERROR: decoding not complete.\n")) + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; + } +#if 0 + UINT32 i; + for (i = 0; i < ofcb->nb_source_symbols; i++) + { + if (source_symbols_tab[i] == NULL) + { + source_symbols_tab[i] = ofcb->available_symbols_tab[i]; + } + } +#else + memcpy(source_symbols_tab, ofcb->available_symbols_tab, ofcb->nb_source_symbols * sizeof(void*)); +#endif + OF_EXIT_FUNCTION + return OF_STATUS_OK; +} + + +#endif //OF_USE_DECODER + +of_status_t of_rs_2_m_set_control_parameter (of_rs_2_m_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length) +{ + UINT16 m; + + OF_ENTER_FUNCTION + switch (type) { + case OF_RS_CTRL_SET_FIELD_SIZE: + if (value == NULL || length != sizeof(UINT16)) { + OF_PRINT_ERROR(("OF_CTRL_SET_FIELD_SIZE ERROR: null value or bad length (got %d, expected %ld)\n", length, sizeof(UINT16))) + goto error; + } + m = *(UINT16*)value; + if (m != 4 && m != 8) { + OF_PRINT_ERROR(("ERROR: invalid m=%d parameter (must be 4 or 8)\n", m)); + goto error; + } + ofcb->m = m; + ofcb->field_size = (1 << ofcb->m) - 1; + ofcb->max_nb_encoding_symbols = ofcb->max_nb_source_symbols = ofcb->field_size; + break; + + default: + OF_PRINT_ERROR(("ERROR: unknown type (%d)\n", type)) + break; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + + +of_status_t of_rs_2_m_get_control_parameter (of_rs_2_m_cb_t* ofcb, + UINT32 type, + void* value, + UINT32 length) +{ + OF_ENTER_FUNCTION + switch (type) { + case OF_CTRL_GET_MAX_K: + if (value == NULL || length != sizeof(UINT32)) { + OF_PRINT_ERROR(("OF_CTRL_GET_MAX_K ERROR: null value or bad length (got %d, expected %ld)\n", length, sizeof(UINT32))) + goto error; + } + if (ofcb->max_nb_source_symbols == 0) { + OF_PRINT_ERROR(("OF_CTRL_GET_MAX_K ERROR: this parameter is not initialized. Use the of_rs_2_m_set_fec_parameters function to initialize it or of_rs_2_m_set_control_parameter.\n")) + goto error; + } + *(UINT32*)value = ofcb->max_nb_source_symbols; + OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_K (%d)\n", __FUNCTION__, *(UINT32*)value)) + break; + + case OF_CTRL_GET_MAX_N: + if (value == NULL || length != sizeof(UINT32)) { + OF_PRINT_ERROR(("OF_CTRL_GET_MAX_N ERROR: null value or bad length (got %d, expected %ld)\n", length, sizeof(UINT32))) + goto error; + } + if (ofcb->max_nb_encoding_symbols == 0) { + OF_PRINT_ERROR(("OF_CTRL_GET_MAX_N ERROR: this parameter is not initialized. Use the of_rs_2_m_set_fec_parameters function to initialize it or of_rs_2_m_set_control_parameter.\n")) + goto error; + } + *(UINT32*)value = ofcb->max_nb_encoding_symbols; + OF_TRACE_LVL(1, ("%s: OF_CTRL_GET_MAX_N (%d)\n", __FUNCTION__, *(UINT32*)value)) + break; + + default: + OF_PRINT_ERROR(("ERROR: unknown type (%d)\n", type)) + goto error; + } + OF_EXIT_FUNCTION + return OF_STATUS_OK; + +error: + OF_EXIT_FUNCTION + return OF_STATUS_ERROR; +} + +#endif diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m_api.h b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m_api.h new file mode 100644 index 0000000..dc9a7c3 --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m_api.h @@ -0,0 +1,60 @@ +/* $Id: of_reed-solomon_gf_2_m_api.h 115 2014-04-09 14:00:27Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + +#ifndef OF_REED_SOLOMON_GF_2_M_API_H +#define OF_REED_SOLOMON_GF_2_M_API_H + + +/** + * \struct of_rs_parameters_t + * \brief Reed-Solomon stable codec specific FEC parameter structure. + * This structure contains the pieces of information required to initialize a codec instance, + * using the of_set_fec_parameters() function. + */ +typedef struct of_rs_2_m_parameters +{ + UINT32 nb_source_symbols; /* must be 1st item */ + UINT32 nb_repair_symbols; /* must be 2nd item */ + UINT32 encoding_symbol_length; /* must be 3rd item */ + /* + * FEC codec id specific attributes follow... + */ + UINT16 m; /* WARNING: was bit_size */ + +} of_rs_2_m_parameters_t; + +#endif /* OF_REED_SOLOMON_GF_2_M_API_H */ + +#endif /*#ifdef OF_USE_REED_SOLOMON_CODEC_2_M */ diff --git a/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m_includes.h b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m_includes.h new file mode 100644 index 0000000..7ebbceb --- /dev/null +++ b/thirdparty/openfec/src/lib_stable/reed-solomon_gf_2_m/of_reed-solomon_gf_2_m_includes.h @@ -0,0 +1,60 @@ +/* $Id: of_reed-solomon_gf_2_m_includes.h 189 2014-07-16 08:53:50Z roca $ */ +/* + * OpenFEC.org AL-FEC Library. + * (c) Copyright 2009 - 2012 INRIA - All rights reserved + * Contact: vincent.roca@inria.fr + * + * This software is governed by the CeCILL-C license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL-C + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ + +#ifndef OF_REED_SOLOMON_2M_INCLUDES_H +#define OF_REED_SOLOMON_2M_INCLUDES_H + +#include +#include +#include +#include + +#include "../../lib_common/of_openfec_api.h" + +/* + * the remaining includes will only be considered if of_codec_profile.h is + * included above by of_openfec_api.h => of_openfec_profile.h + */ +#ifdef OF_USE_REED_SOLOMON_2_M_CODEC + +#include "../../lib_common/linear_binary_codes_utils/of_linear_binary_code.h" + +#include "of_reed-solomon_gf_2_m_api.h" +#include "of_reed-solomon_gf_2_m.h" +#include "galois_field_codes_utils/of_galois_field_code.h" +#include "galois_field_codes_utils/algebra_2_4.h" +#include "galois_field_codes_utils/algebra_2_8.h" + + +#endif //OF_USE_REED_SOLOMON_2_M_CODEC +#endif //OF_REED_SOLOMON_INCLUDES_H diff --git a/thirdparty/openfec/xmake.lua b/thirdparty/openfec/xmake.lua new file mode 100644 index 0000000..b6dfd69 --- /dev/null +++ b/thirdparty/openfec/xmake.lua @@ -0,0 +1,19 @@ +package("openfec") + + set_homepage("http://openfec.org/") + set_license("CeCCIL-C") + + set_sourcedir(os.scriptdir()) + on_install(function (package) + local configs = {} + table.insert(configs, "-DDEBUG:STRING=" .. (package:debug() and "ON" or "OFF")) + table.insert(configs, "-DLIBRARY_OUTPUT_PATH=" .. (path.join(package:installdir(), "lib"))) + + import("package.tools.cmake").install(package, configs) + os.cp("src", package:installdir()) + package:add("includedirs", "src") + end) + + on_test(function (package) + assert(package:has_cfuncs("of_create_codec_instance", {includes = "lib_common/of_openfec_api.h"})) + end) \ No newline at end of file diff --git a/thirdparty/xmake.lua b/thirdparty/xmake.lua index 6e84f24..e701f25 100644 --- a/thirdparty/xmake.lua +++ b/thirdparty/xmake.lua @@ -1,3 +1,4 @@ +includes("openfec") if is_plat("windows") then elseif is_plat("linux") then includes("ffmpeg") diff --git a/xmake.lua b/xmake.lua index 341b749..a36c8b8 100644 --- a/xmake.lua +++ b/xmake.lua @@ -33,6 +33,7 @@ includes("thirdparty") if has_config("server_only") then includes("application/signal_server") else + add_requires("openfec") if is_os("windows") then add_requires("vcpkg::ffmpeg 5.1.2", {configs = {shared = false}}) add_requires("vcpkg::libnice 0.1.21") @@ -242,4 +243,16 @@ else "pcre2-8", "pcre2-16", "pcre2-32", "pcre2-posix", "zlib", "ffi", "libcrypto", "libssl", "intl", "iconv", "charset", "bz2", "Shell32", "Advapi32", "Dnsapi", "Shlwapi", "Iphlpapi") + + target("fec_client") + set_kind("binary") + add_packages("openfec") + add_files("tests/fec/simple_client.cpp") + add_includedirs("tests/fec") + + target("fec_server") + set_kind("binary") + add_packages("openfec") + add_files("tests/fec/simple_server.cpp") + add_includedirs("tests/fec") end \ No newline at end of file