From 17548faaae82dcc4f5dc17b2ee8ef959ab3ffd8d Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 11 Apr 2015 04:18:48 +0000 Subject: [PATCH] linear regression Octave and C code git-svn-id: https://svn.code.sf.net/p/freetel/code@2111 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/tlinreg.m | 40 ++++++++++++++ codec2-dev/src/linreg.c | 106 ++++++++++++++++++++++++++++++++++++ codec2-dev/src/linreg.h | 35 ++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 codec2-dev/octave/tlinreg.m create mode 100644 codec2-dev/src/linreg.c create mode 100644 codec2-dev/src/linreg.h diff --git a/codec2-dev/octave/tlinreg.m b/codec2-dev/octave/tlinreg.m new file mode 100644 index 00000000..81656e68 --- /dev/null +++ b/codec2-dev/octave/tlinreg.m @@ -0,0 +1,40 @@ + +1; + +function [m b] = linreg(x,y,n) + sumx = 0.0; % sum of x + sumx2 = 0.0; % sum of x^2 + sumxy = 0.0; % sum of x * y + sumy = 0.0; % sum of y + sumy2 = 0.0; % sum of y**2 + + for i=1:n + sumx += x(i); + sumx2 += x(i)^2; + sumxy += x(i) * y(i); + sumy += y(i); + sumy2 += y(i)^2; + end + + denom = (n * sumx2 - sumx*sumx); + + if denom == 0 + % singular matrix. can't solve the problem. + m = 0; + b = 0; + else + m = (n * sumxy - sumx * sumy) / denom; + b = (sumy * sumx2 - sumx * sumxy) / denom; + end + +endfunction + +x = [1 2 7 8]; +y = [ -0.70702 + 0.70708i 0.77314 - 0.63442i -0.98083 + 0.19511i 0.99508 - 0.09799i] .* [1 -1 1 -1]; +[m b] = linreg(x,y,4); + +x = [1 2 3 4 5 6 7 8]; +yFit = m * x + b; +figure(1) +plot(yFit,'r*') +axis([-1.5 1.5 -1.5 1.5]) diff --git a/codec2-dev/src/linreg.c b/codec2-dev/src/linreg.c new file mode 100644 index 00000000..e91a69c8 --- /dev/null +++ b/codec2-dev/src/linreg.c @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------------*\ + + 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 . +*/ + +#include +#include +#include + +#include "linreg.h" +#include "comp_prim.h" + + +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. +*/ + +#ifndef __LINREG__ +#define __LINREG__ + +#include "comp.h" + +void linreg(COMP *m, COMP *b, float x[], COMP y[], int n); + +#endif -- 2.25.1