/* Title: equations.c
 * Author: Jed Marti
 * Description: The various inductor equations.
 * Created Sat Jan 20 13:58:06 2024
 *   Thu Jan 25 17:14:23 2024 - Extracted for use everywhere.
 */

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

#include "equations.h"

equations allEqs[] = {
  {.computeUh = ARRLOriginal, .recommend = recARRLOriginal},
  {.computeUh = ARRLTurns, .recommend = recARRLTurns},
  {.computeUh = ARRLcspacing, .recommend = recARRLcspacing},
  {.computeUh = ARRLall22, .recommend = recARRLall22},
  {.computeUh = ARRLall, .recommend = recARRLall},
  {.computeUh = Simple, .recommend = recSimple},
  {.computeUh = Equation8, .recommend = recEquation8},
  {.computeUh = EquationA, .recommend = recEquationA},
  {.computeUh = EquationD, .recommend = recEquationD},
  {.computeUh = EquationF, .recommend = recEquationF},
  {.computeUh = EquationG, .recommend = recEquationG},
  {.computeUh = EquationH, .recommend = recEquationH},
  {.computeUh = EquationI, .recommend = recEquationI},
  {.computeUh = rfc, .recommend = recrfc},
  {.computeUh = rf1, .recommend = recrf1},
  {.computeUh = lundin, .recommend = reclundin},
  {.computeUh = miller, .recommend = recmiller}
};


// Some common functions - optimization probably open codes.
static double sqr(double x) { return x * x; }
static double cube(double x) { return x * x * x; }
static double quart(double x) { return x * x * x * x; }
static double quint(double x) { return x * x * x * x * x; }

static double sqri(int32_t x) { return (double) (x * x); }
static double cubei(int32_t x) { return (double) (x * x * x); }


static void ellipticalSolver(double *fk, double *ek, double k)
/*     Used by the Miller solver.
 *  Recurrence relation:
 *      a[0] = 1
 *      b[0] = sqrt(1 - k^2)
 *      c[0] = k
 *      a[n] = 0.5(a[n-1] + b[n-1])
 *      b[n] = sqrt(1 - k^2)
 *      c[n] = 0.5(a[n-1] - b[n-1])
 *   until c[n] == 0.0 or 32 iterations.
 * Parameters:
 *   fk: address to put F(k)
 *   ek: address to put E(k)
 *   k: Value to solve around.
 * External References: none
 * Returned values: F[k], E[k] in addresses.
 * Errors detected: none.
 */
{
  double  a, b, c;
  double  an, bn, cn;
  int32_t n;
  double  pown;
  double  sum;

  // Initial conditions.
  a = 1.0;
  b = sqrt(1.0 - sqr(k));
  c = k;
  pown = 1.0;
  sum = 0.0;

  // Run to convergence or 32 bits worth.
  for (n = 0; n < 32 && c > 0.0; ++n)
  {
    sum += pown * sqr(c);
    pown *= 2.0;
    an = (a + b) / 2.0;
    bn = sqrt(a * b);
    cn = (a - b) / 2.0;
    a = an;
    b = bn;
    c = cn;
  }

  // Here are the solutions.
  *fk = M_PI / (2.0 * a);
  *ek = *fk * (1.0 - sum / 2.0);
}



double miller(double rm, int32_t turns, double len, double wm)
/*     Build up for Wheeler's formula itself a rehash of Lorenz. Solve the equations and return
 *   the inductance in microHenries.
 * Parameters:
 *   dia: Coil diameter in inches.
 *   len: Coil length in inches.
 *   turns: The number of turns.
 *   wm: wire radius - ignored.
 * External References: none
 * Returned value: inductance in microHenries.
 */
{
  double a;
  double c;
  double d;
  double n;
  double k;
  double fk;
  double ek;
  double K;

  // Get set up for the elliptical equations.
  a  = rm;
  c = len;
  d = sqrt(4.0 * sqr(a) + sqr(c));
  n = turns / c;
  k = (2.0 * a) / d;
  ellipticalSolver(&fk, &ek, k);

  //  Wheeler's  formula.
  K = (1.0 / (3.0 * M_PI)) * ( ((d * c / sqr(a)) * (fk - ek)) + (4.0 * d / c) * ek - 8.0 * a / c);
  return (u0 * sqr(turns) * M_PI * sqr(a) / c) * K;
}



