/* Copyright 2025 by COG9 Enterprises LLC
 * All rights reserved.
 * Title: llsq.ino
 * Author: Jed Marti KI7NNP
 * Description: Linear least squares (fast version).
 * Created: Wed Nov 12 10:02:53 2025
 * Revision History:
 */

#include <stdint.h>
#include "llsq.h"


// Globals for the values.
float y1, y2, y3, y4, y5, y6, y7;


float fllsq5(void)
/*     A fast linear least squares function. We're assuming x is constant so the average for
 *    5 values is 2.0. 
 * Parameters: none
 * External References:
 *   f1-f5: The 5 values.
 * Returned values: Returns slope. Note, the slope can't be infinite since we're in control of x.
 * Errors detected: none.
 */
{
  float avgy, num;
  
  avgy = (y1 + y2 + y3 + y4 + y5) / 5.0f;
  num = (-2.0f * (y1 - avgy)) - (y2 - avgy) + (y4 - avgy) + 2.0f * (y5 - avgy);

  // Probably don't need the /10 as we're just looking for slope change sign.
  return num / 10.0f;
}



float dllsq7(void)
/*     A fast linear least squares function for 7 values. Assume x is linear starting at 0
 *   increasing by 1 so the parameters of the numerator are fixed.
 * Parameters: none
 * External References:
 *   f1-f7: The 7 values.
 * Returned values: Returns slope. Note, the slope can't be infinite since we're in control of x.
 * Errors detected: none.
 */
{
  float avgy, num;
  avgy = (y1 + y2 + y3 + y4 + y5 + y6 + y7) / 7.0f;
  num = (-3.0f * (y1 - avgy)) + (-2.0f * (y2 - avgy)) - (y3 - avgy) +
    (y5 - avgy) + 2.0f * (y6 - avgy) + 3.0f * (y7 - avgy);
  return num / 28.0f;
}


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



void llsq(float *x, float *y, uint16_t n, float *m, float *b)
{
  float avgx, avgy;
  uint16_t i;
  float num,  den;
  
  avgx = avgy = 0.0f;
  for (i = 0; i < n; ++i)
  {
    avgx += x[i],
      avgy += y[i];
  }

  avgx /= (float) n,
    avgy /= (float) n;

  num = den = 0.0f;
  for (i = 0; i < n; ++i)
  {
    num += (x[i] - avgx) * (*y - avgy),
      den += sqr(x[i] - avgx);
  }
  if (den == 0.0f) *m = *b = 0.0f;
  else
  {
    *m = num / den;
    *b = avgy - *m * avgx;
  }
}



// EOF
