Trouble with allocating a variable to an array element - c

So I am currently writing a function that can output data to an array ready for export to text. Function works fine when collecting variables but an getting the "Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)" error within Xcode and don't know how to debug this. I have tried using calloc to assign memory to the array and using address locations but am still getting similar error messages and using address locations just don't work.
Has anyone got any suggestions for how I can solve this? The error code is showing itself on the first line of the for loop and this function is running as part of a larger function.
void LamVelProf(double dP, double L, double d, double mu)
{
double *r = malloc(sizeof(r)); //Point radius from centreline
double *R = malloc(sizeof(R)); //Absolute pipe radius
double *vx = malloc(sizeof(vx));
double *gvx = malloc(sizeof(gvx));
double *offset = malloc(sizeof(offset));
double **profile[7500][4];
**profile = calloc((7500*4), sizeof(double));
//double **profile = calloc((7500*4), sizeof(double));
int *i = malloc(sizeof(i));
*R = d/2; //Setting the boundary condition
*offset = 0.001;
*i = 0;
for(*r = 0; *r < (*R + (*offset/2)); *r = (*r)+(*offset))
{
**profile[*i][0] = *r;
LamVelProCalc(dP, L, d, mu, *r, vx);
**profile[*i][1] = *vx;
LamGenProCalc(*r, d, gvx);
**profile[*i][2] = *gvx;//Results from general profile
**profile[*i][3] = *i+1;
++*i; //Increasing count by 1
}
printf("%i rows generated\n", *i);
free(r);
free(R);
free(offset);
int *row = malloc(sizeof(row));
int *col = malloc(sizeof(col));
for(*row = 0; *row < *i + 1; *row = *row + 1)
{
for(*col = 0; *col < 4; *col = *col + 1)
{
printf("%f", **profile[*row][*col]);
if(*col == 3)
{
printf("\n");
}else{
printf("\t");
}
}
}
}

I've had to aggressively de-pointerize this code to bring it back into the realm of understandability, and the end result is this:
void LamVelProf(double dP, double L, double d, double mu)
{
double R = d/2;
double offset = 0.001;
double profile[7500][4];
int i = 0;
for (double r = 0; r < (R + (offset/2)); r += offset) {
double vx = 0.0; // Initialize appropriately
double gvx = 0.0;
profile[i][0] = r;
// No idea what this does, or why the return value is ignored
LamVelProCalc(dP, L, d, mu, r, vx);
profile[i][1] = vx;
// No idea what this does, or why the return value is ignored
LamGenProCalc(r, d, gvx);
profile[i][2] = gvx;//Results from general profile
profile[i][3] = i+1;
++i; //Increasing count by 1
}
printf("%i rows generated\n", i);
for(int row = 0; row < i + 1; ++row)
{
for(int col = 0; col < 4; ++col)
{
printf("%f", profile[row][col]);
if (col == 3) {
printf("\n");
} else {
printf("\t");
}
}
}
}
As you can see there's two function calls buried in there that should probably have pointer arguments, my guess is vx and gvx are intended to be manipulated by that function. In C it is common to use use pointers to manipulate external variables, so a pointer argument almost always means "array" or "mutable argument" depending on context.
In other words I'd expect to see:
LamVelProCalc(dP, L, d, mu, r, &vx);
Or even better:
double vx = LamVelProCalc(dP, L, d, mu, r);
Where that value is explicitly returned instead.
This should compile and run without crashing now, though note the above mentioned issues.
When it comes to compiler suggestions to fix a problem, remember to take them all under advisement. At the end of the day you're the programmer, not the compiler, and not every educated guess it makes will be a valid interpretation of the problem at hand. If you unwaveringly follow the compiler's advice it may lead you down really, really strange paths, as perhaps has happened here.
As a note, having variables r and R is borderline programmer abuse. Please don't do this.
Another thing to keep in mind is your rather arbitrary use of 7500 here. Is that just a wild guess as to how many entries you'll need? It's almost always better to compute that, you know how the for loop will run in advance so you can do the math, and allocate accordingly.
If it is a limit you've arrived at through some other method it's worth using a #define to indicate as such, like:
#define MAX_PROFILE_ENTRIES 7500
Where it's now clear what the meaning behind that number is.

