Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid using global variables when using recursive functions in C

Tags:

c

recursion

The code below uses a recursive function called interp, but I cannot find a way to avoid using global variables for iter and fxInterpolated. The full code listing (that performs N-dimensional linear interpolation) compiles straightforwardly with:

gcc NDimensionalInterpolation.c -o NDimensionalInterpolation -Wall -lm

The output for the example given is 2.05. The code works fine but I want to find alternatives for the global variables. Any help with this would be greatly appreciated. Thanks.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int linearInterpolation(double *, double **, double *, int);
double ** allocateDoubleMatrix(int, int);
double * allocateDoubleVector(int);
void interp(int, int, double *, double *, double *);
double mult(int, double, double *, double *);

/* The objectionable global 
variables that I want to get rid of! */

int iter=0;
double fxInterpolated=0;

int main(int argc, char *argv[]){

 double *fx, **a, *x;
 int dims=2;

 x=allocateDoubleVector(dims);
 a=allocateDoubleMatrix(dims,2);
 fx=allocateDoubleVector(dims*2);

 x[0]=0.25;
 x[1]=0.4;

 a[0][0]=0;
 a[0][1]=1;
 a[1][0]=0;
 a[1][1]=1;

 fx[0]=1;
 fx[1]=3;
 fx[2]=2;
 fx[3]=4;
 linearInterpolation(fx, a, x, dims);
 printf("%f\n",fxInterpolated);

 return (EXIT_SUCCESS);

 } 

 int linearInterpolation(double *fx, double **a, double *x, int dims){

  double *b, *pos;
  int i;

  b=allocateDoubleVector(dims);
  pos=allocateDoubleVector(dims);

  for (i=0; i<dims;i++)
   b[i] = (x[i] - a[i][0]) / (a[i][1] -  a[i][0]);

  interp(0,dims,pos,fx,b); 

  return (EXIT_SUCCESS);

}  

void interp(int j, int dims, double *pos, double *fx, double *b) {

int i;

if (j == dims){
  fxInterpolated+=mult(dims,fx[iter],pos,b);
  iter++;
  return;
}

 for (i = 0; i < 2; i++){
   pos[j]=(double)i; 
   interp(j+1,dims,pos,fx,b);
 }

}

double mult(int dims, double fx, double *pos, double *b){

 int i;
 double val=1.0; 

 for (i = 0; i < dims; i++){
  val *= fabs(1.0-pos[i]-b[i]); 
 } 
 val *= fx;

 printf("mult val= %f fx=%f\n",val, fx);
 return val;

}

double ** allocateDoubleMatrix(int i, int j){

 int k;
 double ** matrix;
 matrix = (double **) calloc(i, sizeof(double *));
 for (k=0; k< i; k++)matrix[k] = allocateDoubleVector(j);
 return matrix;
}

 double * allocateDoubleVector(int i){
  double *vector;
  vector = (double *) calloc(i,sizeof(double));
  return vector;
}

Thanks for the comments so far. I want to avoid the use of static. I have removed the global variable and as suggested tried parsing with the iter variable. But no joy. In addition I am getting a compile warning: "value computed is not used" with reference to *iter++; What am I doing wrong?

void interp(int j, int dims, double *pos, double *fx, double *b, int *iter) {

int i;

if (j == dims){
fxInterpolated+=mult(dims,fx[*iter],pos,b);
*iter++;
return; 
}

 for (i = 0; i < 2; i++){
  pos[j]=(double)i; 
  interp(j+1,dims,pos,fx,b,iter);
 }

}

like image 632
Oik Avatar asked Feb 11 '23 00:02

Oik


1 Answers

There are two approaches I would consider when looking at this problem:

Keep the state in a parameter

You could use one or more variables that you pass to the function (as a pointer, if necessary) to keep the state across function calls.

For instance,

int global = 0;
int recursive(int argument) {
  // ... recursive stuff
  return recursive(new_argument);
}

could become

int recursive(int argument, int *global) {
  // ... recursive stuff
  return recursive(new_argument, global);
}

or sometimes even

int recursive(int argument, int global) {
  // ... recursive stuff
  return recursive(new_argument, global);
}

Use static variables

You can also declare a variable in a function to be preserved across function calls by using the static keyword:

int recursive(int argument) {
  static int global = 0;
  // ... recursive stuff
  return recursive(argument);
}

Note that because of the static keyword, global = 0 is only set when the program starts, not every time the function is called, as it would be without the keyword. This means that if you alter the value of global, it would keep this value the next time the function is called.

This method can be used if you only use your recursive function once during your program; if you need to use it multiple times, I recommend that you use the alternative method above.

like image 69
Frxstrem Avatar answered May 10 '23 02:05

Frxstrem