summaryrefslogtreecommitdiff
path: root/src/entropy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/entropy.c')
-rw-r--r--src/entropy.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/entropy.c b/src/entropy.c
new file mode 100644
index 0000000..a70789a
--- /dev/null
+++ b/src/entropy.c
@@ -0,0 +1,65 @@
+
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "entropy.h"
+
+// shitty log2 function to avoid linking to -lm
+static inline double entropy_log2(double x) {
+ if (x <= 0.0) {
+ return -1e9;
+ }
+
+ union { double d; uint64_t i; } vx = { x };
+ int exp = (int)((vx.i >> 52) & 0x7FF) - 1023;
+ vx.i &= ((1ULL << 52) - 1);
+ vx.i |= 0x3FF0000000000000ULL;
+
+ double m = vx.d;
+ double log2_m = (m - 1.0) - (m - 1.0) * (m - 1.0) * 0.5;
+ return (double)exp + log2_m;
+}
+
+// Initialize entropy context
+void entropy_init(struct entropy_ctx *ctx) {
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+// Update entropy context
+void entropy_update(struct entropy_ctx *ctx, const unsigned char *buf, size_t len) {
+
+ size_t i;
+ for (i = 0; i + 4 < len; i += 4) {
+ ctx->freq[buf[i]]++;;
+ ctx->freq[buf[i + 1]]++;
+ ctx->freq[buf[i + 2]]++;
+ ctx->freq[buf[i + 2]]++;
+ }
+
+ // process the remaining bytes
+ for(; i < len; i++) {
+ ctx->freq[buf[i]]++;
+ }
+
+ ctx->total_bytes += len;
+}
+
+// Finalize entropy context
+double entropy_final(struct entropy_ctx *ctx) {
+ if (ctx->total_bytes == 0) {
+ return 0.0;
+ }
+
+ double entropy = 0.0;
+ for (int i = 0; i < 256; i++) {
+ if (ctx->freq[i] == 0) {
+ continue;
+ }
+ double p = (double)ctx->freq[i] / (double)ctx->total_bytes;
+ entropy -= p * entropy_log2(p);
+ //entropy -= p * log2(p);
+ }
+
+ return entropy;
+}