*
;

              options nosource;
/* QUICKINT - CALCULATES INTEGRATED FUNCTION  FROM A FUNCTION GIVEN
              IN PARAMETERFORM; AREA TO X-AXIS or BETWEEN TWO
              FUNCTIONS; AREA UNDER A ROC-CURVE.

    Written:  October 24,25, 1994, enhanced : December 12,1994
                                              January  20,1995
                                              April    21,1995
                                              August   21,1998
    Developed using SAS 6.08 for Windows
    Runable:  SAS 6.09 under AIX Unix; SAS 6.10 - 6.12 for Windows
    Author:   Arnold Schick
    Procs:    PROC DATASETS and PROC SORT
    Other:    SAS MACRO language
    Macros:   only QUICKINT
    Note:     Do not use _TEMP_ as a data set name.
              Please don't call %QUICKINT; or %QUICKINT();

    Macro Call: %QUICKINT(DATA,RESULT,X,Y,C,SORT);


MACRO VARIABLE      DESCRIPTION
------------------+-------------------------------------------------
 In Request:

 DATA               Name of SAS data set with input data. If this
                    parameter is missing or blank _LAST_ is used.
                    Integration-interval is between minimum and
                    maximum value of independent variable. No more
                    values shold be in input data set (if necessary
                    select data at first).

 RESULT             Name of SAS data set created by this macro.
                    If missing or blank stops the %macro. 2 new
                    variables are created: FACE and Y_SOURCE .

 X                  Variablename of independent variable in input SAS
                    data set DATA. If missing or blank, X is used.

 Y                  Variablename of dependent variable in input SAS
                    data set DATA. If missing or blank, Y is used.

 C                  Value of integration-constant. If missing or blank,
                    zero is used.

 SORT               Name of option for controlling of sorting the
                    input dataset by the independent variable. If name
                    of options other than SORT, blank or missing, no sorting
                    is applied. Useful for calculating of area between
                    two functions (see example at the end).


Example:

data one;
  do x=-1 to 8*atan(1) by atan(1)/64;
     y=cos(x);
     output;
   end;
run;
*%macro quickint (data,result, x, y, c,sort);
       %quickint (one ,two);
       %quickint (one ,two   , x, y,-1,sort);


For more information:

 Arnold Schick

 E-Mail: schick@yours.com

 If you  find an error-condition  (it is provided 'as it is')
 please let me know about this error-condition.  And when you
 have good tips for better formulation in SAS, let it also know.

  */


%macro quickint (data,result,x,y,c,sort);
 options nosource nostimer nosymbolgen nonotes nomprint;

  %if &data    =  or &data = . %then %let data = _LAST_ ;
  %if &result  =  or &result  = . %then %goto quit_1;
  %if &x       =  or &x    = . %then %let x = x;
  %if &y       =  or &y    = . %then %let y = y;
  %if &sort    =  or &sort = . or %upcase(&sort) = %upcase(sort)
    %then %let sort = sort; %else %let sort = notsort;
  data _NULL_;
    cc = symget('c')/1.0 ;
    if cc = . then cc = 0 ;
    call symput('c',cc);
  run;

%local empty;
data _NULL_ ;
    if 0 then set &data nobs=last;
    call symput('empty',last);
    stop;
run;

%if &empty < 2 %then %goto quit_2;
%if %upcase(&sort) ^= %STR(SORT) %then %do;
                                   data _temp_;
                                     set &data;
                                   run;
                                   %goto next;
                                %end;
proc sort data=&data out=_temp_;
  by &x;