uint8_t recmiller(double rm, int32_t turns, double len, double wm)
/*     Never does well.
 * Parameters:
 *   dia: Coil diameter in inches.
 *   len: Coil length in inches.
 *   turns: The number of turns.
 *   wm: wire radius
 *   wm: wire radius in meters (ignored).
 * External References: none
 * Returned values: not recommended.
 * Errors detected: none
 */
{
  return notRecommended;
}



double ARRLOriginal(double rm, int32_t n, double lm, double wm)
/*     The original ARRL equation and its coefficients.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters (ignored).
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  double d = 2.0 * meters2inches(rm);
  double l = meters2inches(lm);
  return (sqr(d) * (double) (n * n)) / (18.0 * d + 40.0 * l);
}



uint8_t recARRLOriginal(double rm, int32_t n, double lm, double wm)
/*     The original equation doesn't work well at all, here for completeness.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters (ignored).
 * External References: none
 * Returned values: notRecommended enumeration.
 * Errors detected: none
 */
{
  return notRecommended;
}



double ARRLTurns(double rm, int32_t n, double lm, double wm)
/*     The original ARRL equation but optimized for the small turns.csv data set.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  double d = 2.0 * meters2inches(rm);
  double l = meters2inches(lm);
  return (38.0 * sqr(d) * (double) (n * n)) / (1108.0 * d + 1369.0 * l);
}


uint8_t recARRLTurns(double rm, int32_t n, double lm, double wm)
/*     The original ARRL equation but optimized for the small turns.csv data set. This is
 *   highly recommended for a restricted set of coils. Otherwise not recommended.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters.
 * External References: none
 * Returned values: highly recommended for 22 gauge spacing 0.04 otherewise not recommended.
 * Errors detected: none
 */
{
  if (wm != inches2meters(0.028 / 2.0) ||
      n < 8 ||
      n > 50 ||
      rm != inches2meters(0.5 / 2.0) ||
      (lm  / (double) n) != inches2meters(0.04)) return notRecommended;
  else return highlyRecommended;
}



double ARRLcspacing(double rm, int32_t n, double lm, double wm)
/*     The original ARRL equation but optimized for the small cspacing.csv data set.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters.
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  double d = 2.0 * meters2inches(rm);
  double l = meters2inches(lm);
  return (43.0 * sqr(d) * (double) (n * n)) / (864.0 * d + 1909.0 * l);
}



uint8_t recARRLcspacing(double rm, int32_t n, double lm, double wm)
/*     The original ARRL equation but optimized for the small cspacing.csv data set. 
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters.
 * External References: none
 * Returned values: reasonable for 22 gauge in ranges measured otherwise not recommended.
 * Errors detected: none
 */
{
  if (wm != inches2meters(0.028 / 2.0) ||
      n < 5 || n > 40 ||
      rm < inches2meters(0.258 / 2.0) ||
      rm > inches2meters(0.866 / 2.0)) return notRecommended;
  else return reasonable;
}



double ARRLall22(double rm, int32_t n, double lm, double wm)
/*     The original ARRL equation but optimized for all coils above .5 uH with #22 gauge wire.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters (ignored).
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  double d = 2.0 * meters2inches(rm);
  double l = meters2inches(lm);
  return (18.0 * sqr(d) * (double) (n * n)) / (378.0 * d + 734.0 * l);
}



uint8_t recARRLall22(double rm, int32_t n, double lm, double wm)
/*     The original ARRL equation but optimized for all coils above .5 uH with #22 gauge wire.
 *   Marginal for a few instances.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters (ignored).
 * External References: none
 * Returned values: marginal in range, notRecommended outside.
 * Errors detected: none
 */
{
  if (wm != inches2meters(0.028 / 2.0) ||
      n < 5 || n > 40 ||
      rm < inches2meters(0.261 / 2) || rm > inches2meters(2.0 / 2.0) ||
      lm < inches2meters(0.14) || lm > inches2meters(3.0)) return notRecommended;
  else return marginal;
}