So after a lot of head scratching and realising I didn't need malloc because my array would definitely never reach the 125000 elements. Thanks to #tadman for helping with that. Here's the final program which is designed to be called from a menu function:
//
// 02g1LamVelPro .c
// Process Model (MacOS Version)
//
// Created by --- on 30/06/2020.
// Copyright © 2020 ---. All rights reserved.
//
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxstrlen 128
//Declaring global variables and allocating memory
//Function Output
double profile; //Array of doubles
//Calculation Variables
double dP;
double L;
double d;
double mu;
double r;
//Miscellaneous Variables
void LamVelProVar(double *dP, double *L, double *d, double *mu)
{
//Declaring input variables
char pres[maxstrlen];
char len[maxstrlen];
char dia[maxstrlen];
char visc[maxstrlen];
printf("Fluid pressure loss (Pa) = ");
*dP = atof(fgets(pres, sizeof(pres), stdin));
printf("Pipe length (m) = ");
*L = atof(fgets(len, sizeof(len), stdin));
printf("Pipe diameter (mm) = ");
*d = atof(fgets(dia, sizeof(dia), stdin));
*d = (*d)*0.001;
printf("Fluid viscosity (cP) = ");
*mu = atof(fgets(visc, sizeof(visc), stdin));
*mu = (*mu)*0.001;
fflush(stdout);
}
double LamVelCalc(double dP, double L, double d, double mu, double r, double *v_x)
{
//Calculation of the theoretical velocity profile with the flow possessing laminar characteristics
double frac1;
double frac2;
double frac3;
frac1 = (dP/L);
frac2 = pow(d,2);
frac2 = (frac2)/(16*mu);
frac3 = 2*r;
frac3 = (frac3)/d;
frac3 = pow(frac3, 2);
frac3 = 1 - (frac3);
*v_x = frac1 * frac2;
*v_x = (*v_x) * frac3;
return *v_x;
}
double LamGenCalc(double r, double d, double *func)
{
//Calculation of the general velocity profile with the flow possessing laminar characteristics
*func = 2*r;
*func = (*func)/d;
*func = pow(*func, 2);
*func = 1 - (*func);
return *func; //Returns v/v_max
}
double **LamVelProfCalc(double dP, double L, double d, double mu)
{
char display[maxstrlen];
double v_x = 0;
double offset = 0.0001;
//Calculating number of rows for the profile results matrix
double prad = d/2;
int whildisp = 1;
int rows = ((prad)/ (offset)) + 1;
printf("%i rows required\n", rows);
double profile[rows][3];
int i = 0;
for(double r = 0.0; r < (prad + (offset/2)); r += offset)
{
profile[i][0] = r; //Displaying point radius
profile[i][1] = LamVelCalc(dP, L, d, mu, r, &v_x); //Calculating point velocity
profile[i][2] = LamGenCalc(r, d, &v_x); //Calculating
//profile[i][3] = i + 1;
++i;
}
printf("%i rows successfully generated\n\n", i);
while(whildisp == 1)
{
printf("Do you want to display the generated data? ");
fgets(display, sizeof(display), stdin);
switch(display[0])
{
case '1':
case 'Y':
case 'y':
printf("Displaying data\n");
printf("Inputted variables:\n");
printf("dP =\t%.3f\tPa\n", dP);
printf("L =\t%.3f\tm\n", L);
printf("d =\t%.1f\tmm\n", d*1000);
printf("mu =\t%.3f\tPa.s\n", mu);
printf("v_max =\t%.3f\tm/s\n\n", LamVelCalc(dP, L, d, mu, 0, &v_x));
printf("r (m)\tv_x (m/s)\tv/v_max\n");
int row = 0;
int col = 0;
for(row = 0; row < i; ++row)
{
for(col = 0; col < 3; ++col)
{
printf("%.5f", profile[row][col]);
if(col == 2)
{
printf("\n");
}else{
printf("\t");
}
}
}
whildisp = 0;
break;
case '0':
case 'N':
case 'n':
whildisp = 0;
default:
printf("Input not recognised.\n");
break;
}
}
return profile;
}
void LamVelPro()
{
//Main Function
char ContCond[maxstrlen];
int whilmain = 1;
printf("Laminar flow velocity profile\n");
while(whilmain == 1)
{
//Variable declaration
double dP;
double L;
double d;
double mu;
double r;
//Data collection
LamVelProVar(&dP, &L, &d, &mu);
//Data manipulation
LamVelProfCalc(dP, L, d, mu);
//Ask for file write (Remember while loop)
//...
//Continue function
int whilcont = 1;
while(whilcont == 1)
{
printf("Do you want to continue? ");
fgets(ContCond, sizeof(ContCond), stdin);
switch(ContCond[0])
{
case '1':
case 'T':
case 'Y':
case 't':
case 'y':
whilcont = 0;
break;
case '0':
case 'F':
case 'N':
case 'f':
case 'n':
whilcont = 0;
whilmain = 0;
break;
default:
printf("Input not recognised\n");
break;
}
}
}
fflush(stdout);
}

