/*
 * Title: library.c
 * Author: Jed Marti KI7NNP
 * Description: Keeps a list of already completed tests by major values to avoid needless 
 *   repetition. Uses a power of 2 hash table and quadratic search.
 * Revision History: (Created Wed Feb  1 08:47:18 2023)
 *   Sun Feb 26 18:13:24 2023 - JBM add w0 back.
 *   Sun Dec  3 11:49:58 2023 - JBM Switch to generic equationhs.
 */


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

#include "equations.h"
#include "indequ.h"


// A library of already completed results. This is setup for a quadratic search.
result *lib[HTABLESIZE];

// Count of entries.
uint64_t libCnt = 0;

// The number of rejects - attempts to retry parameters already tested.
uint64_t rejects = 0;


void initLibrary(void)
/*     Clear the quadratic search hash table to empty.
 */
{
  int32_t i;
  for (i = 0; i < HTABLESIZE; ++i) lib[i] = NULL;
}



static uint32_t hashResult(result *r)
/*     Create a hash code for a result r. This is masked to the table size. It also assumes that
 *   the result values are doubles which are treated as their bits for the exclusive OR.
 * Parameters:
 *   r: The base parameter values structure to check for library presence.
 * External References:
 *   HTABLESIZE: library size. Must be power of 2.
 * Returned values: Hash code into table for quadratic search. The hash will put some
 *     2^(64 - log2(HASHTABLESIZE))
 *   possible entries into each quadratic string.
 * Errors detected: none
 */
{
  uint32_t h;

  h = r->flags;
#define X(nme) h ^= (uint64_t) (r->nme);
  VARS
#undef X
  return ((uint32_t) h) & (HTABLESIZE - 1);
}
  


static uint8_t entriesEqual(result *l, result *r)
/*     Are two library entries equal? 
 * Parameters:
 *   l: library entry.
 *   r: New parameters to test.
 * External References: none
 * Returned values: 1 they're equal, 0 they're not.
 * Errors detected: none
 */
{
  if ((l->flags == r->flags) &&
#define X(nme) l->nme == r->nme &&
      VARS
#undef X
      1)
    return 1;
  return 0;
}


uint8_t doneAlready(result *r)
/*     Search lib for entry already tested. Uses hash table quadratic search based on flags and 
 *   values. Each search will be at worst log2(HTABLESIZE) entries. Default size (~32 million) is 25.
 * Parameters:
 *   r: See if this one's been done already.
 * External References:
 *   lib[]: Hash table of worked entries. 
 *   HTABLESIZE: Constant, see indequ.h. Size must be a power of 2 for quadratic search
 *     to work.
 * Returned values: 0 if already in table, 1 if not.
 * Errors detected: Symbol table is full, causes halt.
 */
{
  result *l;

  uint32_t i;
  uint32_t inc;

  // Get hash code in table.
  i = hashResult(r);
  inc = 1;
  while (inc < HTABLESIZE)
  {
    if (lib[i] == NULL)
    {
      lib[i] = cloneResult(r);
      ++libCnt;
      return  0;
    }
    if (entriesEqual(lib[i], r))
    {
      ++rejects;
      return 1;
    }
    i = (i + inc) & (HTABLESIZE - 1);
    ++inc;
  }
  fprintf(stderr, "%s (%s:%d) Symbol table overflow\n", __FILE__, __func__, __LINE__);
  exit(-1);
}



// EOF