run;
%next : ;
data &result;
  set _temp_ nobs=n end=last;
  length face y_source y_sourc2 Ax Ay 8 ;
  keep &x &y y_source face mx my;
  x_previo = lag(&x);
  y_previo = lag(&y);
  xm = (&x-x_previo)/2 + x_previo;
  retain x_begin ;
  if _N_ = 1 then do;
                y_sourc2 = &c;
                y_source = 0;
                face     = 0;
                x_begin  = &x;
                Ax = 0;  Ay = 0;
                Mx = &x; My = &y/2;
             end;
             else do;
                y_sourc2 = (xm-x_previo)*y_previo + (&x-xm)*&y;
                face + abs(y_sourc2);
                if (&y + y_previo)=0
                   then x0=xm;
                   else x0=(&x-(&x-x_previo)/3*(&y+2*y_previo)/(&y+y_previo));
                Ax + abs(y_sourc2)*x0;
                if (&x-x_previo)=0
                   then mm=0;
                   else mm=(&y-y_previo)/2/(&x-x_previo);
                bb = &y/2-mm*&x;
                Ay + abs(y_sourc2)*(mm*x0+bb);
                Mx = Ax/face;
                My = Ay/face;
             end;
  y_source + y_sourc2 ;
  if last then do;
    file print;
    x_end = &x ;
    c=&c;
    if face ^=0 then do; Ax = Ax/face;  Ay = Ay/face; end; else do; Ax=.; Ay=.; end;
    face=abs(face);
    put ' Results of QUICK-Integration';
    put ' ';
    put '    area=' face ' with main point at: ' "&x" '=' Ax ' , ' "&y" '=' Ay;
    put '    integrated between ' x_begin ' and ' x_end ;
    put '    with ' n ' points (observations from input data set ' "&data" ' were ' "&sort" 'ed)' ;
    put '    integration constant=' c '.' ;
    put '    Results are stored into data set ' "&result" ;
  end;
  run;

proc datasets nolist;
  delete _temp_ ;
quit;

%goto final ;
%quit_1 : %put         MACRO-HALT: Please define result data set. ;
  %goto final;
%quit_2 : %put         MACRO-HALT: Number of observations in input data set less than 2 or;
          %put         input data set &data is empty. ;
%final : ;

 options source stimer notes;
%mend quickint;   options source;



/*Example section */


*integration of a function;

data one;                          *creates function values and stores into dataset ONE;
  do x=0 to 4*atan(1) by atan(1)/128;
     y=sin(x);
     output;
  end;
run;

*%macro quickint (data,result,x,y, c,sort);
       %quickint (one ,result, , ,-1);          *exact value for area assumes 2.0;

proc gplot;                      *displays the results;
  symbol i=join r=123 c=;
  plot (y y_source face) * x / overlay;
run; quit;


*special example: area between two functions;

data one;                         *the first function must be sorted in ascending order;
  do x=-1 to 4 by atan(1)/128;
     y=sin(x*x*0.89)-0.3;
     output;
  end;
run;

data two;                         *the second function must be sorted in descending order;
  do x=4 to -1 by -atan(1)/128;
     y=-sin(x);
     output;
  end;
  x=-1;
  y=sin(x*x*0.89)-0.3;
  output;                         *last value-pair should be the first values from ONE;
run;
proc append base=one data=two; run;    *both functions are included in dataset ONE;

%quickint(one,result,x,y,0,notsort);   *needs macro-option NOTSORT,
                                        integration-constant is set to 0 !;

                                  *dispays area between both functions;
axis1 order=-1 to 4 by 1  length=11 cm;
axis2 order=-2 to 2 by 1  length=11 cm;
symbol i=join;
proc gplot;
  plot y *x/areas=1 haxis=axis1 vaxis=axis2;
run; quit;


*example:
 calculating of an ara from a circle with radius=1, exact area=3.141592...;

data two;
  do alpha=0 to 4*atan(1) by atan(1)/64;
      x=cos(alpha);
      y=sin(alpha);
     output;
  end;
run;
proc sort data=two;
  by x;
run;
proc sort data=two out=three;
  by descending x;
run;
data three;
  set three;
  y=-y;
run;
proc append base=two data=three; run;

%quickint(two,result,x,y,0,notsort);   *needs macro-option NOTSORT and
                                        integration-constant is set to 0;

axis1 order=-1 to 1 by 1  length=8 cm;
axis2 order=-1 to 1 by 1  length=8 cm;
symbol i=join;
proc gplot;
  plot y *x/areas=1 haxis=axis1 vaxis=axis2;
run; quit;


/* End of example section */

*
;