Related

How to use a nested if else statements in a for loop in c

I'm having issues with my for statement. I'm trying to have a nested if else statement inside and I'm using pointers. I've tried everything and I've looked all over the internet. I've placed comments beside the lines with errors but if you see something else that's wrong please let me know. Thank you
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
void getinput(double*xptr, int*nptr)
{
int flag;
do
{
flag = TRUE;
printf("What is the value of x and the number of terms:");
scanf("%lf %i", xptr, nptr);
if (*nptr <= 0)
{
printf("The number of terms must be positive\n");
flag = FALSE;
}
}
while(flag == FALSE);
}
double sinHyper(double *xptr, int *nptr) {
int i;
double sum;
double ti;
i = 0;
ti = 0;
for (i = 0; i < *nptr; i = i+1)// I'm getting a Warning: comparioson between pointer and integer
{
if (i == 0)
{
sum = xptr;
} else {
ti = 2*i+1;
ti = ti*2*i;
ti = (xptr*xptr)/ti;// I'm getting a error: invalid operands to binary * (have 'double*' and 'double*')
sum = ti*sum;
}
}
return (sum);
}
void main() {
int n;
double x;
double sinhx;
getinput(&x, &n);
sinhx = sinHyper(&x, &n);
printf("For an x of %.0f with %i terms the sinh(x) is %f", x, n, sinhx);
return 0;
}
You forgot to dereference your pointers in several places.
The fact that this line compiles
sum = xptr;
should not mislead you: C lets you convert a pointer to a number with only a warning, while in most cases this is an error. This line should be
sum = *xptr;
It does not let you multiply pointers, so the expression where you square your pointer is an error:
(xptr*xptr)
You should either dereference the pointer twice, i.e. write
((*xptr)*(*xptr))
or make a separate variable for the current value of *xptr and use it instead:
const double x = *xptr;
ti = (x*x)/ti;
Note: This exercise should be purely theoretical, because sinHyper does not change *xptr or *nptr. Therefore, you should pass them as values, not as pointers:
double sinHyper(const double x, const int n) {
...
}
...
sinhx = sinHyper(x, n);

program.exe (C) has stopped working