double ARRLall(double rm, int32_t n, double lm, double wm)
/*     The original ARRL equation but optimized for all coils above .5 uH.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire readius in meters (ignored).
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  double d = 2.0 * meters2inches(rm);
  double l = meters2inches(lm);
  return (22.0 * sqr(d) * (double) (n * n)) / (460.0 * d + 921.0 * l);
}



uint8_t recARRLall(double rm, int32_t n, double lm, double wm)
/*     The original ARRL equation but optimized for all coils above .5 uH. Pretty bad.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire readius in meters.
 * External References: none
 * Returned values: reasonable for fixed pitch 22 gauge otherwise not recommended.
 * Errors detected: none
 */
{
  // turntest result is 6.31% so reasonable.
  if (wm == inches2meters(0.028) / 2.0 &&
      n >= 8 && n <= 50 &&
      lm / n == 0.4) return reasonable;

  // cspacing result is 6.09% so reasonable.
  if (wm == inches2meters(0.028) / 2.0 &&
      n >= 5 && n <= 40 &&
      lm >= inches2meters(0.14) && lm <= inches2meters(1.12)) return reasonable;

  // Everything else is not recommended.
  return notRecommended;
}



double Simple(double rm, int32_t n, double lm, double wm)
/*     Used for #22 gauge, reasonable sized coils. Optimized against the cspacing.csv file.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters (ignored).
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  // Goodness = 0.0233759
  double r0 =     0.04577932701610;
  double r1 =    -3.47318092941792;
  double r2 = -32586.59629999914978;
  double r3 = 990000.68900003179442;
  double cd = 459987.89609983825358;
  double t0 = 81262.26570000193897;
  double t1 = -30132.44869999826915;
  double t2 = -1717.08300000000872;
  double t3 =    21.00967900000605;

  return (u0 * (r0 + r1*rm + r2*sqr(rm) + r3*cube(rm)) * (t0 + t1*n + t2*sqri(n) + t3*cubei(n)))
    / cd;
}



uint8_t recSimple(double rm, int32_t n, double lm, double wm)
/*     Used for #22 gauge, reasonable sized coils. Optimized against the cspacing.csv file. Works
 *   for cspacing.csv stuff but thorougly bad elsewhere.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters.
 * External References: none
 * Returned values: recommended for cspacing, not recommended elsewhere.
 * Errors detected: none
 */
{
  if (wm == inches2meters(0.028 / 2.0) &&
      n >= 5 && n <= 40 &&
      rm >= inches2meters(0.0258 / 2.0) && rm <= inches2meters(0.866 / 2.0) &&
      lm >= inches2meters(0.14) && lm <= inches2meters(1.12)) return recommended;
  else return notRecommended;
}



double Equation8(double rm, int32_t n, double lm, double wm)
/*    A pretty bad one that mimics the ARRL equation but with cubics.  
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters.
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  double num;
  double den;

  // Goodness = 0.101614
  double  rd0 =    71.05500000000164;
  double  rd1 = -17000.01999998896645;
  double  rd2 = -100000.00000000000000;
  double   l1 = -1708.85900000022025;
  double   l2 = -22000.00000000000000;
  double   l3 = -23000.00000000000000;
  double  rn0 =    26.46300000000054;
  double  rn1 = -5900.54999999994016;
  double  rn2 = -18000.00000000000000;
  double  rn3 =  1026.20200000002137;
  double   t0 =   499.99899999998360;
  double   t1 =  1207.27999999987560;
  double   t2 = -1310.40100000087477;

  num = u0 * (rn0 + rn1*rm + rn2*sqr(rm) + rn3*cube(rm)) * (t0 + t1*n + t2*sqri(n));
  den = rd0 + rd1*rm + rd2*sqr(rm) + l1*lm + l2*sqr(lm) + l3*cube(lm);
  return num / den;
}



uint8_t recEquation8(double rm, int32_t n, double lm, double wm)
/*    A pretty bad one that mimics the ARRL equation but with cubics. Not recomended.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters.
 * External References: none
 * Returned values: bletcherous.
 * Errors detected: none
 */
{
  return bletcherous;
}



