add flag to print counts in entropy calculation
authorGeoffrey Allott <geoffrey@allott.email>
Sun, 25 Sep 2022 16:54:15 +0000 (17:54 +0100)
committerGeoffrey Allott <geoffrey@allott.email>
Sun, 25 Sep 2022 16:54:15 +0000 (17:54 +0100)
tools/entropy.c

index bb5a69c45953471ec01406306d59c9d5a792c74f..fc2cbe9dbc1a942004ea6d6a02424f998d824c2d 100644 (file)
@@ -6,7 +6,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-static double bit_entropy(FILE *input, int bits, int chain_len, int low_est_threshold)
+static double bit_entropy(FILE *input, int bits, int chain_len, int low_est_threshold, int print_counts)
 {
     size_t *counts;
     uint8_t *chain;
@@ -37,6 +37,16 @@ static double bit_entropy(FILE *input, int bits, int chain_len, int low_est_thre
         }
     }
 
+    if (print_counts) {
+        for (i = 0; i < ((size_t) 1 << (bits * (chain_len - 1))); ++i) {
+            for (j = 0, subtotal = 0; j < ((size_t) 1 << bits); ++j) {
+                for (k = 0; k + 1 < (size_t) chain_len; ++k)
+                    printf("%02x ", (i >> ((size_t) bits * ((size_t) chain_len - k - 2))) & (((size_t) 1 << bits) - 1));
+                printf("%02x: %lu\n", j, counts[(i << bits) + j]);
+            }
+        }
+    }
+
     entropy = 0;
     total = 0;
     for (i = 0; i < ((size_t) 1 << (bits * (chain_len - 1))); ++i) {
@@ -78,15 +88,16 @@ static void usage(void)
         "    -b - Decode the specified number of bits at a time (1, 2, 4, or (default) 8)\n"
         "    -c - Keep a markov chain `len' symbols long (default 1)\n"
         "    -t - Estimate maximal entropy if subtotal < `threshold' (default 0)\n"
+        "    -p - Print all symbol counts for the file\n"
     );
 }
 
 int main(int argc, char *argv[])
 {
-    int opt, bits = 8, chain_len = 1, low_est_threshold = 0;
+    int opt, bits = 8, chain_len = 1, low_est_threshold = 0, print_counts = 0;
     FILE *input;
 
-    while ((opt = getopt(argc, argv, "hb:c:t:")) != -1) {
+    while ((opt = getopt(argc, argv, "hb:c:t:p")) != -1) {
         switch (opt) {
         case 'h':
             usage();
@@ -100,6 +111,12 @@ int main(int argc, char *argv[])
         case 't':
             low_est_threshold = atoi(optarg);
             break;
+        case 'p':
+            print_counts = 1;
+            break;
+        default:
+            usage();
+            return 1;
         }
     }
 
@@ -112,7 +129,7 @@ int main(int argc, char *argv[])
     argc -= optind;
 
     if (argc == 0) {
-        printf("%f\n", bit_entropy(stdin, bits, chain_len, low_est_threshold));
+        printf("%f\n", bit_entropy(stdin, bits, chain_len, low_est_threshold, print_counts));
     } else {
         for (; argc > 0; --argc, ++argv) {
             input = fopen(argv[0], "rb");
@@ -120,7 +137,7 @@ int main(int argc, char *argv[])
                 fprintf(stderr, "entropy: fopen: %s: %s\n", argv[0], strerror(errno));
                 return 1;
             }
-            printf("%s:\t%f\n", argv[0], bit_entropy(input, bits, chain_len, low_est_threshold));
+            printf("%s:\t%f\n", argv[0], bit_entropy(input, bits, chain_len, low_est_threshold, print_counts));
             fclose(input);
         }
     }