I am extremely new to C and managed to compile this program, but the exe stops working upon running. I'm really not sure what's wrong.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define TINY 1.0e-20 // A small number.
void ludcmp(float a[3][3], int n, int *indx, float *d);
void lubksb(float a[3][3], int n, int *indx, float b[]) ;
int main(){
int i,n,*indx;
float *b,d;
float a[3][3] = {
{ 1.0, 2.0, 5.0},
{-1.0, 2.0, 3.0},
{ 6.0, 0.0, 1.0}
};
ludcmp(a,n,indx,&d);
lubksb(a,n,indx,b);
for(i = 1; i = 3; i++) {
printf("%.2f",b[i]);
}
getchar();
return 0;
}
For those who were asking, the 2 functions ludcmp and lubksg are below. I got them from the numerical recipes textbook, but edited some lines to remove exclusive routines which I do not have. Specifically, they are the lines with malloc, printf, and free.
The original code came with all the loops starting with 1, which is why I also started my loop with 1. I have since changed all the loops to start from 0 instead, hopefully without introducing any new errors.
You can see the original code here:
https://github.com/saulwiggin/Numerical-Recipies-in-C/tree/master/Chapter2.Solution-of-Linear-Equations
Here is ludcmp:
void ludcmp(float a[3][3], int n, int *indx, float *d)
{
int i, imax, j, k;
float big, dum, sum, temp;
float *vv; // vv stores the implicit scaling of each row.
vv = (float *) malloc(n * sizeof(float));
*d=1.0;
for (i=0;i<n;i++) {
big=0.0;
for (j=0;j<n;j++)
if ((temp=fabs(a[i][j])) > big) big=temp;
if (big == 0.0)
{
printf("Singular matrix in routine ludcmp");
//free(vv);
}
// No nonzero largest element.
vv[i] = 1.0 / big; // Save the scaling.
}
// This is the loop over columns of Crout's method.
for (j=0;j<n;j++) {
for (i=0;i<j;i++) {
sum=a[i][j];
for (k=0;k<i;k++) sum -= a[i][k]*a[k][j];
a[i][j]=sum;
}
// Initialize for the search for largest pivot element.
big=0.0;
for (i=j;i<=n;i++) {
sum=a[i][j];
for (k=0;k<j;k++)
sum -= a[i][k]*a[k][j];
a[i][j]=sum;
if ( (dum=vv[i]*fabs(sum)) >= big) {
big=dum;
imax=i;
}
}
if (j != imax) {
for (k=0;k<n;k++) {
dum=a[imax][k];
a[imax][k]=a[j][k];
a[j][k]=dum;
}
*d = -(*d);
vv[imax]=vv[j];
}
indx[j]=imax;
if (a[j][j] == 0.0) a[j][j]=TINY;
if (j != n) {
dum=1.0/(a[j][j]);
for (i=j+1;i<n;i++) a[i][j] *= dum;
}
} // Go back for the next column in the reduction.
free(vv);
}
And lubksb:
void lubksb(float a[3][3],int n,int *indx,float b[])
{
int i,ii=0,ip,j;
float sum;
for (i=1;i<=n;i++) {
ip=indx[i];
sum=b[ip];
b[ip]=b[i];
if (ii)
for (j=ii;j<=i-1;j++) sum -= a[i][j]*b[j];
else if (sum) ii=i;
b[i]=sum;
}
for (i=n;i>=1;i--) {
sum=b[i];
for (j=i+1;j<=n;j++) sum -= a[i][j]*b[j];
b[i]=sum/a[i][i];
}
}
This is a Two Dimensional Array and you are looping as it was just one. You should do something like:
for (int i = 0; i < 3; ++i) {
for(int j = 0; j < 3; ++j) {
printf("%d %d: ", i+1, j+1);
}
}
Is bad practice to define the size of the array explicit. Try to use a constant.
And as said in the comments by #Marged:
In C arrays starts in 0
b is never assigned to anything valid when it's declared:
float *b,d;
At best, it's NULL or pointing to an invalid memory address:
I don't know what the lubksb function does:
lubksb(a,n,indx,b);
But b is clearly an invalid parameter since you never assign to it before calling this function.
And with this statement:
for(i = 1; i = 3; i++) {
printf("%.2f",b[i]);
}
As others have pointed out, array indices start at zero. But there's no evidence that b has a length of three anyway.

Calling C in RStudio causes crash

