*
;
                options nosource;
%macro differ3d ( data, out, x, y, z, m, sorts );
options nosource nostimer nonotes nosymbolgen;

/* developed by Arnold Schick, ACC at the University of Marburg/Germany
  22. Dec. 1992 */

  %if &data =  and &out =  %then %do;
     %put ;
     %put macro-call : DIFFER3D(in,out, x,y,z, m, sort);
     %put ;
     %put this macro differs Z=F(X,Y) to X.;
     %put M corrects a slope on Z at X by that given value of M.;
     %put SORT directs macro for sorting input data set IN by X Y.;
     %put The result is written into dataset OUT.;
     %put ;
     %goto final;
  %end;
  %if &data  =  or &data  = . %then %let data = _LAST_ ;
  %if &out   =  or &out   = . %then %goto quit;
  %if &x     =  or &x     = . %then %let x=x;
  %if &y     =  or &y     = . %then %let y=y;
  %if &z     =  or &z     = . %then %let z=z;

  data _null_;
    b = symget ('m') / 1;
    if b = . then b = 0;
    call symput('m',b);
  run;

  %if &sorts = sort or &sorts = . or &sorts =  %then %do;
      proc sort data = &data  out = &out;
        by &x &y;
      run;
    %end;
      %else %do;
         data &out;
           set &data;
         run;
      %end;

  data _null_ ;
    set &out;
    if _N_ = 1 then call symput('y_1', &y);
    if _N_ = 2 then call symput('y_2', &y);
    if _N_ = 3 then do; call symput('y_3', &y); stop; end;
  run;

  data anfang(keep= &x dz_start);
     set &out ;
     x1 = lag( &x );
     y1 = lag( &y );
     z1 = lag( &z ) + &m * &y;
     if y1 = &y then delete;
     if &y_2 = &y or &y_3 = &y then do;
         dz   = ( &z + &m * &y - z1 )/( &y - y1 );
         dz_b = lag(dz);
         if &y_3 = &y then do;
            dz_start = 2*dz_b - dz;
            output anfang;
         end;
     end;
  run;

  data &out;
    set &out;
    merge &out anfang;
       by &x;
    length z_diff 8 ;
    y_previo = lag( &y );
    z_previo = lag( &z ) + &m * &y;
    if &y = y_previo then delete;
    if &y_1 = &y then z_diff = dz_start;
                 else if &m ^= 0 then z_diff = -(z_previo - &z + &y * &m)
                                               /( &y - y_previo);
                                 else z_diff = -(z_previo - &z)
                                               /( &y - y_previo);
    drop y_previo z_previo dz_start;
  run;

  %goto final ;
  %quit : %put HALT: please define OUT data set (2nd parameter) ;
  %final : ;

options source stimer notes;
%mend differ3d; options source;

/*
*Example;

data eins;                   * data-example one;
  do x=0 to 1 by 0.05;
     do y=0 to 2 by 0.1;
        z=exp(-x*y)/(2-cos(x*y))*sin(y-x);
        output;
     end;
  end;
run;

data eins;                   * data-example two;
  do x=-5 to 5 by 0.25;
     do y=-5 to 5 by 0.25;
        z = sin(sqrt(x*x + y*y));
        output;
     end;
  end;
run;

data eins;                   *data-example three;
 do i=1 to 30;
  x=10*ranuni(33)-5;
  y=10*ranuni(35)-5;
  z=sin(sqrt(x*x + y*y));
  output;
 end;
run;
proc g3grid data=eins out=eins;
  grid x*y=z / spline
               axis1=-5 to 5 by 0.25
               axis2=-5 to 5 by 0.25;
run;
proc sort data=eins out=eins;
  by x y;
run;                        *end of data-example three;


%differ3d;                                         *produces info;
%differ3d (eins, zwei,  x, y, z,-0.0025,nosort);   *F(x,y)/dx;
%differ3d (eins, drei,  y, x, z,.,sort);           *F(x,y)/dy;
%differ3d (drei, sechs, x, y, z_diff,0,sort);      *F(x,y)/dx/dy;
%differ3d (zwei, fuenf, y, x, z_diff,,sort);       *F(x,y)/dy/dx;

title 'orginal function';
proc g3d data=eins;
  plot y*x=z;
run;

title 'deriviation partial to X';
proc g3d data=zwei;
  plot y*x=z_diff ;
run;

title 'deriviation partial to Y';
proc g3d data=drei;
  plot y*x=z_diff;
run;

title 'deriviation partial to XY';
proc g3d data=fuenf;
  plot y*x=z_diff;
run;

title 'deriviation partial to YX';
proc g3d data=sechs;
  plot y*x=z_diff;
run;

*building of total deriviation;

proc sort data=drei out=drei; by x y; run;
data vier;
  set drei (rename=(z_diff=zz_diff));
  merge drei zwei;
   by x y;
   z_diff = zz_diff+z_diff;
run;
title 'deriviation total to X and Y';
proc g3d data=vier;
  plot y*x=z_diff;
run;

*End of Example;

    */
*
;