mirror of
https://github.com/f4exb/sdrangel.git
synced 2026-06-08 17:04:46 -04:00
libfreedv: use in FreeDV demod
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
|
||||
FILE........: linreg.c
|
||||
AUTHOR......: David Rowe
|
||||
DATE CREATED: April 2015
|
||||
|
||||
Linear regression C module based on:
|
||||
|
||||
http://stackoverflow.com/questions/5083465/fast-efficient-least-squares-fit-algorithm-in-c
|
||||
|
||||
Use:
|
||||
|
||||
$ gcc linreg.c -o linreg -D__UNITTEST__ -Wall
|
||||
$ ./linreg
|
||||
|
||||
Then compare yfit results with octave/tlinreg.m
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Copyright (C) 2015 David Rowe
|
||||
|
||||
All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License version 2.1, as
|
||||
published by the Free Software Foundation. This program is
|
||||
distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "linreg.h"
|
||||
#include "codec2/comp_prim.h"
|
||||
|
||||
namespace FreeDV
|
||||
{
|
||||
|
||||
void linreg(COMP *m, COMP *b, float x[], COMP y[], int n)
|
||||
{
|
||||
float sumx = 0.0; /* sum of x */
|
||||
float sumx2 = 0.0; /* sum of x^2 */
|
||||
COMP sumxy = {0.0,0.0}; /* sum of x * y */
|
||||
COMP sumy = {0.0,0.0}; /* sum of y */
|
||||
COMP sumy2 = {0.0,0.0}; /* sum of y**2 */
|
||||
float denom;
|
||||
COMP zero;
|
||||
int i;
|
||||
|
||||
for (i=0; i<n; i++) {
|
||||
sumx += x[i];
|
||||
sumx2 += x[i]*x[i];
|
||||
sumxy = cadd(sumxy, fcmult(x[i], y[i]));
|
||||
sumy = cadd(sumy, y[i]);
|
||||
sumy2 = cadd(sumy2, cmult(y[i],y[i]));
|
||||
}
|
||||
|
||||
denom = (n * sumx2 - sumx*sumx);
|
||||
|
||||
if (denom == 0) {
|
||||
/* singular matrix. can't solve the problem */
|
||||
zero.real = 0.0; zero.imag = 0.0;
|
||||
*m = zero;
|
||||
*b = zero;
|
||||
} else {
|
||||
*m = fcmult(1.0/denom, cadd(fcmult(n, sumxy), cneg(fcmult(sumx,sumy))));
|
||||
*b = fcmult(1.0/denom, cadd(fcmult(sumx2,sumy), cneg(fcmult(sumx, sumxy))));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef __UNITTEST__
|
||||
|
||||
|
||||
static float x[] = {1, 2, 7, 8};
|
||||
|
||||
static COMP y[] = {
|
||||
{-0.70702, 0.70708},
|
||||
{-0.77314, 0.63442},
|
||||
{-0.98083, 0.19511},
|
||||
{-0.99508, 0.09799}
|
||||
};
|
||||
|
||||
|
||||
int main(void) {
|
||||
float x1;
|
||||
COMP m,b,yfit;
|
||||
|
||||
linreg(&m, &b, x, y, sizeof(x)/sizeof(float));
|
||||
|
||||
for (x1=1; x1<=8; x1++) {
|
||||
yfit = cadd(fcmult(x1, m),b);
|
||||
printf("%f %f\n", yfit.real, yfit.imag);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // FreeDV
|
||||
|
||||
Reference in New Issue
Block a user