I'm trying to convert this line of Matlab code into c programming language:
coefs = polyfit(X(50:(length(X)-50)),Y(50:(length(Y)-50)),1);
I've tried different implementations, but none of them seem to give me the same coefs(1) value, i.e, slope. All I'm interested in is in the slope.
Note: all the code is probably over-complicated. As of know, I don't know any better. Still new to this.
Since c doesn't have dynamic arrays, I have two linked lists, X and Y
UPDATE: I changed everything to *float instead of lists. Below is the functions' code and the declarations.
float getSumF(float * head, int size){
int i;
float sum=0;
for (i=0;i<size;i++){
sum = sum + head[i];
}
return sum;
}
float coef (float* xx, float* yy, int size) {
int i=0;
float sumX2 = 0;
float sumXY = 0;
float sumX = 0;
float sumY = 0;
for (i=0;i<size;i++){
sumX = sumX + xx[i];
sumY = sumY + yy[i];
sumX2 = sumX2 + xx[i]*xx[i];
sumXY = sumXY + xx[i]*yy[i];
}
float slope = (size*sumXY-sumX*sumY)/(size*sumX2-sumX*sumX);
return slope;
}
int main(void) {
setbuf(stdout, NULL);
int threshold=20;
int k, i, j;
float slope, angle;
int width, height, channels;
float* X = 0;
float* Y = 0;
int arraysizeX = 0;
float* osc = 0;
int arraysizeOsc = 0;
float* coord = 0;
int arraysizeCoord = 0;
unsigned char *img;
The way I achieve the array indexing of Matlab is through this:
for(i=0;i<1440;i++){
if (coord[i] > 0){
X = realloc (X,++arraysizeX*sizeof(*X));
Y = realloc (Y,arraysizeX*sizeof(*Y));
X[arraysizeX-1]=i+1;
Y[arraysizeX-1]=coord[i];
}
}
if (arraysizeX>102){
slope=coef(X+50,Y+50,arraysizeX-100);
}
else{
if(arraysizeX==0){
free(X);
free(Y);
free(coord);
printf("Threshold too low. Exiting.\n");
return 3;
}
slope = coef(X,Y,arraysizeX);
}
I also coded the same linear regression algorithm to matlab, here:
sizeX=length(X);
sumX2 = 0;
sumXY = 0;
for i=1:sizeX
sumX2 = sumX2 + X(i)*X(i);
sumXY = sumXY + X(i)*Y(i);
endfor
slope=(sizeX*sumXY-sum(X)*sum(Y))/(sizeX*sumX2-sum(X)*sum(X));
slope_polyfit = 7.4615e-3
slope_matlab = 5.8421e-3
slope_c = -0.175331
Now.. is my mistake in the coef call/function? Have I done everything right?
UPDATE: The solution I provided (with guidance from the comments) is functioning properly. The error was in the matlab code, in the obtention of X and Y arrays.
As updated in the post: the solution I provided (with some tweaks from the comments) is functioning properly. The error was in the matlab code, in the obtention of X and Y arrays.
Related
EDIT: I've added the main, factorial, and trapGamma function to give the full picture but I am specifically talking about the for loop for iSum in the I function.
Basically I've run out of ideas and exhausted everywhere I know of to find an answer to this. I need to code a program that will compute a complex function which represents an M/M/1 queue.
The function includes sub functions such as calculating the integral of a gamma function and computing factorials. I've written all the code for the computations but my sum is giving me huge numbers when I would expect nothing higher than about .35
#include <math.h>
#include <stdio.h>
double I(int k, double t);
double trapGamma(double z);
unsigned long long int factorial(unsigned int n);
int main()
{
int k;
int i = 0;
double dt = 0.1;
printf("Ikx = [ \n");
for (t = 14.0 ; t <= 15.0; t += dt)
{
printf("%f " , t);
for (k = 1 ; k <= 10 ; k++)
{
I(k, t);
printf("%f " , I(k, t));
}
printf("\n");
}
printf(" ];\n");
return (0);
}
double I(int k, double t)
{
unsigned long long int x;
unsigned int n = 20;
double numerator, y, pow1, c;
double iSum;
double Ix;
int i = 0;
iSum = 0.0;
Ix = 0.0;
a = .25 * pow(t , 2);
b = pow(a, i);
x = factorial(n);
y = trapGamma(k + i + 1);
iSum = (b / (x * y));
//This is the sum loop that I'm having trouble with, I've broke the iSum equation down for my own readability while coding right above this comment
for (i = 0; i <= 100 ; i++)
{
iSum += i;
}
Ix = (pow((.5 * t), k) ) * iSum;
return Ix;
}
/*
I've checked both the factorial and trapGamma functions and they are giving me the expected results.
*/
unsigned long long int factorial(unsigned int n)
{
if(n <= 1)
return 1;
else
return (n * factorial(n - 1));
}
double trapGamma (double z)
{
int i , N = 100;
double gamma;
double a = 0.0;
double b = 15.0;
double x1, x2, y1, y2;
double areai;
double w = (b - a) / N;
gamma = 0.0;
for (i = 1; i < N; i++)
{
x1 = a + ((i - 1) * w); //the left bound point
x2 = a + (i*w); //the right bound point
y1 = pow(x1,z - 1)*exp(-x1); //the height of our left bound
y2 = pow(x2, z - 1)*exp(-x2); //the height of our right bound
areai = ((y1 + y2) / 2.0) * (x2 - x1);
gamma += areai;
}
return gamma;
}
This is building upon another project where I used a bessel function to create the M/M/1 queue over a 60 second span so I can see what this one is supposed to be. I've checked both my trapGamma and factorial functions results on there own and they are both working as expected.
How are summations supposed to be coded?
If the intent of the posted code is to calculate the modified Bessel function I, there are some pitfalls and useful semplifications to be aware of. Given
Trying to calculate the factorial, the value of the Gamma function, their product and the powers separately for each term of the sum leads to integer overflow sooner than later.
It's better to update the value of each addend of the sum instead.
Also, given that k is a whole, we have Γ(n) = (n - 1)!
The addends are increasingly smaller and, after some iterations, too small to be added to the sum, given the limited precision of type double.
// Evaluates x^k / k! trying not to overflow
double power_over_factorial(double x, int k)
{
double result = 1.0;
for ( int i = 1; i <= k; ++i )
{
result *= x / i;
}
return result;
}
#define MAX_ITERS 20
double modified_Bessel_I(int k, double x)
{
x /= 2;
const double xx = x * x;
double partial = power_over_factorial(x, k);
double old_sum, sum = partial;
int m = 1;
do
{
old_sum = sum;
partial *= xx / ((m + k) * m);
sum += partial;
}
while ( old_sum != sum && ++m < MAX_ITERS );
return sum;
}
Testable here.
In my code I had an error that I was able to pinpoint down to a certain for loop, but now I'm uncertain as to how exactly the problem is being caused
int linregm(int n, float x[], float y[]){
float denom=1;
sumx = 0.0;
sumx2 = 0.0;
sumxy = 0.0;
sumy = 0.0;
/*
for (i=0;i<n;i++)
{
//sumx = sumx + x[i];
//sumx2 = sumx2 + x[i]*x[i];
//sumxy = sumxy + x[i] * y[i];
//sumy = sumy + y[i];
}
*/
denom = (n * sumx2 - sqr(sumx));
if (denom == 0) {
// singular matrix. can't solve the problem.
pass=1;
return 0;
}
m = (n * sumxy - sumx * sumy) / denom;
pass=0;
return m;
}
This is the function that has a problem at the spot where there is a for-loop, even if I just run the loop itself without the internal contents it still gives me an error.
m = linregm(sizeof(x)/sizeof(x[0]), x, y);
__IO float Send_float_Data[256];
float x[8] = {1,2,3,4,5,6,7,8};
float y[8];
float m,b;
unsigned int pass;
float sumx,sumx2,sumxy,sumy=0.0;
unsigned int i=0,j;
And these are the variable declarations.
I'm new to C so I don't know if there are special interactions between variables or something that could have screwed up my code, there was no compiler warning so syntax shouldn't be a problem.Do you guys have any idea on what exactly I'm doing wrong? Thanks.
I'm trying to filter my data to get rid of some noise, and I found that when I to run the filter the data from the original array with the pre-filtered data and the second array with the filtered data both become unprintable.
This is where I called the filter function(s):
int main(void)
{
int n = 0;
double sum=0.0;
USART1_Config();
ADC1_Init();
IIR_Reset();
while(1)
{
if(DMA_GetFlagStatus(DMA1_FLAG_TC1)==SET)
{
sgolayfilt();
IIR_filter();
for(i=0;i<256;i++)
{
Send_int_Data[i]=(int)(Send_float_Data[i]*1000);
printf("%d\n",ADC_ConvertedValue[i]);
//printf("%d\n",Send_int_Data[i]);
}
DMA_ClearFlag(DMA1_FLAG_TC1);
}
}
}
This is for sgolayfilt, the function that messes up the data(I even tried printing the pre-filter array right after I called the function, but even that didn't give me any values):
float sqr(float x) {
return x*x;
}
int linreg(int n, float x[], float y[], float* m, float* b, float* r){
float sumx = 0.0;
float sumx2 = 0.0;
float sumxy = 0.0;
float sumy = 0.0;
float sumy2 = 0.0;
float denom;
for (i=0;i<n;i++)
{
sumx += x[i];
sumx2 += sqr(x[i]);
sumxy += x[i] * y[i];
sumy += y[i];
sumy2 += sqr(y[i]);
}
denom = (n * sumx2 - sqr(sumx));
if (denom == 0) {
// singular matrix. can't solve the problem.
*m = 0;
*b = 0;
//if (r) *r = 0;
return 1;
}
*m = (n * sumxy - sumx * sumy) / denom;
*b = (sumy * sumx2 - sumx * sumxy) / denom;
if (r!=NULL) {
*r = (sumxy - sumx * sumy / n) /
sqrt((sumx2 - sqr(sumx)/n) *
(sumy2 - sqr(sumy)/n));
}
return 0;
}
void sgolayfilt(void){
//for(i=0;i<256;i++) printf("%d\n",ADC_ConvertedValue[i]);
if (!check)
{
for (i=0;i<4;i++)
{
ADC_ConvertedValueLocal = (float)
ADC_ConvertedValue[i]/4096*2.5;
placeholder[i] = ADC_ConvertedValueLocal;
}
check = 1;
}
for(i=0;i<256;i++)
{
if(i<4)
{
for(j=i;j<4;j++) y[j-i] = placeholder[j];
for(j=4-i;j<8;j++)
{
ADC_ConvertedValueLocal = (float)
ADC_ConvertedValue[j+i-4]/4096*2.5;
y[j] = ADC_ConvertedValueLocal;
}
}
else
{
for(j=i-4;j<i+4;j++)
{
ADC_ConvertedValueLocal = (float)
ADC_ConvertedValue[j]/4096*2.5;
y[j-i+4] = ADC_ConvertedValueLocal;
}
}
pass = linreg(8, x, y, &m, &b, &r);
if (pass==0) Send_float_Data[i] = (5 * m + b);
else
{
ADC_ConvertedValueLocal = (float)
ADC_ConvertedValue[i]/4096*2.5;
Send_float_Data[i] = ADC_ConvertedValueLocal;
}
}
for(i=0;i<4;i++) placeholder[i] = y[4+i];
}
This is for the original filter that works just fine save the actual filtering:
void IIR_filter(void)
{
for(i=0;i<256;i++)
{
ADC_ConvertedValueLocal =(float) ADC_ConvertedValue[i]/4096*2.5;
x0=ADC_ConvertedValueLocal;
w0[0]=IIR_50Notch_A[0]*x0-IIR_50Notch_A[1]*w0[1]-
IIR_50Notch_A[2]*w0[2];
y0=IIR_50Notch_B[0]*w0[0]+IIR_50Notch_B[1]*w0[1]+IIR_50Notch_B[2]*w0
[2];
x1=y0;
w1[0]=IIR_High_A[0]*x1-IIR_High_A[1]*w1[1]-IIR_High_A[2]*w1[2];
y1=IIR_High_B[0]*w1[0]+IIR_High_B[1]*w1[1]+IIR_High_B[2]*w1[2];
Send_float_Data[i]=y1;
w0[2]=w0[1];
w0[1]=w0[0];
w1[2]=w1[1];
w1[1]=w1[0];
}
}
And these are the variable declarations:
__IO unsigned char s[50];//
extern __IO uint16_t ADC_ConvertedValue[256];
__IO float ADC_ConvertedValueLocal;
__IO float Send_float_Data[256];
__IO int Send_int_Data[256];
volatile char Send_char_data[4];
__IO float placeholder[4];
float w0[3]={0};
float w1[3]={0};
float x0=0,x1=0;
float y0=0,y1=0;
float x[8] = {1,2,3,4,5,6,7,8};
float y[8];
float m,b,r;
unsigned int pass;
unsigned int i=0,j;
_Bool check = 0;
I don't have much experience with C and so I'm looking for help on how should I modify my code so that "sgolayfilt()" interacts with the data like "IIR_filter" does and not mess up the arrays.
EDIT After going back and looking through it a bit more the pre-filter array "ADC_ConvertedValue" encounters the error the moment I call the faulty function. I placed the two function calls in the same place and the "printf" statements at the very start of the function definitions themselves and the original can print the values within the array regardless while the faulty function can't.
Trying to implement a perceptron in C, can't get it to train.
The output always just goes to zero and I don't know what’s wrong.
Although, I do suspect it might be either the delta function or me just incorrectly implementing the perceptron.
Thanks in advance to everyone who helps!
#include<stdio.h>
#define arrayLength(x) (sizeof(x) / sizeof((x)[0]))
typedef int bool;
enum { false, true };
int main(){
float trainInputs [2][2] = {{0.0f, 1.0f}, {0.0f, 0.0f}};
float trainOutputs [2][1] = {{1.0f}, {0.0f}};
int amontOfTrainData = 1;
float inputs [] = {0.0f, 1.1f};
float outputs [] = {0.0f};
float wights [(arrayLength(inputs) * arrayLength(outputs))] = {0.5f, 0.5f, 0.5f, 0.5f};
float learningRate = 0.01f;
float delta(float actual, float want, float wight){
float error = want - actual;
float out = error * learningRate * wight;
printf(":%.6f:\n", out);
return out;
}
// Run perceptron
void run(bool train){
int outputInc = 0;
int wightInc = 0;
while(outputInc < arrayLength(outputs)){
int inputInc = 0;
while(inputInc < arrayLength(inputs)){
if(train){
int x = 0;
while(x < amontOfTrainData){
outputs[outputInc] = trainInputs[x][inputInc] * wights[wightInc];
wights[wightInc] = delta(outputs[outputInc], trainOutputs[x][outputInc], wights[wightInc]);
x++;
}
}else{
outputs[outputInc] = inputs[inputInc] * wights[wightInc];
}
inputInc++;
wightInc++;
}
//printf("out[%i]: %.5f\n", outputInc, outputs[outputInc]);
outputInc++;
}
}
int b = 0;
while(b < 100){
run(true);
b++;
}
printf("-----------[ 100 LOOPS DONE ]-----------\n");
run(false);
return 0;
}
As error, learningRate and wight are less than 0, the expression error * learningRate * wight will tend to 0 too.
The delta should not be the new value for the weight, it is the amount of change, so instead of:
wights[wightInc] = delta(...);
Try:
wights[wightInc] += delta(...);
(Which source are you using for you perceptron formulas?)
I have applied all the changes and this is the final working code.
Thanks to everyone who helped me!
#include<stdio.h>
#include<stdbool.h>
#define arrayLength(x) (sizeof(x) / sizeof((x)[0]))
float trainInputs [2][2] = {{0.0f, 1.0f}, {0.0f, 0.0f}};
float trainOutputs [2][1] = {{1.0f}, {0.0f}};
int amontOfTrainData = 1;
float inputs [] = {1.0f, 1.0f};
float outputs [] = {0.0f};
float wights [(arrayLength(inputs) * arrayLength(outputs))] = {0.001f, 0.001f};
float learningRate = 0.1f;
float delta(float actual, float want, float wight)
{
float error = want - actual;
float out = error * learningRate * wight;
return out;
}
void run(bool train)
{
int outputInc = 0;
int wightInc = 0;
while(outputInc < arrayLength(outputs))
{
int inputInc = 0;
while(inputInc < arrayLength(inputs))
{
if(train)
{
int x = 0;
while(x < amontOfTrainData)
{
outputs[outputInc] = trainInputs[x][inputInc] * wights[wightInc];
wights[wightInc] += delta(outputs[outputInc], trainOutputs[x][outputInc], wights[wightInc]);
x++;
}
}
else
{
outputs[outputInc] = inputs[inputInc] * wights[wightInc];
}
inputInc++;
wightInc++;
}
printf("out[%i]: %.5f\n", outputInc, outputs[outputInc]);
outputInc++;
}
}
int main()
{
// Run neural network
int b = 0;
int loops = 500;
while(b < loops)
{
run(true);
b++;
}
printf("-----------[ %i LOOPS DONE ]-----------\n", loops);
run(false);
return 0;
}
I have a homework to implement an FIR filter in C and I wonder whether you think I understood the assignment correctly. The program I wrote that I think solves the problem is:
#include <stdio.h>
float FIRfloats[5];
void floatFIR(float newsample)
{
int i;
float sum=0;
FIRfloats[0]=newsample*0.0299;
FIRfloats[1]=FIRfloats[2]*0.4701;
FIRfloats[2]=FIRfloats[3]*0.4701;
FIRfloats[3]=FIRfloats[4]*0.0299;
/* sum */
for(i=0;i<5;i++)
{
sum=sum+FIRfloats[i];
}
printf("Sum: %f\n", sum);
}
int main ()
{
float n=0.0f;
while (scanf("%f", &n) > 0)
{
floatFIR(n);
}
return 0;
}
And the specification is
Before a new sample xk arrives the old samples are shifted to the
right and then each sample is scaled with a coefficient before the
result yk, the total sum of all scaled samples, is calculated
Coefficients should be c0=0.0299, c1=0.4701, c2=0.4701, c3=0.0299.
Do you think that I solved the assignment correctly? I think it seemed too easy and therefore I wonder.
I'm afraid the implementation provided in the question will not provide the correct results.
In FIR (Finite Impulse Response) filter with 4 coefficients the output series (y) for input series (x) is:
y[t] = c0*x[t] + c1*x[t-1] + c2*x[t-2] + c3*x[t-3]
Therefore the implementation should be similar to:
/* add includes (stdio.h and whatever else you'll need...) */
float floatFIR(float inVal, float* x, float* coef, int len)
{
float y = 0.0;
for (int i = (len-1) ; i > 0 ; i--)
{
x[i] = x[i-1];
y = y + (coef[i] * x[i]);
}
x[0] = inVal;
y = y + (coef[0] * x[0]);
return y;
}
main(int argc, char** argv)
{
float coef[4] = {0.0299, 0.4701, 0.4701, 0.0299};
float x[4] = {0, 0, 0, 0}; /* or any other initial condition*/
float y;
float inVal;
while (scanf("%f", &inVal) > 0)
{
y = floatFIR(inVal, x, coef, 4);
}
return 0;
}
This does the shift and multiplication at the same loop (which does not affect results - only is more efficient.)
If you want to follow the spec exactly, you can change floatFir like this:
float floatFIR(float inVal, float* x, float* coef, int len)
{
float y = 0.0;
for (int i = (len-1) ; i > 0 ; i--)
{
x[i] = x[i-1];
}
x[0] = inVal;
for (int i = 0 ; i < len ; i++)
{
y = y + (coef[i] * x[i]);
}
return y;
}