I am constantly facing a fatal error when calling a C function in R and I suspect it may be because of the way I have used "realloc" routine for variable n_k in the gCRSF_gibbs function. Can somebody tell me if the reallocation of memory to n_k is correct or not?
void gCRSF_gibbs(double *z, double **n_k, double *SampleDex,
double *r, double *a, double *p,
int *Ksize, int *WordNum) {
int i, j, k;
double mass;
double *prob_cumsum;
double cum_sum, probrnd;
prob_cumsum = (double *) calloc(Ksize[0],sizeof(double));
mass = r[0]*pow(p[0],-a[0]);
for (i=0;i<WordNum[0];i++){
j = (int) SampleDex[i] -1;
k = (int) z[j] -1;
if(z[j]>0){
(*n_k)[k]--;
}
for (cum_sum=0, k=0; k<Ksize[0]; k++) {
cum_sum += (*n_k)[k]-a[0];
prob_cumsum[k] = cum_sum;
}
if ( ((double) rand() / RAND_MAX * (cum_sum + mass) < cum_sum)){
probrnd = (double)rand()/(double)RAND_MAX*cum_sum;
k = BinarySearch(probrnd, prob_cumsum, Ksize[0]);
}
else{
for (k=0; k<Ksize[0]; k++){
if ((int) (*n_k)[k]==0){
break;
}
}
if (k==Ksize[0]){
Ksize[0]++;
realloc(*n_k,sizeof(**n_k)*Ksize[0]);
(*n_k)[Ksize[0]-1]=0;
prob_cumsum = realloc(prob_cumsum,sizeof(*prob_cumsum)*Ksize[0]);
}
}
z[j] = k+1;
(*n_k)[k]++;
}
free(prob_cumsum);}
And this is how it is called in R:
gCRSF_gibbs <- function(z, n_k, sampleDex, r, a, p){
out <- .C("gCRSF_gibbs", z=as.double(z), n_k=as.double(n_k),
SampleDex=as.double(sampleDex), r=as.double(r), a=as.double(a),
p=as.double(p), Ksize=as.integer(length(n_k)),
WordNum=as.integer(length(sampleDex)))
out}
You're using realloc wrong. It should be:
*n_k = realloc(*n_k,sizeof(**n_k)*Ksize[0]);
You always want to use realloc like p = realloc(p, size). Otherwise, if the buffer gets moved by realloc, *n_k will be pointing to a freed pointer.

caught segfault in [R] function

