Problems 6
  1. Theory:
    1. What will the following code print?

      double k=0; 
      void foo(){ printf( "k=%g\n", k); }
      void bar(void f()){ f(); }
      int main(void) {
      	k=1; bar(foo);
      	k=2; bar(foo);
      	double k;
      	k=3; bar(foo);
      return 0;}
      
    2. What does the line

      double  k = *(double*)params;
      
      mean, if anything?
    3. When the 'tabulate' function from the exercise exits, is the parameter 'a' changed in the scope of the caller?

  2. Practice. Passing parameters to the argument-function (the 'foo' function in the example above) through the variables in the appropriate scope is not always the thing. Often you want to keep and pass the parameters to argument-function together with the function itself in a structure. Here is the exercise.
    1. Implement a function called tabulate that tabulates a double function of double argument --- but with some extra paramteters --- over a given interval with a given step. The function to tabulate together with its parameters must be kept in the following structure,

      struct my_function {double (*f)(double, void*); void* params;};
      
      The params are typed void* in order not to restrict the number and types of the parameters. If foo is of our type struct function the call to the function is done as
      double y = foo.f(x,foo.params);
      
      Here the absence of classes in C is mostly evident: the 'method' of the struct has no direct access to the fields of the struct.

      Hint:

      void tabulate(struct my_function *f, double a, double b, double dx){
        for(; a<b; a+=dx) printf( "%g\t%g\n", a, (*f).f(a,(*f).params) );
      }
      
    2. Tabulate the three functions, sin(x), sin(2x), sin(3x) using your tabulator and plot them. Represent the function to plot, sin(kx), as
      double sinkx(double x, void* params){
        double  k=*(double*)params;
        return sin(k*x);
      }
      

      Hints:

        Tabulation:
      1. struct my_function foo; double k=1,x1=0,dx=0.1,x2=2*M_PI+dx;
        foo.f=&sinkx;
        foo.params=(void*)&k;
        k=1; tabulate(&foo,x1,x2,dx); printf("\n");
        k=2; tabulate(&foo,x1,x2,dx); printf("\n");
        k=3; tabulate(&foo,x1,x2,dx); printf("\n");
        
      2. The pyxplot script
        set terminal pdf
        set output 'plot.pdf'
        set xlabel '$x$'
        set ylabel '$y$'
        plot 'data.out' with lines
        
    3. Tabulate and plot several parabolas, a+bx+cx2, with different coefficients 'a', 'b', and 'c'.

      Hints:

      1. Function:
        struct abc {double a,b,c;};
        double parabola(double x, void* params){
        	struct abc p = *(struct abc *)params;
        	return p.a + p.b*x + p.c*x*x;
        }
        
      2. Tabulation:
        struct my_function foo;
        struct abc p;
        double x1=0,x2=5,dx=0.1;
        foo.f=&sinkx;
        foo.params=(void*)&p;
        p.a=1;p.b=0;p.c=0; tabulate(&foo,x1,x2,dx); printf("\n");
        p.a=0;p.b=1;p.c=0; tabulate(&foo,x1,x2,dx); printf("\n");
        p.a=0;p.b=0;p.c=1; tabulate(&foo,x1,x2,dx); printf("\n");
        
    4. The makefile to build the project could then be something like
      CFLAGS = -Wall
      LDLIBS = -lm
      obj = main.o tabulate.o
      all: plot.pdf
      plot.pdf: plot.pyxplot data.out ; pyxplot $<
      data.out: main ; ./main > $@
      main: $(obj)
      clean: ; $(RM) $(obj) main data.out plot.pdf
      
    5. You can view the plot in the pdf-file (if you have a graphical session) with the command
      evince plot.pdf
      
      if you have installed 'evince' viewer, or with the command
      gv plot.pdf
      
      if you have installed 'gv' viewer, or with the command
      firefox plot.pdf
      
      if your have the firefox browser installed.