double EquationA(double rm, int32_t n, double lm, double wm)
/*     Radius and length with  quintics. Works well with the 22 gauge coils as wire size isn't
 *   part of the equation. Optimized against all22.csv.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters (ignored).
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  double num;
  double den;

// Goodness = 0.042212
  double r0 =    -0.17800000000000;
  double r1 =    89.85999999999989;
  double r2 = 14065.75999999790838;
  double r3 = 65176.01999999124382;
  double r4 = -3966996.59999996656552;
  double r5 = -4866131.40000447072089;
  double t0 =    71.18799999999275;
  double t1 =   -24.71200000000025;
  double t2 =    -8.06400000000000;
  double l0 =  -758.09600000010414;
  double l1 = -66241.73999998404179;
  double l2 = 190766.85999987658579;
  double l3 = 1997028.80000000027940;
  double l4 = 2176060.00000000000000;
  double l5 = 389613.00000000000000;

  num = u0 * (r0 + r1*rm + r2*sqr(rm) + r3*cube(rm) + r4*quart(rm) + r5*quint(rm)) *
    (t0 + t1*n + t2*sqri(n));
  den = l0 + l1*lm + l2*sqr(lm) + l3*cube(lm) + l4*quart(lm) + l5*quint(lm);
  return num / den;
}



uint8_t recEquationA(double rm, int32_t n, double lm, double wm)
/*     Radius and length with  quintics. Works well with the 22 gauge coils as wire size isn't
 *   part of the equation. Optimized against all22.csv. 
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters.
 * External References: none
 * Returned values: recommended for 22 gauge wire in range otherwise not recommended.
 * Errors detected: none
 */
{
  if (wm == inches2meters(0.028 / 2.0) &&
      rm >= inches2meters(0.261 / 2.0) && rm <= inches2meters(2.0 / 2.0) &&
      lm >= inches2meters(0.14) && lm <= inches2meters(3.0)) return recommended;
  else return notRecommended;
}



double EquationD(double rm, int32_t n, double lm, double wm)
/*     Cubics except on wire size and turns which are quadratic. Best all around performer for
 *   random coils with different wire gauges.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters.
 * External References: none
 * Returned values: Inductance in Henries.
 * Errors detected: none
 */
{
  double num;
  double den;

  // Goodness = 0.0485485
  double r0 =     0.00000000000000;
  double r1 =     0.30519079303306;
  double r2 =   415.87716734474901;
  double r3 = -5385.21525101574753;
  double t0 =  9505.14599999444363;
  double t1 = -3488.24947002016506;
  double t2 =  -998.70297274909854;
  double w0 =    -1.31232586306154;
  double w1 =    11.84295226650429;
  double w2 =  -180.50670000000000;
  double l0 =  2318.86862683093750;
  double l1 = 195665.62995095332735;
  double l2 = -702802.99999999953434;
  double l3 = -1040339.95272062066942;

   num = u0 * (r0 + r1*rm + r2*sqr(rm) + r3*cube(rm)) * (t0 + t1*n + t2*sqri(n)) *
    (w0 + w1*wm + w2*sqr(wm));
  den = l0 + l1*lm + l2*sqr(lm) + l3*cube(lm);
  return num / den;
}



uint8_t recEquationD(double rm, int32_t n, double lm, double wm)
/*     Cubics except on wire size and turns which are quadratic. Best all around performer for
 *   random coils with different wire gauges.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters.
 * External References: none
 * Returned values: reasonable in ranges, not recommended outside.
 * Errors detected: none
 */
{
  if (wm <= inches2meters(0.067 / 2.0) && wm <= inches2meters(0.013 / 2) &&
      rm >= inches2meters(0.261 / 2.0) && rm <= inches2meters(2.0 / 2.0) &&
      lm >= inches2meters(0.14) && lm <= inches2meters(3.0) &&
      n >= 5 && n <= 50) return reasonable;
  else return notRecommended;
}



double EquationF(double rm, int32_t n, double lm, double wm)
/*     Cubics on all, but only optimized for #22 gauge wire. No wire size included. Not a bad job
 *   all around.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters.
 * External References: none
 * Returned values: Inductance in Henries.
 * Errors detected: none
 */
{
  double num;
  double den;
  
// Goodness = 0.0541144
  double r0 =     0.09800000000000;
  double r1 =   -57.40291999999053;
  double r2 = -10949.29838000065320;
  double r3 = -7000.13919999999962;
  double t0 =   -10.00000000000000;
  double t1 =     4.91220000000005;
  double t2 =     1.75840000000000;
  double l0 =  -134.06080000003760;
  double l1 = -9000.00020000434233;
  double l2 = -1501.47499999999991;
  double l3 =    49.51000000000000;

  num = u0 * (r0 + r1*rm + r2*sqr(rm) + r3*cube(rm))*(t0 + t1*n + t2*sqri(n));
  den = l0 + l1*lm + l2*sqr(lm) + l3*cube(lm);
  return num/den;
}