I am very new to C but know my way around [R]. This error could be a very stupid mistake in C.
My C code does kernel smoothing.
*When I comment out the last line of code my function works: results[i] = v; *
This call kills R:
new.y<-zsmooth2( x=c(0:80000), xpts=dat$V2, ypts=dat$V4, h=10000)
* caught segfault *
address 0x1184f8000, cause 'memory not mapped'
Traceback:
1: .C("kernel_smooth", as.double(x), as.double(ypts), as.double(xpts), as.integer(n), as.integer(nxpts), as.double(h), result = double(length(xpts)))
2: zsmooth2(x = c(0:80000), xpts = dat$V2, ypts = dat$V4, h = 10000)
C-code:
#include <R.h>
#include <Rmath.h>
#include <stdio.h>
void kernel_smooth(double *x, double *ypts, double *xpts, int *n, int *nxpts, double *h, double *results){
int i, j;
for(i = 0; i < *n; i++){
double nsum = 0;
double dsum = 0;
double z = x[i] + *h;
double y = x[i] - *h;
for(j = 0; j < *nxpts; j++){
if(xpts[j] < y){
continue;
}
if(xpts[j] > z){
break;
}
double d = (xpts[j] - i) / *h;
double r = dnorm(d, 0, 1, 0);
nsum += r * ypts[j];
dsum += r;
}
Rprintf("test:i %d\n", i);
double v = nsum / dsum;
Rprintf("test:v %f\n", v);
results[i] = v;
}
}
R-code:
dyn.load("~/github/ZevRTricks/smoother1.so")
zsmooth2<-function(x, ypts, xpts, h){
n <- length(x)
nxpts <- length(xpts)
dens <- .C("kernel_smooth", as.double(x), as.double(ypts),
as.double(xpts), as.integer(n), as.integer(nxpts),
as.double(h), result = double(length(xpts)))
dens[["result"]]
}
xpts and ypts are vectors, and in your C code you are trying to access elements 1 to n in each of them. n is the length of x, which is 100 times longer in your second example than in your first example. Compare seq(from = 0, to = 80000 by = 100) to 0:80000, (and while you're at it you can drop the c() from around the 0:80000).
So I guess that xpts and ypts are at least 801 elements long, but less than 80001 elements. You've messed up your indexing somewhere.
Note also that you pass x to your C code, but don't actually use it for anything.

Selecting and analysing window of points in an array

Could someone please advise me on how to resolve this problem.
I have a function which performs a simple regression analysis on a sets of point contained in an array.
I have one array (pval) which contains all the data I want to perform regression analysis on.
This is how I want to implement this.
I get an average value for the first 7 elements of the array. This is what I call a 'ref_avg' in the programme.
I want to perform a regression analysis for every five elements of the array taking the first element of this array as the 'ref_avg'. That is in every step of the regression analysis I will have 6 points in the array.
e.g
For the 1st step the ref_avg as calculated below is 70.78. So the 1st step in the simple regression will contain these points
1st = {70.78,76.26,69.17,68.68,71.49,73.08},
The second step will contain the ref_avg as the 1st element and other elements starting from the second element in the original array
2nd = {70.78,69.17,68.68,71.49,73.08,72.99},
3rd = {70.78,68.68,71.49,73.08,72.99,70.36},
4th = {70.78,71.49,73.08,72.99,70.36,57.82} and so on until the end.
The regression function is also shown below.
I don't understand why the first 3 elements of the 'calcul' array have value 0.00 on the first step of the regression, 2 elements on the 2nd step,1 elements on the 3rd.
Also the last step of the regression function is printed 3 times.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
float pval[]={76.26,69.17,68.68,71.49,73.08,72.99,70.36,57.82,58.98,69.71,70.43,77.53,80.77,70.30,70.5,70.79,75.58,76.88,80.20,77.69,80.80,70.5,85.27,75.25};
int count,Nhour;
const int MAX_HOUR = 24;
float *calcul=NULL;
float *tab_time =NULL;
float ref_avg;
int size_hour=7;
float sum=0;
int length = Nhour+1;
float m;
float b;
calcul=(float*)calloc(MAX_HOUR,sizeof(calcul));
if (calcul==NULL)
{
printf(" error in buffer\n");
exit(EXIT_FAILURE);
}
tab_time= calloc(MAX_HOUR,sizeof(float));
/* Get the average of the first seven elements */
int i;
for (i=0;i<size_hour;i++)
{
sum += pval[i];
}
ref_avg = sum / size_hour;
count=0;
/* perform the regression analysis on 5 hours increment */
while(count<=MAX_HOUR)
{
++count;
Nhour=5;
int pass = -(Nhour-1);
int i=0;
for(i=0;i<Nhour+1;i++)
{
if(count<MAX_HOUR)
{
calcul[0]=ref_avg;
calcul[i] =pval[count+pass];
pass++;
}
printf("calc=%.2f\n",calcul[i]); // For debug only
tab_time[i]=i+1;
if(i==Nhour)
{
linear_regression(tab_time, calcul, length, &m, &b);
printf("Slope= %.2f\n", m);
}
}
}
free(calcul);
calcul=NULL;
free(tab_time);
tab_time=NULL;
return 0;
}
/* end of the main function */
/* This function is used to calculate the linear
regression as it was called above in the main function.
It compiles and runs very well, was just included for the
compilation and execution of the main function above where I have a problem. */
int linear_regression(const float *x, const float *y, const int n, float *beta1, float *beta0)
{
float sumx = 0,
sumy = 0,
sumx2 = 0,
sumxy = 0;
int i;
if (n <= 1) {
*beta1 = 0;
*beta0= 0;
printf("Not enough data for regression \n");
}
else
{
float variance;
for (i = 0; i < n; i++)
{
sumx += x[i];
sumy += y[i];
sumx2 += (x[i] * x[i]);
sumxy += (x[i] * y[i]);
}
variance = (sumx2 - ((sumx * sumx) / n));
if ( variance != 0) {
*beta1 = (sumxy - ((sumx * sumy) / n)) / variance;
*beta0 = (sumy - ((*beta1) * sumx)) / n;
}
else
{
*beta1 = 0;
*beta0 = 0;
}
}
return 0;
}
I think this code produces sane answers. The reference average quoted in the question seems to be wrong. The memory allocation is not needed. The value of MAX_HOUR was 24 but there were only 23 data values in the array. The indexing in building up the array to be regressed was bogus, referencing negative indexes in the pval array (and hence leading to erroneous results). The variable Nhour was referenced before it was initialized; the variable length was not correctly set. There wasn't good diagnostic printing.
The body of main() here is substantially rewritten; the editing on linear_regression() is much more nearly minimal. The code is more consistently laid out and white space has been used to make it easier to read. This version terminates the regression when there is no longer enough data left to fill the array with 5 values - it is not clear what the intended termination condition was.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void linear_regression(const float *x, const float *y, const int n,
float *beta1, float *beta0);
int main(void)
{
float pval[]={
76.26, 68.68, 71.49, 73.08, 72.99, 70.36, 57.82, 58.98,
69.71, 70.43, 77.53, 80.77, 70.30, 70.50, 70.79, 75.58,
76.88, 80.20, 77.69, 80.80, 70.50, 85.27, 75.25,
};
const int Nhour = 5;
const int MAX_HOUR = sizeof(pval)/sizeof(pval[0]);
const int size_hour = 7;
float ref_avg;
float sum = 0.0;
float m;
float b;
float calc_y[6];
float calc_x[6];
/* Get the average of the first seven elements */
for (int i = 0; i < size_hour; i++)
sum += pval[i];
ref_avg = sum / size_hour;
printf("ref avg = %5.2f\n", ref_avg); // JL
/* perform the regression analysis on 5 hours increment */
for (int pass = 0; pass <= MAX_HOUR - Nhour; pass++) // JL
{
calc_y[0] = ref_avg;
calc_x[0] = pass + 1;
printf("pass %d\ncalc_y[0] = %5.2f, calc_x[0] = %5.2f\n",
pass, calc_y[0], calc_x[0]);
for (int i = 1; i <= Nhour; i++)
{
int n = pass + i - 1;
calc_y[i] = pval[n];
calc_x[i] = pass + i + 1;
printf("calc_y[%d] = %5.2f, calc_x[%d] = %5.2f, n = %2d\n",
i, calc_y[i], i, calc_x[i], n);
}
linear_regression(calc_x, calc_y, Nhour+1, &m, &b);
printf("Slope= %5.2f, intercept = %5.2f\n", m, b);
}
return 0;
}
void linear_regression(const float *x, const float *y, const int n, float *beta1, float *beta0)
{
float sumx1 = 0.0;
float sumy1 = 0.0;
float sumx2 = 0.0;
float sumxy = 0.0;
assert(n > 1);
for (int i = 0; i < n; i++)
{
sumx1 += x[i];
sumy1 += y[i];
sumx2 += (x[i] * x[i]);
sumxy += (x[i] * y[i]);
}
float variance = (sumx2 - ((sumx1 * sumx1) / n));
if (variance != 0.0)
{
*beta1 = (sumxy - ((sumx1 * sumy1) / n)) / variance;
*beta0 = (sumy1 - ((*beta1) * sumx1)) / n;
}
else
{
*beta1 = 0.0;
*beta0 = 0.0;
}
}

Resources