OverviewFilesCommitsIssuesDocsReleasesPeers

atomspace-layer-discovery / experiments / ladder / port / count.c

75 lines · c ref:
// Port of Linas's counting pipe (learn scm/pipe-parse/pipe-count.scm make-parse-pipe): every atom the parser
// emits gets its count (TruthValueKey index 2) incremented by one. For LgParseBonds the atoms are the
// parse's words and its edges; for LgParseSections they are its Sections and its edges (words not counted).
//
// Input: one or more recorded-parse files (<window>\t<parse>\t<atom>, from oracle/g0.scm), applied in order,
// so `count parses-A.tsv parses-C.tsv` gives the counts after stage C (which adds onto stage A's).
//
//   count <parses.tsv>... > counts.tsv

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct { char *atom; double n; } ent_t;

static ent_t *ents;
static size_t nents, capents, tmask = 65535;
static long *tab;

static uint64_t fnv (const char *s) {
  uint64_t h = 1469598103934665603ULL;
  while (*s) h = (h ^ (unsigned char) *s++) * 1099511628211ULL;
  return h;
}

static void grow (void) {
  tmask = tmask * 2 + 1;
  free(tab);
  tab = malloc(sizeof(long) * (tmask + 1));
  for (size_t i = 0; i <= tmask; i++) tab[i] = -1;
  for (size_t k = 0; k < nents; k++) {
    size_t i = fnv(ents[k].atom) & tmask;
    while (tab[i] >= 0) i = (i + 1) & tmask;
    tab[i] = k;
  }
}

static void incr (const char *atom) {
  size_t i = fnv(atom) & tmask;
  while (tab[i] >= 0) {
    if (!strcmp(ents[tab[i]].atom, atom)) { ents[tab[i]].n += 1; return; }
    i = (i + 1) & tmask;
  }
  if (nents == capents) { capents = capents ? capents * 2 : 4096; ents = realloc(ents, sizeof(ent_t) * capents); }
  ents[nents] = (ent_t) { strdup(atom), 1 };
  tab[i] = nents++;
  if (nents * 2 > tmask) grow();
}

int main (int argc, char **argv) {
  if (argc < 2) { fprintf(stderr, "usage: count <parses.tsv>...\n"); return 1; }
  tab = malloc(sizeof(long) * (tmask + 1));
  for (size_t i = 0; i <= tmask; i++) tab[i] = -1;
  static char line[1 << 16];
  for (int a = 1; a < argc; a++) {
    FILE *f = fopen(argv[a], "r");
    if (!f) { perror(argv[a]); return 1; }
    long nline = 0;
    while (fgets(line, sizeof line, f)) {
      nline++;
      size_t len = strlen(line);
      if (len && line[len - 1] == '\n') line[--len] = 0;
      else if (len == sizeof line - 1) { fprintf(stderr, "%s:%ld: line too long\n", argv[a], nline); return 1; }
      char *atom = strchr(line, '\t');
      if (atom) atom = strchr(atom + 1, '\t');
      if (!atom) { fprintf(stderr, "%s:%ld: malformed\n", argv[a], nline); return 1; }
      incr(atom + 1);
    }
    fclose(f);
  }
  for (size_t k = 0; k < nents; k++) printf("%s\t(PredicateNode \"*-TruthValueKey-*\")\t0 0 %.17g\n", ents[k].atom, ents[k].n);
  return 0;
}