uint8_t recEquationF(double rm, int32_t n, double lm, double wm)
/*     Cubics on all, but only optimized for #22 gauge wire. No wire size included. Not a bad job
 *   all around.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters.
 * External References: none
 * Returned values: recommended for turntest, rasonable for all 22 gauge, marginal for others.
 * Errors detected: none
 */
{
  // alljan24.csv restrictions are marginal outside of #22.
  if (wm != inches2meters(0.028 / 2.0) &&
      n >= 5 && n <= 50 &&
      rm >= inches2meters(0.261 / 2.0) && rm <= inches2meters(2.0 / 2.0) &&
      lm >= inches2meters(0.14) && lm <= inches2meters(3.0)) return marginal;

  // turntest.
  else if (wm == inches2meters(0.028 / 2.0) &&
	   n >= 5 && n <= 50 &&
	   rm >= inches2meters(0.261 / 2.0) && rm <= inches2meters(2.0 / 2.0) &&
	   lm == n * inches2meters(0.04)) return recommended;

  // all22.csv and cspacing.csv.
  else if (wm == inches2meters(0.028 / 2.0) &&
	   n >= 5 && n <= 40 &&
	   rm >= inches2meters(0.261 / 2.0) && rm <= inches2meters(2.0 / 2.0) &&
	   lm >= inches2meters(0.14) && lm <= inches2meters(3.0)) return reasonable;

  else return notRecommended;
}
  


double EquationG(double rm, int32_t n, double lm, double wm)
/*     Cubic on radius and length, quadratic on turns, no wire gauge. Pretty bad all around. 
 *   Probably needs some more runs on the optimizer.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters (ignored).
 * External References: none
 * Returned values: Inductance in Henries.
 * Errors detected: none
 */
{
  double num;
  double den;

  // Goodness = 0.156818
  double rn0 =    -0.76000000000000;
  double rn1 =   340.67999999999910;
  double rn2 =    -0.40000000000000;
  double rn3 = 24999.80000000024302;
  double cd =  2695.40000000000009;
  double rd1 =    -4.45000000000000;
  double rd2 = -6439.00000000000000;
  double t0 =  -416.29999999995550;
  double t1 =   144.18999999997621;
  double t2 =     5.44000000000000;
  double l1 = 24999.80000000067230;
  double l2 =    99.98000000000008;
  double l3 =  3676.61999999999989;

  num = u0 * (rn0 + rn1*rm + rn2*sqr(rm) + rn3*cube(rm)) * (t0 + t1*n + t2*sqri(n));
  den = cd + rd1*rm + rd2*sqr(rm) + l1 + l2*sqr(lm) + l3*cube(lm);
  return num/den;
}


uint8_t recEquationG(double rm, int32_t n, double lm, double wm)
/*     Cubic on radius and length, quadratic on turns, no wire gauge. Pretty bad all around. 
 *   Probably needs some more runs on the optimizer. So don't recommend.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: wire radius in meters.
 * External References: none
 * Returned values: bletcherous.
 * Errors detected: none
 */
{
  return bletcherous;
}



double EquationH(double rm, int32_t n, double lm, double wm)
/*     Turns a function of length. Optimized against cspacing.csv. Does poorly all around.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters (ignored)
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  double num;
  double den;
// Goodness = 0.0881938
  double r0 =   200.05999999999764;
  double r1 = -32705.05999999758569;
  double r2 = 1493771.60000001755543;
  double r3 = -1490874.40999975963496;
  double l0 =   -15.54000000000006;
  double l1 =  7163.15999999994983;
  double l2 = 106422.55999998308835;
  double l3 = 51945.70000000068831;

  num = u0 * (l0 + l1*lm + l2*sqr(lm) + l3*cube(lm));
  den = r0 + r1*rm + r2*sqr(rm) + r3*cube(rm);
  return num / den;
}



uint8_t recEquationH(double rm, int32_t n, double lm, double wm)
/*     Turns a function of length. Optimized against cspacing.csv. Does poorly all around,
 *    bletcherous.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters.
 * External References: none
 * Returned values: bletcherous.
 * Errors detected: none
 */
{
  return bletcherous;
}



