/* Title: compare.c
 * Author: Jed Marti
 * Description: Read a CSV file and compare the measured values against the different equations.
 * Created Sat Jan 20 13:58:06 2024
 */


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

#include "compare.h"
#include "equations.h"

// The list of inductors read in.
extern anInductor *theInductors;

 static double sqr(double x) { return x * x; }

int32_t main(int32_t argc, char *argv[])
/*     Accept command line arguments:
 *             inductor inductors.csv
 *     The csv file is built from raw data files. The columns are:
 *   Henrys: The inductance in Henries.
 *   Radius: The coil radius in meters.
 *   wire: The wire diameter in inches.
 *   gauge: The wire gauge.
 *   Turns: The number of turns.
 *   Length: The coil length in meters. 
 *   FileName: The raw CSV file from whence it came.
 * Parameters: Typical C command line.
 * External References:
 *   theInductors: A list of inductors from the CSV test file.
 * Returned values: 0 for OK, -1 for error.
 * Errors detected: No file to test against, bad CSV file.
 */
{
  double ARRLOriginalSum = 0.0;
  double ARRLTurnsSum = 0.0;
  double ARRLcspacingSum = 0.0;
  double ARRLall22Sum = 0.0;
  double ARRLallSum = 0.0;
  double RFCSum = 0.0;
  double RF1Sum = 0;0;
  double LundinSum = 0.0;
  double MillerSum = 0.0;
  double Equation8Sum = 0.0;
  double EquationDSum = 0.0;
  double EquationASum = 0.0;
  double SimpleSum = 0.0;
  double EquationFSum = 0.0;
  double EquationGSum = 0.0;
  double EquationHSum = 0.0;
  double EquationISum = 0.0;
  
  anInductor *ind;
  double     rv;
  int32_t    cnt = 0;
  
  int32_t    mint, maxt;
  int32_t    ming, maxg;
  double     minh, maxh;
  double     minrad, maxrad;
  double     minlen, maxlen;

  printf("compare V%d.%02d.%03d\n", VERSION, RELEASE, PATCH);
  
  if (argc != 2)
  {
    fprintf(stderr, "Usage: compare inductors.csv\n\
Run all the forumlae against the database of inductors and give RMS error.\n");
    exit(-1);
  }

  readTestInductors(argv[1]);

  // Get the ranges
  minlen = minrad = minh = 1.0e6;
  maxlen = maxrad = maxh = -1.0e6;
  mint = ming = 1000;
  maxt = maxg = -1000;
  for (ind = theInductors; ind != NULL; ind = ind->next)
  {
    if (ind->L < minh) minh = ind->L;
    if (ind->L > maxh) maxh = ind->L;

    if (ind->R < minrad) minrad = ind->R;
    if (ind->R > maxrad) maxrad = ind->R;

    if (ind->G < ming) ming = ind->G;
    if (ind->G > maxg) maxg = ind->G;

    if (ind->LEN < minlen) minlen = ind->LEN;
    if (ind->LEN > maxlen) maxlen = ind->LEN;

    if (ind->N < mint) mint = ind->N;
    if (ind->N > maxt) maxt = ind->N;
  }

  printf("Limits:\n");
  printf("  Turns      %d -> %d\n", mint, maxt);
  printf("  Gauge     #%d -> #%d\n", ming, maxg);
  printf("  Diameter  %g\" -> %g\"\n", meters2inches(2.0 * minrad), meters2inches(2.0 * maxrad));
  printf("  Length    %g\" -> %g\"\n", meters2inches(minlen), meters2inches(maxlen));
  printf("  Ind.      %g uH -> %g uH\n\n", minh, maxh);

  for (ind = theInductors; ind != NULL; ind = ind->next)
  {
    ++cnt;

    // Original uses radius, turns, length, results in uH.
    rv = ARRLOriginal(ind->R, ind->N, ind->LEN, 0.0);
    rv /= 1.0E6;
    ARRLOriginalSum += sqr((ind->L - rv) / ind->L);

    // ARRL equation optimized for turns. Results in uH.
    rv = ARRLTurns(ind->R, ind->N, ind->LEN, 0.0);
    rv /= 1.0E6;
    ARRLTurnsSum += sqr((ind->L - rv) / ind->L);

    // Optimized for cspacing.
    rv = ARRLcspacing(ind->R, ind->N, ind->LEN, 0.0);
    rv /= 1.0E6;
    ARRLcspacingSum += sqr((ind->L - rv) / ind->L);

    // For all 22 gauge wire. Results in uH.
    rv = ARRLall22(ind->R, ind->N, ind->LEN, 0.0);
    rv /= 1.0E6;
    ARRLall22Sum += sqr((ind->L - rv) / ind->L);

    // Optimized for all coils.
    rv = ARRLall(ind->R, ind->N, ind->LEN, 0.0);
    rv /= 1.0E6;
    ARRLallSum += sqr((ind->L - rv) / ind->L);

    // RFC in metric. Results in uH.
    rv = rfc(ind->R, ind->N, ind->LEN, 0.0);
    rv /= 1.0E6;
    RFCSum += sqr((ind->L - rv) / ind->L);

    // All metric.
    rv = rf1(ind->R, ind->N, ind->LEN, 0.0);
    rv /= 1.0E6;
    RF1Sum += sqr((ind->L - rv) / ind->L);

    // Lundin, all metric, results in Henries.
    rv = lundin(ind->R, ind->N, ind->LEN, 0.0);
    LundinSum += sqr((ind->L - rv) / ind->L);

    // Miller all metric, results in Henries.
    rv = miller(ind->R, ind->N, ind->LEN, 0.0);
    MillerSum += sqr((ind->L - rv) / ind->L);

    // Equation 8, all metric, results in Henries.
    rv = Equation8(ind->R, ind->N, ind->LEN, 0.0);
    Equation8Sum += sqr((ind->L - rv) / ind->L);

    // Equation A, all metric, results in Henries.
    rv = EquationA(ind->R, ind->N, ind->LEN, 0.0);
    EquationASum += sqr((ind->L - rv) / ind->L);

    // Equation D, all metric, results in Henries.
    rv = EquationD(ind->R, ind->N, ind->LEN, ind->W);
    EquationDSum += sqr((ind->L - rv) / ind->L);

    // Equation F, all metric, results in Henries.
    rv = EquationF(ind->R, ind->N, ind->LEN, 0.0);
    EquationFSum += sqr((ind->L - rv) / ind->L);

    // Equation G, all metric, results in Henries.
    rv = EquationG(ind->R, ind->N, ind->LEN, 0.0);
    EquationGSum += sqr((ind->L - rv) / ind->L);

    // Equation H, all metric, results in Henries.
    rv = EquationH(ind->R, ind->N, ind->LEN, 0.0);
    EquationHSum += sqr((ind->L - rv) / ind->L);

    // Equation I, all metric, results in Henries.
    rv = EquationI(ind->R, ind->N, ind->LEN, ind->W);
    EquationISum += sqr((ind->L - rv) / ind->L);

    // Simple, all metric, results in Henries.
    rv = Simple(ind->R, ind->N, ind->LEN, 0.0);
    SimpleSum += sqr((ind->L - rv) / ind->L);
  }

  printf("Working %s\n", argv[1]);
  printf("Original ARRL error %6.2f%%\n", 100.0 * sqrt(ARRLOriginalSum / cnt));
  printf("ARRL Turns error    %6.2f%%\n", 100.0 * sqrt(ARRLTurnsSum / cnt));
  printf("ARRL cspacing error %6.2f%%\n", 100.0 * sqrt(ARRLcspacingSum / cnt));
  printf("ARRL all22 error    %6.2f%%\n", 100.0 * sqrt(ARRLall22Sum / cnt));
  printf("ARRL all error      %6.2f%%\n", 100.0 * sqrt(ARRLallSum / cnt));
  printf("RFC error           %6.2f%%\n", 100.0 * sqrt(RFCSum / cnt));
  printf("RF1 error           %6.2f%%\n", 100.0 * sqrt(RF1Sum / cnt));
  printf("Lundin error        %6.2f%%\n", 100.0 * sqrt(LundinSum / cnt));
  printf("Miller error        %6.2f%%\n", 100.0 * sqrt(MillerSum / cnt));
  printf("\n");
  printf("Simple error        %6.2f%%\n", 100.0 * sqrt(SimpleSum / cnt));
  printf("Equation 8 error    %6.2f%%\n", 100.0 * sqrt(Equation8Sum / cnt));
  printf("Equation A error    %6.2f%%\n", 100.0 * sqrt(EquationASum / cnt));
  printf("Equation D error    %6.2f%%\n", 100.0 * sqrt(EquationDSum / cnt));
  printf("Equation F error    %6.2f%%\n", 100.0 * sqrt(EquationFSum / cnt));
  printf("Equation G error    %6.2f%%\n", 100.0 * sqrt(EquationGSum / cnt));
  printf("Equation H error    %6.2f%%\n", 100.0 * sqrt(EquationHSum / cnt));
  printf("Equation I error    %6.2f%%\n", 100.0 * sqrt(EquationISum / cnt));
  exit(0);
}


// EOF
