// ANSCoder.cpp Asymmetric Numeral System Coder // (C) 2009, Andrew Polar under GPL ver. 3. // Released Feb. 05, 2009. // // LICENSE // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 3 of // the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details at // Visit . // // This is implementation of the concept of ANS coder suggested by Jarek Duda at // http://demonstrations.wolfram.com/DataCompressionUsingAsymmetricNumeralSystems/ // and reduced to practice by Andrew Polar. // First version May 24, 2008 // This version Feb 5, 2009 // #include #include #include #include #include //this parameters is a trade off between compression ratio and speed. //the higher the value the better compression. const unsigned char PRECISION = 4; //must not be less than 2 double entropy24_zero_min(int* data, int size) { int min, max, counter; int* buffer; double entropy; double log2 = log(2.0); double prob; min = 0; max = data[0]; for (counter=0; counter max) max = data[counter]; } buffer = (int*)malloc((max+1)*sizeof(int)); memset(buffer, 0x00, (max+1)*sizeof(int)); for (counter=0; counter 0) { prob = (double)buffer[counter]; prob /= (double)size; entropy += log(prob)/log2*prob; } } entropy *= -1.0; if (buffer) free(buffer); return entropy; } double round(double x) { if ((x - floor(x)) >= 0.5) return ceil(x); else return floor(x); } double MakeData(int* data, int data_size, int min, int max, int redundancy_factor) { int counter, cnt, high, low; double buf; if (redundancy_factor <= 1) redundancy_factor = 1; if (max <= min) max = min + 1; srand((unsigned)time(0)); for (counter=0; counter high) high = data[counter]; if (data[counter] < low) low = data[counter]; } for (counter=0; counter 0) { D >>= 1; ++len; } return len; } void GetOrder(int* data, int* order, int size) { int min = data[0]; int max = data[0]; for (int i=0; i data[i]) min = data[i]; if (max < data[i]) max = data[i]; } if (min == max) { for (int i=0; i tmp[i]) { min = tmp[i]; pos = i; } } order[k] = pos; tmp[pos] = max; } if (tmp) free(tmp); } void CollectStatistics(int* data, int data_size, int* freq, int nSymbols, int PROBABILITY_PRECISION) { memset(freq, 0x00, nSymbols*sizeof(int)); for (int i=0; i MAX_STATE) break; if (chart[state] == denominator) { chart[state] = order[i]; ++sizes[order[i]]; break; } }while (true); } } } } if (order) free(order); } void MakeDESCENDTable(int** descend, int* chart, int* sizes, int nSymbols, int PROBABILITY_PRECISION, int MAX_STATE) { int denominator = 1< sizes[source[i]]-1) { ++bit; byte |= state & 1; if (bit == 8) { result[res_size++] = byte; bit = 0; byte = 0; } else { byte <<=1; } state >>= 1; } state = descend[source[i]][state]; if (state < control_MASK) { printf("problem with data symbol %d %d %d\n", i, source[i], state); encodingIsCorrect = false; break; } } int byte_offset; if (bit == 0) { byte_offset = 0; } else { byte_offset = 8 - bit; result[res_size++] = byte << (7 - bit); } memcpy(result + res_size, &byte_offset, 1); res_size += 1; memcpy(result + res_size, &byte_size, 4); res_size += 4; memcpy(result + res_size, &state, 4); res_size += 4; //end encoding if (freq) free(freq); if (descend) { for (int i=0; i=0; --i) { decoded[i] = ascendSymbol[state]; state = ascendState[state]; while (state < MASK) { state <<= 1; state |= (data[counter] & (1<>shift; ++shift; if (shift == 8) { shift = 0; --counter; } } } //end decoding if (ascendSymbol) free(ascendSymbol); if (ascendState) free(ascendState); if (descend) { for (int i=0; i=0; --i) { if (source[i] != test_sample[i]) { printf("Error, data mismatch %d %d %d\n", i, source[i], test_sample[i]); isOK = false; break; } } //end test if (isOK == true) { printf("Round trip is OK\n\n"); } else { printf("Round trip failed\n\n"); } if (source) free(source); if (result) free(result); if (test_sample) free(test_sample); }