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
|
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string>
#include <vector>
#include <zlib.h>
#include "error.h"
#include "log.h"
#include "utils.h"
#include "math.h"
bit_count_estimator::bit_count_estimator(const bit_count_estimator_type_t type_in) : type(type_in)
{
}
int bit_count_estimator::get_bit_count(const unsigned char *const data, const unsigned int n_bytes)
{
if (n_bytes == 0)
return 0;
#ifdef _DEBUG
int sh = determine_number_of_bits_of_data_shannon(data, n_bytes);
int compr = determine_number_of_bits_of_data_compression(data, n_bytes);
dolog(LOG_DEBUG, "in: %d, shannon: %d, compression: %d", n_bytes * 8, sh, compr);
if (type == BCE_SHANNON)
return sh;
else if (type == BCE_COMPRESSION)
return compr;
#else
if (type == BCE_SHANNON)
return determine_number_of_bits_of_data_shannon(data, n_bytes);
else if (type == BCE_COMPRESSION)
return determine_number_of_bits_of_data_compression(data, n_bytes);
#endif
error_exit("Bit count estimator: unknown mode");
return -1;
}
int bit_count_estimator::determine_number_of_bits_of_data_shannon(const unsigned char *const data, const unsigned int n_bytes)
{
double ent = 0.0, nbytesd = double(n_bytes);
int cnts[256];
memset(cnts, 0x00, sizeof cnts);
for(unsigned int loop=0; loop<n_bytes; loop++)
cnts[data[loop]]++;
for(unsigned int loop=0; loop<256; loop++)
{
if (cnts[loop])
{
double prob = double(cnts[loop]) / nbytesd;
ent += prob * log2(1.0 / prob);
}
}
ent *= nbytesd;
if (ent < 0.0)
ent=0.0;
ent = std::min(nbytesd * 8.0, ent);
return ent;
}
int bit_count_estimator::determine_number_of_bits_of_data_compression(const unsigned char *const data, const unsigned int n_bytes)
{
uLongf destLen = n_bytes * 2 + 512;
unsigned char *dest = new unsigned char[destLen];
int rc = -1;
if ((rc = compress2(dest, &destLen, data, n_bytes, 9)) != Z_OK)
error_exit("Failed invoking zlib %d", rc);
delete [] dest;
// zlib adds a 6 byte header
double factor = double(destLen - 6) / double(n_bytes);
return int(factor * double(n_bytes) * 8.0);
}
|