*
;
              options nosource;
/* NEAREST  - CALCULATES MIN, MAX, MEAN DISTANCES OF FUNCTION-VALUES
              WHERE THE DISTANCES CAN BE SQUARE OR ROOT OF SQUARE.

    Written:  June 20, 1995
    Updated:  January 17, 1996

    Developed using SAS 6.10 for Windows
    Run able: SAS 6.09 under AIX Unix, SAS 6.08 for Windows, SAS 6.04 under DOS
    Author:   Arnold Schick
    Procs:    PROC RANK, SORT and DATASETS
    Other:    SAS MACRO language
    Macros:   only NEAREST
    Note:     Do not use _TEMP_ as a data set name.
              Please don't call %NEAREST; or %NEAREST();

    Macro Call: %NEAREST(DATA,N,RESULT,X,Y,SQRT);


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

 DATA               Name of SAS data set with input data. If this
                    parameter is missing or blank _LAST_ is used.

 N                  Number of nearest function-values. If blank or
                    missing N is set to 5.

 RESULT             Name of SAS data set created by this macro.
                    If missing or blank stops the %macro. Two new
                    variables are created: D and RANK_D.
                    D      obtains the calculated distance or square
                           distance
                    RANK_D abtains the rank of D.

 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.

 SQRT               Name of option for sort of distance.
                    SQRT   means the direct-distance to the previous
                           function-values, calculated as:
                           d = sqrt(Xi-Xi-1)**2 + (Yi-Yi-1))
                    if otherwise specified, square-distance:
                           d = (Xi-Xi-1)**2 + (Yi-Yi-1)**2 is used.

Example:

data one;
  do x=-1 to 8*atan(1) by atan(1)/64;
     y=sin(x);
     output;
   end;
run;
*%macro nearest (data,n,result, x, y, sqrt);
       %nearest ( one,6,two,    x, y, nosqrt );
       %nearest ( one,5,two);


For more information:

 Arnold Schick

 University of Marburg
 Academic Computing Center
 Hans-Meerwein-Str.
 35032 Marburg/Lahn   Germany

 Internet: schick@hrz.uni-marburg.de

 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.

  */

               options nosource;
%macro nearest(data,n,result,x,y,sqrt);
       options nosource nostimer nosymbolgen nonotes nomprint;

  %if &data    =  or &data = . %then %let data = _LAST_ ;
  %if &n       =  or &n    = . %then %let n    = 5;
  %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 &sqrt    =  or &sqrt = . or %upcase(&sqrt) = %upcase(sqrt)
    %then %let sqrt = sqrt; %else %let sqrt = square;

%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(&sqrt) = %STR(SQRT) %then %do;
data _temp_;
  set &data;
  d=sqrt(dif(&x)**2 + dif(&y)**2);
  n=_N_;
  if n=1 then delete;
run; %end;
%else %do;
data _temp_;
  set &data;
  d=dif(&x)**2 + dif(&y)**2;
  n=_N_;
  if n=1 then delete;
run; %end;

proc rank data=_temp_ out=&result;
  var d;
  ranks rank_d;
run;
proc sort data=&result out=&result;
  by rank_d;
run;
options notes;
data &result;
  set &result nobs=obs;
  if _N_ < &n+1 or _N_ > obs-&n;
run;
options nonotes;
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 nearest;  options source;

/*

*Example;
                                 *creates simple function into dataset ONE;
data one;
  do x=-1 to 1 by 0.01;
     y= cos(x/cos(x));
     output;
  end;
run;

*%macro nearest  (data,n,result,x,y,sqrt);
       %nearest  (one ,2,result, , ,sqrt);

proc print data=result;          *prints the result;
run; quit;

       %nearest  (one ,9999,result, , ,sqrt);

proc gplot data=result;                      *displays the results;
  symbol i=join r=123 ;
  plot (y d) * x / nolegend;
run; quit;
*/

*
;