double EquationI(double rm, int32_t n, double lm, double wm)
/*     Turns a function of length. Optimized against alljan24.csv. Work in progress, wire size
 *   moved to denominator.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters.
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  double num;
  double den;

  // Goodness = 0.0442219
  double r0 =    -0.12716221980779;
  double r1 =    60.40271717668718;
  double r2 =  6444.10592558200824;
  double r3 =   -99.61924000000008;
  double w0 = -1482.17775341672382;
  double w1 = -9225.04352588244183;
  double w2 =  1008.68999981377294;
  double w3 =     5.16899483100000;
  double t0 =     8.00081726339813;
  double t1 =   777.48701447490737;
  double t2 =  1142.68896854347327;
  double t3 =    -4.79052490058133;
  double l0 =   -32.75276122504449;
  double l1 = -2719.67508315435452;
  double l2 = 11643.08111810707305;
  double l3 =  6239.06140125771981;

  

  num = u0 * (r0 + r1*rm + r2*sqr(rm) + r3*cube(rm)) * (t0 + t1*n + t2*sqri(n) + t3*cube(n));
  den = (w0 + w1*wm + w2*sqr(wm) + w3*cube(wm)) * (l0 + l1*lm + l2*sqr(lm) + l3*cube(lm));

  return num / den;
}


uint8_t recEquationI(double rm, int32_t n, double lm, double wm)
/*     Turns a function of length. Optimized against alljan24.csv. Work in progress, wire size
 *   moved to denominator.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters.
 * External References: none
 * Returned values: Bletcherous for now.
 * Errors detected: none
 */
{
  return bletcherous;
}



double rfc(double rm, int32_t n, double lm, double wm)
/*     Equation from RF Circuit Design. Really ARRL formula for metric.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters (ignored).
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  double diamm = rm * 2000.0;
  double lenmm = lm * 1000.0;
  return (0.0394 * sqr(diamm / 2.0) * sqri(n)) / (4.5 * diamm + 10.0 * lenmm);
}



uint8_t recrfc(double rm, int32_t n, double lm, double wm)
/*     Equation from RF Circuit Design. Really ARRL formula for metric. Never better than
 *   10.3% so not recommended.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters (ignored).
 * External References: none
 * Returned values: not recommended.
 * Errors detected: none
 */
{
  return notRecommended;
}



double rf1(double rm, int32_t n, double lm, double wm)
/*     From Reinhold Ludwig and Gene Bogdanov. RF Circuit Design Theory and Applications. 
 *   Pearson, second edition.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters (ignored).
 * External References: none
 * Returned values: Inductance in MicroHenries.
 * Errors detected: none
 */
{
  double diam = 2.0 * rm;
  return 10.0 * (M_PI * sqr(rm) * u0 * sqri(n)) / (4.5 * diam + 10.0 * lm) * 1.0e6;
}



uint8_t recrf1(double rm, int32_t n, double lm, double wm)
/*     From Reinhold Ludwig and Gene Bogdanov. RF Circuit Design Theory and Applications. 
 *   Pearson, second edition. Never better than 10.45%
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters (ignored).
 * External References: none
 * Returned values: not recommended.
 * Errors detected: none
 */
{
  return notRecommended;
}


static double f1(double x)
// For Lundin approximation.
{  return (1.0 + 0.383901*x + 0.017108*sqr(x))/ (1.0 + 0.258952 * x); }

static double f2(double x)
// For Lundin approximation.
{  return  0.093842*x + 0.002029 * sqr(x) - 0.000801 * cube(x); }



double lundin(double rm, int32_t n, double lm, double wm)
/*     From Richard Lundin, A Handbook Formula for the Inductance of a Single-Layer Circular Coil.
 *    Proceedings of the IEEE, 1985, Vol. 73, No. 9, pp 1428-1429.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters (ignored).
 * External References: none
 * Returned values: Inductance in Henries.
 * Errors detected: none
 */{

  double sqrrm = sqr(rm);
  
  if ((2.0 * rm) <= lm)
    return((u0 * sqri(n) * M_PI * sqrrm) / lm) *
      (f1((4.0 * sqrrm) / sqr(lm)) - (8.0 * rm) / (3.0 * M_PI * lm));
  else
    return u0 * sqri(n) * rm * ((log(8.0 * rm / lm) - 0.5) * f1(sqr(lm) / (4.0 * sqrrm))
       + f2(sqr(lm) / (4.0 * sqrrm)));
}


uint8_t reclundin(double rm, int32_t n, double lm, double wm)
/*     Never better than 10.25%, not recommended.
 * Parameters:
 *   rm: Radius in meters.
 *   n: Number of turns.
 *   lm: Length in meters.
 *   wm: Wire radius in meters
 * External References: none
 * Returned values: not recommended.
 * Errors detected: none
 */
{
  return notRecommended;
}



// EOF
