zoukankan      html  css  js  c++  java
  • scatter plots smooth算法 lowess

    C++版本

    /*
     *  c++ implementation of Lowess weighted regression by 
     *  Peter Glaus http://www.cs.man.ac.uk/~glausp/
     *
     *
     *  Based on fortran code by Cleveland downloaded from:
     *  http://netlib.org/go/lowess.f
     *  original author:
    * wsc@research.bell-labs.com Mon Dec 30 16:55 EST 1985
    * W. S. Cleveland
    * Bell Laboratories
    * Murray Hill NJ 07974
     *  
     *  See original documentation below the code for details.
     * 
     */
    #include<algorithm>
    #include<cmath>
    #include<fstream>
     
    using namespace std;
     
    #include "lowess.h"
    #include "common.h"
     
    void lowess(const vector<double> &x, const vector<double> &y, double f, long nsteps, vector<double> &ys){//{{{
       vector<double> rw,res;
       lowess(x,y,f,nsteps,0.,ys,rw,res);
    }//}}}
    void lowess(const vector<double> &x, const vector<double> &y, double f, long nsteps, double delta, vector<double> &ys, vector<double> &rw, vector<double>&res){ //{{{
       long n=(long)x.size();
       bool ok=false;
       long nleft,nright, i, j, iter, last, m1, m2, ns;
       double cut, cmad, r, d1, d2, c1, c9, alpha, denom;
       if((n==0)||((long)y.size()!=n)) return;
       ys.resize(n);
       rw.resize(n);
       res.resize(n);
       if(n==1){
          ys[0]=y[0];
          return;
       }
       // ns - at least 2, at most n
       ns = max(min((long)(f*n),n),(long)2);
       for(iter=0;iter<nsteps+1; iter++){
          // robustnes iterations
          nleft = 0;
          nright = ns-1;
          // index of last estimated point
          last = -1;
          // index of current point
          i=0;
          do{
             while(nright<n-1){
                // move <nleft,nright> right, while radius decreases
                d1 = x[i]-x[nleft];
                d2 = x[nright+1] - x[i];
                if(d1<=d2)break;
                nleft++;
                nright++;
             }
             // fit value at x[i]
             lowest(x,y,x[i],ys[i],nleft,nright,res,iter>0,rw,ok);
             if(!ok) ys[i]=y[i];
             if(last<i-1){
                // interpolate skipped points
                if(last<0){
                   warning("Lowess: out of range.
    ");
                }
                denom = x[i] - x[last];
                for(j=last+1;j<i;j++){
                   alpha = (x[j]-x[last])/denom;
                   ys[j] = alpha * ys[i] + (1.0-alpha)*ys[last];
                }
             }
             last = i;
             cut = x[last]+delta;
             for(i=last+1;i<n;i++){
                if(x[i]>cut)break;
                if(x[i]==x[last]){
                   ys[i]=ys[last];
                   last=i;
                }
             }
             i=max(last+1,i-1);
          }while(last<n-1);
          for(i=0;i<n;i++)
             res[i] = y[i]-ys[i];
          if(iter==nsteps)break ;
          for(i=0;i<n;i++)
             rw[i]=abs(res[i]);
          sort(rw.begin(),rw.end());
          m1 = n/2+1;
          m2 = n-m1;
          m1 --;
          cmad = 3.0 *(rw[m1]+rw[m2]);
          c9 = .999*cmad;
          c1 = .001*cmad;
          for(i=0;i<n;i++){
             r = abs(res[i]);
             if(r<=c1) rw[i]=1;
             else if(r>c9) rw[i]=0;
             else rw[i] = (1.0-(r/cmad)*(r/cmad))*(1.0-(r/cmad)*(r/cmad));
          }
       }
    }//}}}
     
    void lowest(const vector<double> &x, const vector<double> &y, double xs, double &ys, long nleft, long nright, vector<double> &w, bool userw,  vector<double> &rw, bool &ok){//{{{
       long n = (long)x.size();
       long nrt, j;
       double a, b, c, h, r, h1, h9, range;
       range = x[n-1]-x[0];
       h = max(xs-x[nleft],x[nright]-xs);
       h9 = 0.999*h;
       h1 = 0.001*h;
       // sum of weights
       a = 0; 
       for(j=nleft;j<n;j++){
          // compute weights (pick up all ties on right)
          w[j]=0.;
          r = abs(x[j]-xs);
          if(r<=h9){
             // small enough for non-zero weight
             if(r>h1) w[j] = (1.0-(r/h)*(r/h)*(r/h))*(1.0-(r/h)*(r/h)*(r/h))*(1.0-(r/h)*(r/h)*(r/h));
             else w[j] = 1.;
             if(userw) w[j] *= rw[j];
             a += w[j];
          }else if(x[j]>xs) break; // get out at first zero wt on right
       }
       nrt = j-1;
       // rightmost pt (may be greater than nright because of ties)
       if(a<=0.) ok = false;
       else{
          // weighted least squares
          ok = true;
          // normalize weights
          for(j=nleft;j<=nrt;j++)
             w[j] /= a;
          if(h>0.){
             // use linear fit
             a = 0.;
             for(j=nleft;j<=nrt;j++)
                a += w[j]*x[j]; // weighted centre of values
             b = xs-a;
             c = 0;
             for(j=nleft;j<=nrt;j++)
                c += w[j]*(x[j]-a)*(x[j]-a);
             if(sqrt(c)>0.001*range){
                // points are spread enough to compute slope
                b /= c;
                for(j=nleft;j<=nrt;j++)
                   w[j] *= (1.0+b*(x[j]-a));
             }
          }
          ys = 0;
          for(j=nleft;j<=nrt;j++)
             ys += w[j]*y[j];
       }
    }//}}}
     
    /* {{{ Documentation
    * wsc@research.bell-labs.com Mon Dec 30 16:55 EST 1985
    * W. S. Cleveland
    * Bell Laboratories
    * Murray Hill NJ 07974
    * 
    * outline of this file:
    *    lines 1-72   introduction
    *        73-177   documentation for lowess
    *       178-238   ratfor version of lowess
    *       239-301   documentation for lowest
    *       302-350   ratfor version of lowest
    *       351-end   test driver and fortran version of lowess and lowest
    * 
    *   a multivariate version is available by "send dloess from a"
    * 
    *              COMPUTER PROGRAMS FOR LOCALLY WEIGHTED REGRESSION
    * 
    *             This package consists  of  two  FORTRAN  programs  for
    *        smoothing    scatterplots   by   robust   locally   weighted
    *        regression, or lowess.   The  principal  routine  is  LOWESS
    *        which   computes   the  smoothed  values  using  the  method
    *        described in The Elements of Graphing Data, by William S.
    *        Cleveland    (Wadsworth,    555 Morego   Street,   Monterey,
    *        California 93940).
    * 
    *             LOWESS calls a support routine, LOWEST, the code for
    *        which is included. LOWESS also calls a routine  SORT,  which
    *        the user must provide.
    * 
    *             To reduce the computations, LOWESS  requires  that  the
    *        arrays  X  and  Y,  which  are  the  horizontal and vertical
    *        coordinates, respectively, of the scatterplot, be such  that
    *        X  is  sorted  from  smallest  to  largest.   The  user must
    *        therefore use another sort routine which will sort X  and  Y
    *        according  to X.
    *             To summarize the scatterplot, YS,  the  fitted  values,
    *        should  be  plotted  against X.   No  graphics  routines are
    *        available in the package and must be supplied by the user.
    * 
    *             The FORTRAN code for the routines LOWESS and LOWEST has
    *        been   generated   from   higher   level   RATFOR   programs
    *        (B. W. Kernighan, ``RATFOR:  A Preprocessor for  a  Rational
    *        Fortran,''  Software Practice and Experience, Vol. 5 (1975),
    *        which are also included.
    * 
    *             The following are data and output from LOWESS that  can
    *        be  used  to check your implementation of the routines.  The
    *        notation (10)v means 10 values of v.
    * 
    * 
    * 
    * 
    *        X values:
    *          1  2  3  4  5  (10)6  8  10  12  14  50
    * 
    *        Y values:
    *           18  2  15  6  10  4  16  11  7  3  14  17  20  12  9  13  1  8  5  19
    * 
    * 
    *        YS values with F = .25, NSTEPS = 0, DELTA = 0.0
    *         13.659  11.145  8.701  9.722  10.000  (10)11.300  13.000  6.440  5.596
    *           5.456  18.998
    * 
    *        YS values with F = .25, NSTEPS = 0 ,  DELTA = 3.0
    *          13.659  12.347  11.034  9.722  10.511  (10)11.300  13.000  6.440  5.596
    *            5.456  18.998
    * 
    *        YS values with F = .25, NSTEPS = 2, DELTA = 0.0
    *          14.811  12.115  8.984  9.676  10.000  (10)11.346  13.000  6.734  5.744
    *            5.415  18.998
    * 
    * 
    * 
    * 
    *                                   LOWESS
    * 
    * 
    * 
    *        Calling sequence
    * 
    *        CALL LOWESS(X,Y,N,F,NSTEPS,DELTA,YS,RW,RES)
    * 
    *        Purpose
    * 
    *        LOWESS computes the smooth of a scatterplot of Y  against  X
    *        using  robust  locally  weighted regression.  Fitted values,
    *        YS, are computed at each of the  values  of  the  horizontal
    *        axis in X.
    * 
    *        Argument description
    * 
    *              X = Input; abscissas of the points on the
    *                  scatterplot; the values in X must be ordered
    *                  from smallest to largest.
    *              Y = Input; ordinates of the points on the
    *                  scatterplot.
    *              N = Input; dimension of X,Y,YS,RW, and RES.
    *              F = Input; specifies the amount of smoothing; F is
    *                  the fraction of points used to compute each
    *                  fitted value; as F increases the smoothed values
    *                  become smoother; choosing F in the range .2 to
    *                  .8 usually results in a good fit; if you have no
    *                  idea which value to use, try F = .5.
    *         NSTEPS = Input; the number of iterations in the robust
    *                  fit; if NSTEPS = 0, the nonrobust fit is
    *                  returned; setting NSTEPS equal to 2 should serve
    *                  most purposes.
    *          DELTA = input; nonnegative parameter which may be used
    *                  to save computations; if N is less than 100, set
    *                  DELTA equal to 0.0; if N is greater than 100 you
    *                  should find out how DELTA works by reading the
    *                  additional instructions section.
    *             YS = Output; fitted values; YS(I) is the fitted value
    *                  at X(I); to summarize the scatterplot, YS(I)
    *                  should be plotted against X(I).
    *             RW = Output; robustness weights; RW(I) is the weight
    *                  given to the point (X(I),Y(I)); if NSTEPS = 0,
    *                  RW is not used.
    *            RES = Output; residuals; RES(I) = Y(I)-YS(I).
    * 
    * 
    *        Other programs called
    * 
    *               LOWEST
    *               SSORT
    * 
    *        Additional instructions
    * 
    *        DELTA can be used to save computations.   Very  roughly  the
    *        algorithm  is  this:   on the initial fit and on each of the
    *        NSTEPS iterations locally weighted regression fitted  values
    *        are computed at points in X which are spaced, roughly, DELTA
    *        apart; then the fitted values at the  remaining  points  are
    *        computed  using  linear  interpolation.   The  first locally
    *        weighted regression (l.w.r.) computation is carried  out  at
    *        X(1)  and  the  last  is  carried  out at X(N).  Suppose the
    *        l.w.r. computation is carried out at  X(I).   If  X(I+1)  is
    *        greater  than  or  equal  to  X(I)+DELTA,  the  next  l.w.r.
    *        computation is carried out at X(I+1).   If  X(I+1)  is  less
    *        than X(I)+DELTA, the next l.w.r.  computation is carried out
    *        at the largest X(J) which is greater than or equal  to  X(I)
    *        but  is not greater than X(I)+DELTA.  Then the fitted values
    *        for X(K) between X(I)  and  X(J),  if  there  are  any,  are
    *        computed  by  linear  interpolation  of the fitted values at
    *        X(I) and X(J).  If N is less than 100 then DELTA can be  set
    *        to  0.0  since  the  computation time will not be too great.
    *        For larger N it is typically not necessary to carry out  the
    *        l.w.r.  computation for all points, so that much computation
    *        time can be saved by taking DELTA to be  greater  than  0.0.
    *        If  DELTA =  Range  (X)/k  then,  if  the  values  in X were
    *        uniformly  scattered  over  the  range,  the   full   l.w.r.
    *        computation  would be carried out at approximately k points.
    *        Taking k to be 50 often works well.
    * 
    *        Method
    * 
    *        The fitted values are computed by using the nearest neighbor
    *        routine  and  robust locally weighted regression of degree 1
    *        with the tricube weight function.  A few additional features
    *        have  been  added.  Suppose r is FN truncated to an integer.
    *        Let  h  be  the  distance  to  the  r-th  nearest   neighbor
    *        from X(I).   All  points within h of X(I) are used.  Thus if
    *        the r-th nearest neighbor is exactly the  same  distance  as
    *        other  points,  more  than r points can possibly be used for
    *        the smooth at  X(I).   There  are  two  cases  where  robust
    *        locally  weighted regression of degree 0 is actually used at
    *        X(I).  One case occurs when  h  is  0.0.   The  second  case
    *        occurs  when  the  weighted  standard error of the X(I) with
    *        respect to the weights w(j) is  less  than  .001  times  the
    *        range  of the X(I), where w(j) is the weight assigned to the
    *        j-th point of X (the tricube  weight  times  the  robustness
    *        weight)  divided by the sum of all of the weights.  Finally,
    *        if the w(j) are all zero for the smooth at X(I), the  fitted
    *        value is taken to be Y(I).
    * 
    * 
    * 
    * 
    *  subroutine lowess(x,y,n,f,nsteps,delta,ys,rw,res)
    *  real x(n),y(n),ys(n),rw(n),res(n)
    *  logical ok
    *  if (n<2){ ys(1) = y(1); return }
    *  ns = max0(min0(ifix(f*float(n)),n),2)  # at least two, at most n points
    *  for(iter=1; iter<=nsteps+1; iter=iter+1){      # robustness iterations
    *         nleft = 1; nright = ns
    *         last = 0        # index of prev estimated point
    *         i = 1   # index of current point
    *         repeat{
    *                 while(nright<n){
    *  # move nleft, nright to right if radius decreases
    *                         d1 = x(i)-x(nleft)
    *                         d2 = x(nright+1)-x(i)
    *  # if d1<=d2 with x(nright+1)==x(nright), lowest fixes
    *                         if (d1<=d2) break
    *  # radius will not decrease by move right
    *                         nleft = nleft+1
    *                         nright = nright+1
    *                         }
    *                 call lowest(x,y,n,x(i),ys(i),nleft,nright,res,iter>1,rw,ok)
    *  # fitted value at x(i)
    *                 if (!ok) ys(i) = y(i)
    *  # all weights zero - copy over value (all rw==0)
    *                 if (last<i-1) { # skipped points -- interpolate
    *                         denom = x(i)-x(last)    # non-zero - proof?
    *                         for(j=last+1; j<i; j=j+1){
    *                                 alpha = (x(j)-x(last))/denom
    *                                 ys(j) = alpha*ys(i)+(1.0-alpha)*ys(last)
    *                                 }
    *                         }
    *                 last = i        # last point actually estimated
    *                 cut = x(last)+delta     # x coord of close points
    *                 for(i=last+1; i<=n; i=i+1){     # find close points
    *                         if (x(i)>cut) break     # i one beyond last pt within cut
    *                         if(x(i)==x(last)){      # exact match in x
    *                                 ys(i) = ys(last)
    *                                 last = i
    *                                 }
    *                         }
    *                 i=max0(last+1,i-1)
    *  # back 1 point so interpolation within delta, but always go forward
    *                 } until(last>=n)
    *         do i = 1,n      # residuals
    *                 res(i) = y(i)-ys(i)
    *         if (iter>nsteps) break  # compute robustness weights except last time
    *         do i = 1,n
    *                 rw(i) = abs(res(i))
    *         call sort(rw,n)
    *         m1 = 1+n/2; m2 = n-m1+1
    *         cmad = 3.0*(rw(m1)+rw(m2))      # 6 median abs resid
    *         c9 = .999*cmad; c1 = .001*cmad
    *         do i = 1,n {
    *                 r = abs(res(i))
    *                 if(r<=c1) rw(i)=1.      # near 0, avoid underflow
    *                 else if(r>c9) rw(i)=0.  # near 1, avoid underflow
    *                 else rw(i) = (1.0-(r/cmad)**2)**2
    *                 }
    *         }
    *  return
    *  end
    * 
    * 
    * 
    * 
    *                                   LOWEST
    * 
    * 
    * 
    *        Calling sequence
    * 
    *        CALL LOWEST(X,Y,N,XS,YS,NLEFT,NRIGHT,W,USERW,RW,OK)
    * 
    *        Purpose
    * 
    *        LOWEST is a support routine for LOWESS and  ordinarily  will
    *        not  be  called  by  the  user.   The  fitted  value, YS, is
    *        computed  at  the  value,  XS,  of  the   horizontal   axis.
    *        Robustness  weights,  RW,  can  be employed in computing the
    *        fit.
    * 
    *        Argument description
    * 
    * 
    *              X = Input; abscissas of the points on the
    *                  scatterplot; the values in X must be ordered
    *                  from smallest to largest.
    *              Y = Input; ordinates of the points on the
    *                  scatterplot.
    *              N = Input; dimension of X,Y,W, and RW.
    *             XS = Input; value of the horizontal axis at which the
    *                  smooth is computed.
    *             YS = Output; fitted value at XS.
    *          NLEFT = Input; index of the first point which should be
    *                  considered in computing the fitted value.
    *         NRIGHT = Input; index of the last point which should be
    *                  considered in computing the fitted value.
    *              W = Output; W(I) is the weight for Y(I) used in the
    *                  expression for YS, which is the sum from
    *                  I = NLEFT to NRIGHT of W(I)*Y(I); W(I) is
    *                  defined only at locations NLEFT to NRIGHT.
    *          USERW = Input; logical variable; if USERW is .TRUE., a
    *                  robust fit is carried out using the weights in
    *                  RW; if USERW is .FALSE., the values in RW are
    *                  not used.
    *             RW = Input; robustness weights.
    *             OK = Output; logical variable; if the weights for the
    *                  smooth are all 0.0, the fitted value, YS, is not
    *                  computed and OK is set equal to .FALSE.; if the
    *                  fitted value is computed OK is set equal to
    * 
    * 
    *        Method
    * 
    *        The smooth at XS is computed using (robust) locally weighted
    *        regression of degree 1.  The tricube weight function is used
    *        with h equal to the maximum of XS-X(NLEFT) and X(NRIGHT)-XS.
    *        Two  cases  where  the  program  reverts to locally weighted
    *        regression of degree 0 are described  in  the  documentation
    *        for LOWESS.
    * 
    * 
    * 
    * 
    *  subroutine lowest(x,y,n,xs,ys,nleft,nright,w,userw,rw,ok)
    *  real x(n),y(n),w(n),rw(n)
    *  logical userw,ok
    *  range = x(n)-x(1)
    *  h = amax1(xs-x(nleft),x(nright)-xs)
    *  h9 = .999*h
    *  h1 = .001*h
    *  a = 0.0        # sum of weights
    *  for(j=nleft; j<=n; j=j+1){     # compute weights (pick up all ties on right)
    *         w(j)=0.
    *         r = abs(x(j)-xs)
    *         if (r<=h9) {    # small enough for non-zero weight
    *                 if (r>h1) w(j) = (1.0-(r/h)**3)**3
    *                 else      w(j) = 1.
    *                 if (userw) w(j) = rw(j)*w(j)
    *                 a = a+w(j)
    *                 }
    *         else if(x(j)>xs)break   # get out at first zero wt on right
    *         }
    *  nrt=j-1        # rightmost pt (may be greater than nright because of ties)
    *  if (a<=0.0) ok = FALSE
    *  else { # weighted least squares
    *         ok = TRUE
    *         do j = nleft,nrt
    *                 w(j) = w(j)/a   # make sum of w(j) == 1
    *         if (h>0.) {     # use linear fit
    *                 a = 0.0
    *                 do j = nleft,nrt
    *                         a = a+w(j)*x(j) # weighted center of x values
    *                 b = xs-a
    *                 c = 0.0
    *                 do j = nleft,nrt
    *                         c = c+w(j)*(x(j)-a)**2
    *                 if(sqrt(c)>.001*range) {
    *  # points are spread out enough to compute slope
    *                         b = b/c
    *                         do j = nleft,nrt
    *                                 w(j) = w(j)*(1.0+b*(x(j)-a))
    *                         }
    *                 }
    *         ys = 0.0
    *         do j = nleft,nrt
    *                 ys = ys+w(j)*y(j)
    *         }
    *  return
    *  end
    * 
    }}}*/
    

    C版本

    #define FALSE 0
    #define TRUE 1
     
    long min (long x, long y)
    {
    	return((x < y) ? x : y);
    }
     
    long max (long x, long y)
    {
    	return((x > y) ? x : y);
    }
     
    static double pow2(double x) { return(x * x); }
    static double pow3(double x) { return(x * x * x); }
    double fmax(double x, double y) { return (x > y ? x : y); }
     
    int static compar(const void *aa, const void *bb)
    {
    	const double* a = (double*)aa;
    	const double* b = (double*)bb;
     
    	if (*a < *b) return(-1);
    	else if (*a > *b) return(1);
    	else return(0);
    }
     
    static void lowest(const double *x, const double *y, size_t n, double xs, double *ys, long nleft, long nright,
    	double *w, int userw, double *rw, int *ok)
    {
    	double range, h, h1, h9, a, b, c, r;
    	long j, nrt;
     
    	range = x[n - 1] - x[0];
    	h = fmax(xs - x[nleft], x[nright] - xs);
    	h9 = .999 * h;
    	h1 = .001 * h;
     
    	/* compute weights (pick up all ties on right) */
    	a = 0.0;        /* sum of weights */
    	for(j = nleft; j < n; j++)
    	{
    		w[j]=0.0;
    		r = fabs(x[j] - xs);
    		if (r <= h9) 
    		{    /* small enough for non-zero weight */
    			if (r > h1) w[j] = pow3(1.0-pow3(r/h));
    			else w[j] = 1.0;
    			if (userw) w[j] = rw[j] * w[j];
    			a += w[j];
    		}
    		else if (x[j] > xs) break;  /* get out at first zero wt on right */
    	}
    	nrt = j - 1;  /* rightmost pt (may be greater than nright because of ties) */
    	if (a <= 0.0) *ok = FALSE;
    	else { /* weighted least squares */
    		*ok = TRUE;
     
    		/* make sum of w[j] == 1 */
    		for (j = nleft; j <= nrt; j++) w[j] = w[j] / a;
     
    		if (h > 0.0) {     /* use linear fit */
     
    			/* find weighted center of x values */
    			for (j = nleft, a = 0.0; j <= nrt; j++) a += w[j] * x[j];
     
    			b = xs - a;
    			for (j = nleft, c = 0.0; j <= nrt; j++) 
    				c += w[j] * (x[j] - a) * (x[j] - a);
     
    			if(sqrt(c) > .001 * range) {
    				/* points are spread out enough to compute slope */
    				b = b/c;
    				for (j = nleft; j <= nrt; j++) 
    					w[j] = w[j] * (1.0 + b*(x[j] - a));
    			}
    		}
    		for (j = nleft, *ys = 0.0; j <= nrt; j++) *ys += w[j] * y[j];
    	}
    }
     
    static void sort(double *x, size_t n)
    {
    	qsort(x, n, sizeof(double), compar);
    }
     
    int lowess(const double *x, const double *y, size_t n,double f, size_t nsteps,
    	double delta, double *ys, double *rw, double *res)
    {
    	int iter, ok;
    	long i, j, last, m1, m2, nleft, nright, ns;
    	double d1, d2, denom, alpha, cut, cmad, c9, c1, r;
     
    	if (n < 2) { ys[0] = y[0]; return(1); }
    	ns = max(min((long) (f * n), n), 2);  /* at least two, at most n points */
    	for(iter = 1; iter <= nsteps + 1; iter++){      /* robustness iterations */
    		nleft = 0; nright = ns - 1;
    		last = -1;        /* index of prev estimated point */
    		i = 0;   /* index of current point */
    		do {
    			while(nright < n - 1){
    				/* move nleft, nright to right if radius decreases */
    				d1 = x[i] - x[nleft];
    				d2 = x[nright + 1] - x[i];
    				/* if d1 <= d2 with x[nright+1] == x[nright], lowest fixes */
    				if (d1 <= d2) break;
    				/* radius will not decrease by move right */
    				nleft++;
    				nright++;
    			}
    			lowest(x, y,
    				n, x[i],
    				&ys[i],
    				nleft, nright,
    				res, (iter > 1), rw, &ok);
    			/* fitted value at x[i] */
    			if (! ok) ys[i] = y[i];
    			/* all weights zero - copy over value (all rw==0) */
    			if (last < i - 1) { /* skipped points -- interpolate */
    				denom = x[i] - x[last];    /* non-zero - proof? */
    				for(j = last + 1; j < i; j = j + 1){
    					alpha = (x[j] - x[last]) / denom;
    					ys[j] = alpha * ys[i] + (1.0 - alpha) * ys[last];
    				}
    			}
    			last = i;        /* last point actually estimated */
    			cut = x[last] + delta;     /* x coord of close points */
    			for(i=last + 1; i < n; i++) {     /* find close points */
    				if (x[i] > cut) break;     /* i one beyond last pt within cut */
    				if(x[i] == x[last]) {      /* exact match in x */
    					ys[i] = ys[last];
    					last = i;
    				}
    			}
    			i = max(last + 1,i - 1);
    			/* back 1 point so interpolation within delta, but always go forward */
    		} while(last < n - 1);
    		for (i = 0; i < n; i++)      /* residuals */
    			res[i] = y[i] - ys[i];
    		if (iter > nsteps) break; /* compute robustness weights except last time */
    		for (i = 0; i < n; i++) 
    			rw[i] = fabs(res[i]);
    		sort(rw,n);
    		m1 = 1 + n / 2; m2 = n - m1 + 1;
    		cmad = 3.0 * (rw[m1] + rw[m2]);      /* 6 median abs resid */
    		c9 = .999 * cmad; c1 = .001 * cmad;
    		for (i = 0; i < n; i++) {
    			r = fabs(res[i]);
    			if(r <= c1) rw[i] = 1.0;      /* near 0, avoid underflow */
    			else if(r > c9) rw[i] = 0.0;  /* near 1, avoid underflow */
    			else rw[i] = pow2(1.0 - pow2(r / cmad));
    		}
    	}
    	return(0);
    }
    

    测试main函数

    void test_smooth()
    {
    	const double in[] = {
    		-55.1047,
    		-56.3673,
    		-56.314,
    		-55.8626,
    		-56.3733,
    		-55.8694,
    		-54.4476,
    		-56.1106,
    		-58.3752,
    		-56.4632,
    		-57.5418,
    		-57.259,
    		-54.999,
    		-56.5903,
    		-56.5675,
    		-57.2702,
    		-56.5198,
    		-59.275,
    		-58.0706,
    		-55.4509,
    		-58.1618,
    		-57.2596,
    		-55.4555,
    		-55.7893,
    		-55.7953,
    		-55.8368,
    		-57.3642,
    		-57.5559,
    		-56.0514,
    		-56.8001,
    		-58.4702,
    		-55.175,
    		-53.7347,
    		-54.4519,
    		-54.5773,
    		-56.9627,
    		-57.1959,
    		-55.6704,
    		-55.0481,
    		-57.9426,
    		-57.3462,
    		-55.6331,
    		-55.629,
    		-55.3975,
    		-56.4719,
    		-58.1078,
    		-56.1705,
    		-54.758,
    		-58.8711,
    		-57.9153,
    		-56.4004,
    		-55.1685,
    		-55.7985,
    		-54.3574,
    		-55.6311,
    		-55.4626,
    		-56.6099,
    		-55.4795,
    		-54.0479,
    		-56.069,
    		-56.2238,
    		-56.643,
    		-57.3297,
    		-57.2569,
    		-55.3871,
    		-55.8629,
    		-55.827,
    		-55.3129,
    		-56.7753,
    		-54.7421,
    		-53.2383,
    		-53.1972,
    		-54.2125,
    		-55.1294,
    		-55.3516,
    		-54.4107,
    		-56.1692,
    		-55.6607,
    		-54.1289,
    		-56.2226,
    		-54.9853,
    		-54.5406,
    		-55.8668,
    		-54.4344,
    		-51.34,
    		-53.4457,
    		-55.3933,
    		-56.4022,
    		-57.494,
    		-57.042,
    		-53.8239,
    		-54.7248,
    		-55.1078,
    		-54.9422,
    		-57.6964,
    		-57.2593,
    		-54.7605,
    		-56.342,
    		-57.4363,
    		-53.8504,
    		-52.5132,
    		-54.1004,
    		-55.4099,
    		-55.062,
    		-54.2594,
    		-52.8564,
    		-52.14,
    		-51.7081,
    		-52.2992,
    		-52.3724,
    		-51.8007,
    		-55.592,
    		-55.7873,
    		-53.5016,
    		-54.1608,
    		-53.7607,
    		-52.8233,
    		-54.0887,
    		-54.6511,
    		-54.4701,
    		-54.7901,
    		-56.7217,
    		-55.1668,
    		-54.6029,
    		-55.2335,
    		-53.67,
    		-53.9694,
    		-56.1003,
    		-55.6258,
    		-55.8682,
    		-54.7942,
    		-54.6461,
    		-56.4503,
    		-57.3815,
    		-55.4552,
    		-56.4655,
    		-55.3854,
    		-54.1829,
    		-53.3174,
    		-54.3715,
    		-53.5423,
    		-54.4937,
    		-56.8845,
    		-54.4562,
    		-53.0783,
    		-54.8609,
    		-52.7257,
    		-53.1482,
    		-55.1311,
    		-54.7786,
    		-54.3794,
    		-55.2594,
    		-52.3897,
    		-50.3529,
    		-50.6989,
    		-50.8013,
    		-50.2843,
    		-51.4467,
    		-52.3954,
    		-51.4057,
    		-51.6931,
    		-53.6986,
    		-52.1103,
    		-49.9167,
    		-51.4783,
    		-53.218,
    		-53.8505,
    		-52.805,
    		-51.589,
    		-51.8991,
    		-53.1859,
    		-50.7663,
    		-51.6103,
    		-52.6432,
    		-50.0238,
    		-52.5902,
    		-54.4426,
    		-51.1014,
    		-51.337,
    		-52.8024,
    		-53.7283,
    		-53.3006,
    		-54.6558,
    		-56.1147,
    		-53.3179,
    		-52.8044,
    		-52.334,
    		-51.9468,
    		-51.2366,
    		-56.9915,
    		-54.5127,
    		-53.0841,
    		-54.4758,
    		-53.2447,
    		-54.7147,
    		-54.3793,
    		-52.4646,
    		-52.7251,
    		-53.2872,
    		-51.1914,
    		-52.1654,
    		-53.3249,
    		-52.2418,
    		-50.3992,
    		-51.7577,
    		-50.617,
    		-50.6632,
    		-54.7326,
    		-52.635,
    		-51.3294,
    		-54.1903,
    		-53.3178,
    		-51.235,
    		-53.1232,
    		-52.5514,
    		-51.5221,
    		-49.9557,
    		-52.2744,
    		-53.2325,
    		-51.3947,
    		-51.9394,
    		-52.0155,
    		-51.9813,
    		-52.9384,
    		-51.6752,
    		-51.4657,
    		-53.9598,
    		-56.0678,
    		-55.6356,
    		-54.9773,
    		-52.1095,
    		-49.7851,
    		-51.2385,
    		-52.6269,
    		-53.3314,
    		-55.0205,
    		-55.7239,
    		-53.4701,
    		-52.5249,
    		-53.1064,
    		-55.33,
    		-53.1046,
    		-52.853,
    		-53.7369,
    		-54.7797,
    		-54.5858,
    		-54.2175,
    		-53.2216,
    		-50.8936,
    		-36.8913,
    		-35.1439,
    		-37.0516,
    		-50.6355,
    		-52.1987,
    		-53.0451,
    		-53.1897,
    		-52.8646,
    		-52.6694,
    		-52.9763,
    		-53.23,
    		-54.3301,
    		-55.2726,
    		-54.0729,
    		-51.3799,
    		-50.7924,
    		-51.3911,
    		-51.1238,
    		-50.1222,
    		-51.9869,
    		-51.6642,
    		-50.5145,
    		-50.098,
    		-49.673,
    		-51.0346,
    		-48.4426,
    		-46.532,
    		-49.659,
    		-49.8172,
    		-47.0652,
    		-48.479,
    		-50.3125,
    		-50.6249,
    		-52.0916,
    		-49.325,
    		-46.4799,
    		-48.3024,
    		-51.8701,
    		-48.8237,
    		-50.4471,
    		-50.5064,
    		-49.4765,
    		-51.0378,
    		-49.8951,
    		-50.867,
    		-51.7528,
    		-49.7907,
    		-50.9414,
    		-50.196,
    		-50.7166,
    		-48.2638,
    		-48.1027,
    		-49.4721,
    		-51.5115,
    		-49.6891,
    		-49.1679,
    		-50.4271,
    		-50.3478,
    		-50.5238,
    		-49.163,
    		-48.1769,
    		-48.8715,
    		-51.5548,
    		-48.3888,
    		-47.5323,
    		-50.1061,
    		-49.1536,
    		-49.2668,
    		-49.7307,
    		-51.1017,
    		-54.1429,
    		-50.4325,
    		-49.1318,
    		-48.6643,
    		-50.4365,
    		-49.6167,
    		-48.396,
    		-49.2512,
    		-50.9879,
    		-49.5467,
    		-50.9555,
    		-53.2533,
    		-50.8848,
    		-50.4579,
    		-50.1226,
    		-49.8508,
    		-49.3174,
    		-50.3957,
    		-47.6939,
    		-47.1738,
    		-49.8836,
    		-49.2091,
    		-49.4535,
    		-53.6354,
    		-52.5986,
    		-51.6961,
    		-52.7263,
    		-48.666,
    		-49.2609,
    		-52.923,
    		-52.6971,
    		-51.1352,
    		-50.2645,
    		-48.4548,
    		-48.1124,
    		-47.8769,
    		-48.4172,
    		-46.8714,
    		-48.2583,
    		-50.2179,
    		-48.3703,
    		-49.6104,
    		-49.8433,
    		-46.8929,
    		-47.5154,
    		-50.6053,
    		-51.3085,
    		-51.9856,
    		-50.2469,
    		-47.5982,
    		-49.3081,
    		-51.3249,
    		-48.7754,
    		-49.3255,
    		-50.9454,
    		-49.4825,
    		-50.0666,
    		-49.8912,
    		-48.8952,
    		-48.1874,
    		-49.0473,
    		-48.5272,
    		-47.6251,
    		-50.1978,
    		-51.7487,
    		-48.6737,
    		-49.9187,
    		-50.7832,
    		-48.591,
    		-47.5307,
    		-53.948,
    		-49.7888,
    		-47.7759,
    		-49.4646,
    		-49.2951,
    		-48.0835,
    		-50.9995,
    		-47.7416,
    		-47.4029,
    		-51.7832,
    		-47.9682,
    		-46.4668,
    		-49.6323,
    		-50.7472,
    		-48.5351,
    		-48.8773,
    		-49.049,
    		-48.3435,
    		-50.9687,
    		-49.1747,
    		-46.6598,
    		-48.7942,
    		-49.6085,
    		-47.7136,
    		-46.3717,
    		-47.9584,
    		-48.8272,
    		-47.049,
    		-48.0484,
    		-48.5147,
    		-47.7235,
    		-48.9985,
    		-48.3041,
    		-48.7325,
    		-52.1014,
    		-48.6559,
    		-45.9734,
    		-47.9816,
    		-49.9001,
    		-49.744,
    		-49.0705,
    		-49.5089,
    		-50.6053,
    		-51.4918,
    		-50.2007,
    		-49.1247,
    		-50.8951,
    		-53.99,
    		-50.9961,
    		-51.2368,
    		-54.649,
    		-50.5483,
    		-49.6662,
    		-49.7394,
    		-48.4737,
    		-50.7644,
    		-52.0322,
    		-51.6659,
    		-48.8891,
    		-50.7512,
    		-51.6192,
    		-49.0519,
    		-48.6193,
    		-49.1657,
    		-49.9413,
    		-50.675,
    		-50.7688,
    		-47.5235,
    		-48.7736,
    		-51.2266,
    		-50.0237,
    		-48.7437,
    		-51.924,
    		-52.801,
    		-49.2737,
    		-46.3321,
    		-48.3736,
    		-48.1676,
    		-46.3604,
    		-48.1548,
    		-51.7357,
    		-48.9502,
    		-48.1962,
    		-48.5177,
    		-49.363,
    		-48.0272,
    		-45.426,
    		-48.0143,
    		-48.0975,
    		-45.1166,
    		-46.3444,
    		-48.1079,
    		-47.5219,
    		-47.5311,
    		-47.5127,
    		-45.4789,
    		-47.1243,
    		-48.7736,
    		-46.554,
    		-48.3435,
    		-50.5012,
    		-46.9389,
    		-47.8544,
    		-48.8036,
    		-50.0142,
    		-50.8305,
    		-51.3919,
    		-50.5138,
    		-47.5832,
    		-47.4375,
    		-47.9406,
    		-48.4136,
    		-47.9574,
    		-46.4125,
    		-46.3805,
    		-49.6796,
    		-48.7645,
    		-46.8555,
    		-48.4917,
    		-48.5139,
    		-45.8423,
    		-47.3436,
    		-49.4883,
    		-47.0694,
    		-46.6695,
    		-48.0118,
    		-47.1591,
    		-49.1952,
    		-50.3417,
    		-48.5627,
    		-47.191,
    		-48.3246,
    		-48.2971,
    		-47.0113,
    		-48.5018,
    		-49.5539,
    		-48.1113,
    		-48.9499,
    		-48.0196,
    		-44.7132,
    		-46.8052,
    		-49.3817,
    		-48.9602,
    		-51.7208,
    		-47.954,
    		-45.4842,
    		-49.5872,
    		-47.2174,
    		-44.829,
    		-46.5841,
    		-48.7515,
    		-47.0837,
    		-47.6698,
    		-49.6554,
    		-49.0501,
    		-48.0787,
    		-47.2196,
    		-48.6574,
    		-46.4617,
    		-47.7125,
    		-47.2467,
    		-49.2226,
    		-50.1231,
    		-47.5745,
    		-45.2543,
    		-46.22,
    		-46.6847,
    		-45.2459,
    		-45.3651,
    		-48.327,
    		-45.4815,
    		-45.0398,
    		-45.7934,
    		-45.2835,
    		-44.7138,
    		-45.9321,
    		-45.2813,
    		-47.0122,
    		-46.104,
    		-45.367,
    		-45.9876,
    		-47.9313,
    		-48.014,
    		-45.8913,
    		-45.8209,
    		-44.539,
    		-43.8343,
    		-47.3054,
    		-48.6662,
    		-47.7547,
    		-46.8956,
    		-48.9327,
    		-47.4592,
    		-48.1918,
    		-47.9374,
    		-45.3557,
    		-45.4929,
    		-45.3678,
    		-43.5012,
    		-43.1875,
    		-45.2978,
    		-46.5465,
    		-49.1348,
    		-49.1225,
    		-46.0337,
    		-46.0285,
    		-47.0877,
    		-44.4196,
    		-44.1308,
    		-46.6495,
    		-45.2522,
    		-44.6563,
    		-45.8002,
    		-44.6618,
    		-44.5779,
    		-44.4855,
    		-44.2913,
    		-43.1099,
    		-43.9997,
    		-45.2453,
    		-45.0873,
    		-46.2542,
    		-47.2774,
    		-45.2886,
    		-44.5012,
    		-45.9774,
    		-44.1381,
    		-45.4811,
    		-48.5527,
    		-47.2975,
    		-44.8606,
    		-46.5022,
    		-46.7482,
    		-46.028,
    		-48.0085,
    		-47.6895,
    		-45.0938,
    		-46.893,
    		-47.9799,
    		-46.101,
    		-46.2139,
    		-48.2228,
    		-47.5895,
    		-45.3641,
    		-45.9702,
    		-45.4339,
    		-47.2054,
    		-50.1577,
    		-47.9846,
    		-48.8655,
    		-48.461,
    		-48.6598,
    		-48.6151,
    		-49.7885,
    		-47.47,
    		-49.6225,
    		-47.6268,
    		-47.3095,
    		-48.6953,
    		-47.3902,
    		-47.3501,
    		-46.8645,
    		-49.2446,
    		-46.3305,
    		-44.4973,
    		-46.9743,
    		-48.1871,
    		-48.1099,
    		-46.9727,
    		-45.9809,
    		-47.0705,
    		-48.4405,
    		-45.9353,
    		-45.4907,
    		-46.1851,
    		-44.4699,
    		-47.7013,
    		-46.1764,
    		-46.9609,
    		-46.7163,
    		-45.2347,
    		-45.2775,
    		-45.7384,
    		-45.4096,
    		-46.1625,
    		-43.9906,
    		-42.2237,
    		-43.7476,
    		-44.4925,
    		-42.0441,
    		-43.5432,
    		-44.4195,
    		-44.1445,
    		-45.2037,
    		-43.0051,
    		-41.7508,
    		-43.4584,
    		-45.7652,
    		-43.0487,
    		-44.2161,
    		-45.7777,
    		-44.9954,
    		-45.5829,
    		-45.2463,
    		-46.069,
    		-46.7692,
    		-44.4243,
    		-45.4386,
    		-45.8462,
    		-45.5292,
    		-42.6122,
    		-42.72,
    		-45.0977,
    		-47.1575,
    		-41.8999,
    		-42.8585,
    		-44.6372,
    		-45.2421,
    		-45.8997,
    		-43.8037,
    		-43.0463,
    		-43.7606,
    		-49.1001,
    		-43.6061,
    		-42.4586,
    		-43.3683,
    		-43.391,
    		-44.8932,
    		-46.0093,
    		-46.4953,
    		-46.0914,
    		-45.0499,
    		-44.6887,
    		-44.5065,
    		-44.6259,
    		-43.2564,
    		-41.6824,
    		-44.2345,
    		-46.3672,
    		-44.4248,
    		-44.7575,
    		-45.4479,
    		-46.4974,
    		-46.4438,
    		-48.1768,
    		-47.8746,
    		-48.1585,
    		-46.0249,
    		-44.2233,
    		-45.0271,
    		-47.7074,
    		-45.1241,
    		-45.602,
    		-48.034,
    		-45.7877,
    		-45.7414,
    		-48.8029,
    		-46.1515,
    		-44.7503,
    		-46.0245,
    		-48.1391,
    		-42.7574,
    		-45.0704,
    		-44.4313,
    		-42.3392,
    		-42.7127,
    		-42.63,
    		-42.1699,
    		-43.1941,
    		-44.8777,
    		-43.7871,
    		-44.7024,
    		-43.1134,
    		-41.052,
    		-41.5106,
    		-42.7823,
    		-43.9133,
    		-46.6444,
    		-44.1329,
    		-42.4254,
    		-41.9902,
    		-43.1927,
    		-42.4992,
    		-43.2412,
    		-45.32,
    		-43.1171,
    		-41.8517,
    		-45.7062,
    		-44.5682,
    		-43.9681,
    		-42.4479,
    		-42.7704,
    		-45.2259,
    		-46.2546,
    		-43.2546,
    		-42.3056,
    		-42.9318,
    		-41.2086,
    		-40.1974,
    		-38.86,
    		-41.7293,
    		-45.3347,
    		-43.45,
    		-43.1411,
    		-42.5701,
    		-42.2307,
    		-42.1508,
    		-40.1295,
    		-39.5435,
    		-44.5262,
    		-44.3852,
    		-41.6828,
    		-42.4575,
    		-41.5466,
    		-41.2296,
    		-40.6723,
    		-40.7443,
    		-41.0065,
    		-44.0477,
    		-44.4363,
    		-41.7784,
    		-43.8286,
    		-44.3334,
    		-40.4965,
    		-40.7184,
    		-42.1522,
    		-40.372,
    		-40.0213,
    		-42.1974,
    		-43.9423,
    		-41.4528,
    		-41.3604,
    		-40.0896,
    		-40.5994,
    		-43.1084,
    		-44.5182,
    		-40.5199,
    		-43.2448,
    		-43.9948,
    		-42.4505,
    		-43.8804,
    		-41.658,
    		-41.7391,
    		-43.9621,
    		-42.5052,
    		-41.941,
    		-43.953,
    		-44.4372,
    		-42.9089,
    		-41.4266,
    		-44.5048,
    		-44.0139,
    		-43.1635,
    		-42.9775,
    		-42.5989,
    		-44.2387,
    		-43.6555,
    		-42.2137,
    		-40.8761,
    		-41.2583,
    		-41.6775,
    		-39.2895,
    		-38.7132,
    		-39.5674,
    		-41.6928,
    		-38.4184,
    		-36.5258,
    		-36.6337,
    		-36.45,
    		-35.4038,
    		-34.3154,
    		-33.8786,
    		-34.3,
    		-32.2024,
    		-31.6128,
    		-29.9677,
    		-28.604,
    		-26.7203,
    		-21.491,
    		-20.0435,
    		-20.0388,
    		-19.4482,
    		-19.675,
    		-15.5392,
    		-15.7468,
    		-15.7612,
    		-14.1639,
    		-17.6221,
    		-20.3647,
    		-15.2342,
    		-14.4646,
    		-15.9993,
    		-16.7893,
    		-20.0614,
    		-18.6413,
    		-15.156,
    		-15.7714,
    		-18.9955,
    		-11.9265,
    		-13.1928,
    		-17.4033,
    		-15.9239,
    		-15.6211,
    		-15.1626,
    		-17.2121,
    		-15.1454,
    		-14.846,
    		-17.4043,
    		-14.9008,
    		-17.8761,
    		-13.6937,
    		-12.7696,
    		-16.4788,
    		-17.8299,
    		-14.1835,
    		-15.9506,
    		-15.5977,
    		-16.4307,
    		-16.6612,
    		-17.2893,
    		-17.1491,
    		-15.2785,
    		-14.299,
    		-11.5101,
    		-12.0057,
    		-14.3695,
    		-12.3953,
    		-14.5376,
    		-18.6463,
    		-17.6179,
    		-17.2854,
    		-14.838,
    		-15.901,
    		-15.4921,
    		-16.3385,
    		-14.7699,
    		-11.5637,
    		-13.0916,
    		-16.2336,
    		-16.4366,
    		-15.3438,
    		-16.4631,
    		-16.434,
    		-15.4712,
    		-14.356,
    		-16.113,
    		-16.3932,
    		-14.813,
    		-10.4706,
    		-14.0698,
    		-18.1615,
    		-16.0609,
    		-15.0685,
    		-18.28,
    		-15.6291,
    		-15.2425,
    		-18.0123,
    		-16.8178,
    		-13.9477,
    		-18.1202,
    		-20.0955,
    		-18.5818,
    		-18.6161,
    		-17.0272,
    		-15.1053,
    		-14.8645,
    		-14.2902,
    		-14.2992,
    		-18.4018,
    		-18.3067,
    		-14.4854,
    		-17.361,
    		-16.466,
    		-12.033,
    		-12.1618,
    		-18.0388,
    		-14.6222,
    		-14.4357,
    		-16.3651,
    		-14.5199,
    		-16.5932,
    		-18.0895,
    		-18.2942,
    		-14.4461,
    		-14.9826,
    		-13.7885,
    		-11.4138,
    		-14.7876,
    		-17.2821,
    		-15.1468,
    		-14.2192,
    		-14.4969,
    		-14.6106,
    		-19.7936,
    		-18.5169,
    		-15.4286,
    		-17.5611,
    		-17.1634,
    		-13.5942,
    		-13.6943,
    		-16.9909,
    		-16.9429,
    		-16.4109,
    		-18.8415,
    		-16.5409,
    		-15.0603,
    		-15.8583,
    		-15.0508,
    		-14.7035,
    		-20.1458,
    		-14.2932,
    		-11.0877,
    		-14.5908,
    		-18.6891,
    		-16.1547,
    		-15.6604,
    		-17.4981,
    		-15.1965,
    		-16.2621,
    		-15.3162,
    		-15.8825,
    		-18.2088,
    		-17.8679,
    		-12.9174,
    		-13.0332,
    		-14.5191,
    		-15.1663,
    		-17.884,
    		-19.5843,
    		-16.3794,
    		-15.5378,
    		-15.8095,
    		-16.8979,
    		-16.1351,
    		-16.554,
    		-14.7715,
    		-11.7863,
    		-15.7083,
    		-16.0304,
    		-16.8404,
    		-19.9122,
    		-15.3532,
    		-17.1025,
    		-16.169,
    		-18.5948,
    		-18.5845,
    		-17.9948,
    		-20.0339,
    		-16.0732,
    		-15.9746,
    		-18.4749,
    		-17.5057,
    		-15.7567,
    		-18.9827,
    		-18.5605,
    		-19.4898,
    		-19.8482,
    		-19.9323,
    		-19.4093,
    		-20.9551,
    		-19.3766,
    		-18.472,
    		-16.8604,
    		-15.9094,
    		-16.6785,
    		-18.2195,
    		-20.4397,
    		-17.7038,
    		-16.4312,
    		-20.627,
    		-20.5637,
    		-17.8994,
    		-19.3752,
    		-15.7811,
    		-15.8661,
    		-21.2333,
    		-17.3369,
    		-17.6729,
    		-17.944,
    		-16.6844,
    		-15.3104,
    		-18.4577,
    		-17.4173,
    		-14.2345,
    		-16.6316,
    		-15.1417,
    		-12.4047,
    		-16.2736,
    		-18.1997,
    		-13.7877,
    		-14.0002,
    		-15.3601,
    		-15.24,
    		-16.6319,
    		-17.412,
    		-15.6287,
    		-16.9564,
    		-18.5734,
    		-12.4446,
    		-13.2975,
    		-16.535,
    		-16.7369,
    		-16.7826,
    		-16.7616,
    		-17.2345,
    		-15.6208,
    		-15.6083,
    		-14.7413,
    		-15.5053,
    		-19.3031,
    		-14.9355,
    		-12.4761,
    		-16.9753,
    		-19.1808,
    		-14.589,
    		-15.7518,
    		-17.9452,
    		-17.4412,
    		-18.4867,
    		-19.3394,
    		-15.8374,
    		-15.3029,
    		-16.1687,
    		-13.7927,
    		-12.9113,
    		-14.1068,
    		-14.4755,
    		-16.5459,
    		-20.7771,
    		-18.5065,
    		-16.205,
    		-14.6572,
    		-14.6384,
    		-15.8938,
    		-17.6287,
    		-14.2392,
    		-12.21,
    		-14.5071,
    		-18.1666,
    		-16.0671,
    		-14.9861,
    		-16.4561,
    		-18.072,
    		-15.2579,
    		-13.6526,
    		-14.9221,
    		-15.7395,
    		-13.5946,
    		-10.9806,
    		-14.4211,
    		-17.8838,
    		-15.2315,
    		-16.0815,
    		-17.462,
    		-16.6821,
    		-15.6187,
    		-19.4224,
    		-14.3781,
    		-13.0367,
    		-18.8141,
    		-19.094,
    		-17.2449,
    		-19.502,
    		-18.4997,
    		-16.9683,
    		-18.2979,
    		-16.559,
    		-14.2958,
    		-17.2245,
    		-16.5611,
    		-15.965,
    		-16.2773,
    		-16.0848,
    		-13.4482,
    		-13.628,
    		-17.3424,
    		-15.2759,
    		-15.4864,
    		-15.5957,
    		-15.4528,
    		-17.081,
    		-18.0077,
    		-16.725,
    		-16.0681,
    		-16.6705,
    		-14.7472,
    		-11.1078,
    		-15.5698,
    		-18.9295,
    		-14.5944,
    		-15.3533,
    		-14.4935,
    		-14.1263,
    		-18.3201,
    		-16.4641,
    		-14.0456,
    		-16.3689,
    		-15.9044,
    		-13.9083,
    		-15.1376,
    		-18.0881,
    		-15.4433,
    		-18.0392,
    		-19.8115,
    		-17.2612,
    		-16.1393,
    		-14.6346,
    		-12.639,
    		-13.3451,
    		-20.3823,
    		-15.5033,
    		-11.6252,
    		-17.2243,
    		-19.6212,
    		-15.889,
    		-16.2187,
    		-17.2933,
    		-15.3106,
    		-15.2818,
    		-15.3002,
    		-15.3482,
    		-16.0188,
    		-15.113,
    		-13.0713,
    		-12.5087,
    		-15.7176,
    		-17.3474,
    		-16.7773,
    		-19.4358,
    		-16.6256,
    		-15.8939,
    		-17.3975,
    		-16.3073,
    		-15.8907,
    		-17.3589,
    		-15.003,
    		-11.9169,
    		-16.0895,
    		-14.965,
    		-15.6599,
    		-18.6817,
    		-17.8752,
    		-18.2858,
    		-17.1836,
    		-18.8071,
    		-17.1642,
    		-16.1271,
    		-16.7472,
    		-19.1897,
    		-18.4565,
    		-20.2236,
    		-18.0552,
    		-18.4603,
    		-20.0452,
    		-18.7502,
    		-17.8809,
    		-22.238,
    		-29.1337,
    		-30.655,
    		-30.9884,
    		-31.0855,
    		-26.6656,
    		-30.7148,
    		-31.103,
    		-29.2949,
    		-26.9712,
    		-21.8321,
    		-17.1371,
    		-19.202,
    		-20.7523,
    		-18.956,
    		-18.5722,
    		-22.2649,
    		-17.2581,
    		-17.3095,
    		-17.8291,
    		-16.7546,
    		-18.3583,
    		-19.4196,
    		-17.1012,
    		-19.0665,
    		-19.6574,
    		-18.7763,
    		-15.6548,
    		-17.41,
    		-14.4814,
    		-12.649,
    		-16.4868,
    		-19.6048,
    		-15.9429,
    		-14.6092,
    		-16.2591,
    		-16.6707,
    		-16.7363,
    		-17.5889,
    		-15.5971,
    		-17.7072,
    		-16.9493,
    		-12.379,
    		-14.5237,
    		-17.3588,
    		-18.0528,
    		-18.7503,
    		-17.4407,
    		-17.773,
    		-16.1955,
    		-16.316,
    		-17.5686,
    		-16.1528,
    		-17.5352,
    		-15.1959,
    		-12.5491,
    		-16.2168,
    		-17.951,
    		-16.2831,
    		-16.8028,
    		-21.7191,
    		-17.5696,
    		-18.5079,
    		-17.8364,
    		-16.8529,
    		-17.3568,
    		-16.4887,
    		-14.5074,
    		-13.6032,
    		-15.0561,
    		-14.8592,
    		-17.1061,
    		-18.2881,
    		-17.3267,
    		-17.4816,
    		-15.2771,
    		-15.9633,
    		-17.1671,
    		-16.8132,
    		-15.4977,
    		-13.4716,
    		-14.6176,
    		-15.4932,
    		-15.5906,
    		-16.0732,
    		-16.6312,
    		-19.8594,
    		-17.7166,
    		-14.7387,
    		-16.1423,
    		-17.7272,
    		-16.0497,
    		-12.0825,
    		-14.8194,
    		-18.6578,
    		-16.2647,
    		-16.952,
    		-21.209,
    		-17.2636,
    		-15.4765,
    		-21.519,
    		-18.9253,
    		-15.6929,
    		-18.4423,
    		-22.0175,
    		-20.0796,
    		-19.7565,
    		-18.4389,
    		-17.4147,
    		-16.1838,
    		-15.7579,
    		-15.7313,
    		-17.9307,
    		-17.6456,
    		-15.472,
    		-16.2165,
    		-18.3629,
    		-13.9219,
    		-13.3908,
    		-18.0883,
    		-15.8902,
    		-15.8117,
    		-17.6531,
    		-15.399,
    		-17.1985,
    		-20.5278,
    		-18.2017,
    		-16.0071,
    		-16.6188,
    		-15.3262,
    		-12.4708,
    		-16.0418,
    		-18.4806,
    		-15.2803,
    		-14.1438,
    		-15.4045,
    		-17.4351,
    		-21.2766,
    		-18.956,
    		-14.8291,
    		-15.6915,
    		-17.9646,
    		-13.796,
    		-14.2603,
    		-17.9241,
    		-17.1372,
    		-20.2816,
    		-18.5349,
    		-16.7273,
    		-15.9286,
    		-17.0292,
    		-15.6254,
    		-16.2442,
    		-21.4171,
    		-15.2941,
    		-11.6143,
    		-16.4831,
    		-19.1565,
    		-17.3051,
    		-16.2204,
    		-16.7853,
    		-14.3267,
    		-16.5206,
    		-17.4987,
    		-15.8609,
    		-16.1717,
    		-18.7535,
    		-13.7566,
    		-13.515,
    		-16.0579,
    		-16.2419,
    		-17.9404,
    		-20.2519,
    		-18.8312,
    		-16.4888,
    		-16.1905,
    		-18.4802,
    		-15.4975,
    		-16.8566,
    		-15.1004,
    		-12.0728,
    		-16.1559,
    		-16.5879,
    		-17.5269,
    		-17.6385,
    		-17.0088,
    		-18.2969,
    		-17.6654,
    		-18.2338,
    		-18.5142,
    		-18.5781,
    		-23.0018,
    		-18.7451,
    		-18.7929,
    		-20.3262,
    		-18.2918,
    		-20.992,
    		-20.8563,
    		-21.0641,
    		-19.8925,
    		-20.8524,
    		-19.6837,
    		-20.3027,
    		-20.8755,
    		-18.7651,
    		-19.745,
    		-19.0357,
    		-22.9735,
    		-19.6601,
    		-17.5248,
    		-22.4799,
    		-22.2368,
    		-20.741,
    		-21.4475,
    		-19.1367,
    		-20.0864,
    		-20.6374,
    		-17.0022,
    		-17.0454,
    		-20.2269,
    		-20.2276,
    		-18.1309,
    		-18.3089,
    		-19.0382,
    		-17.7965,
    		-17.7277,
    		-19.0534,
    		-16.6147,
    		-16.9542,
    		-15.08,
    		-13.8843,
    		-18.0411,
    		-20.2552,
    		-17.1335,
    		-15.8885,
    		-16.4164,
    		-19.8657,
    		-21.2539,
    		-21.6384,
    		-17.9591,
    		-16.4973,
    		-19.4645,
    		-13.7794,
    		-14.5086,
    		-17.499,
    		-18.7878,
    		-22.569,
    		-18.4554,
    		-19.112,
    		-17.7439,
    		-16.5406,
    		-19.7502,
    		-17.2812,
    		-19.5686,
    		-16.5935,
    		-14.6281,
    		-16.7502,
    		-19.8096,
    		-16.3894,
    		-17.3978,
    		-17.9746,
    		-16.3131,
    		-16.844,
    		-18.1621,
    		-16.3371,
    		-16.2464,
    		-18.0401,
    		-14.3329,
    		-13.5673,
    		-16.2798,
    		-15.4207,
    		-17.4112,
    		-20.4657,
    		-19.6506,
    		-18.5436,
    		-18.5071,
    		-18.5784,
    		-18.1828,
    		-18.302,
    		-15.7905,
    		-14.5212,
    		-15.8785,
    		-17.87,
    		-17.5357,
    		-17.2979,
    		-19.5085,
    		-15.4981,
    		-16.5418,
    		-16.4873,
    		-16.6953,
    		-18.9113,
    		-17.337,
    		-12.8396,
    		-15.5374,
    		-18.1843,
    		-18.6142,
    		-17.9819,
    		-20.3665,
    		-18.874,
    		-17.8146,
    		-21.8009,
    		-19.4206,
    		-15.1749,
    		-16.941,
    		-21.3388,
    		-19.2361,
    		-18.5137,
    		-19.5836,
    		-17.8294,
    		-18.0813,
    		-16.2072,
    		-15.2342,
    		-17.3446,
    		-17.9416,
    		-17.0639,
    		-19.0464,
    		-18.1247,
    		-14.0078,
    		-14.1669,
    		-17.2219,
    		-16.7482,
    		-15.523,
    		-17.009,
    		-17.2274,
    		-17.2415,
    		-20.7098,
    		-22.7188,
    		-15.6795,
    		-16.1834,
    		-15.076,
    		-12.8413,
    		-17.1034,
    		-21.6745,
    		-16.3876,
    		-15.0064,
    		-15.6645,
    		-15.5831,
    		-19.8088,
    		-18.1582,
    		-15.6864,
    		-16.8537,
    		-16.605,
    		-14.3675,
    		-14.9494,
    		-18.2275,
    		-17.9394,
    		-17.9904,
    		-21.1667,
    		-18.6842,
    		-17.2572,
    		-16.2678,
    		-15.2376,
    		-15.7674,
    		-20.0147,
    		-15.5518,
    		-12.6766,
    		-16.4039,
    		-15.9753,
    		-16.8163,
    		-16.7973,
    		-17.6159,
    		-17.4915,
    		-17.6545,
    		-17.1689,
    		-16.1077,
    		-18.1998,
    		-18.469,
    		-13.9715,
    		-13.9777,
    		-16.6906,
    		-16.3311,
    		-17.1617,
    		-19.8228,
    		-17.2765,
    		-18.7073,
    		-20.429,
    		-19.0216,
    		-16.8083,
    		-20.0403,
    		-18.0369,
    		-14.1958,
    		-18.8201,
    		-19.6189,
    		-18.9291,
    		-21.8515,
    		-21.4555,
    		-19.4145,
    		-21.1048,
    		-24.6117,
    		-30.1201,
    		-30.2087,
    		-32.4339,
    		-34.0687,
    		-34.3296,
    		-35.9902,
    		-35.9791,
    		-36.9887,
    		-38.0751,
    		-37.0478,
    		-38.1653,
    		-39.9887,
    		-41.1763,
    		-40.8435,
    		-40.5692,
    		-42.2582,
    		-43.4551,
    		-43.1281,
    		-41.4753,
    		-41.3605,
    		-44.7594,
    		-48.0518,
    		-45.8695,
    		-44.5699,
    		-44.9164,
    		-46.7043,
    		-46.9795,
    		-45.987,
    		-46.8277,
    		-46.9546,
    		-48.517,
    		-48.9181,
    		-48.5357,
    		-47.1731,
    		-46.1186,
    		-46.5777,
    		-49.208,
    		-50.2139,
    		-47.5279,
    		-47.6892,
    		-45.6928,
    		-42.3576,
    		-45.6602,
    		-50.0009,
    		-44.0409,
    		-44.8954,
    		-46.0335,
    		-46.3665,
    		-47.0359,
    		-46.5136,
    		-43.8663,
    		-45.1994,
    		-48.9513,
    		-43.6399,
    		-44.5852,
    		-48.9535,
    		-48.7395,
    		-50.6469,
    		-47.9366,
    		-50.2694,
    		-53.1197,
    		-51.219,
    		-48.9197,
    		-49.6145,
    		-49.3445,
    		-46.2711,
    		-46.8294,
    		-48.7328,
    		-48.689,
    		-46.8953,
    		-46.455,
    		-47.4365,
    		-49.5511,
    		-47.2848,
    		-48.2091,
    		-48.48,
    		-49.6225,
    		-49.5303,
    		-45.9227,
    		-45.6378,
    		-47.6079,
    		-48.3332,
    		-51.1252,
    		-50.0722,
    		-47.7211,
    		-46.3724,
    		-47.9191,
    		-46.9733,
    		-46.4178,
    		-47.9862,
    		-48.7368,
    		-47.3079,
    		-48.573,
    		-47.8612,
    		-47.7978,
    		-47.9014,
    		-47.465,
    		-48.1392,
    		-51.7731,
    		-50.9328,
    		-48.3029,
    		-48.4842,
    		-51.4898,
    		-48.723,
    		-48.3427,
    		-50.284,
    		-50.1632,
    		-49.0694,
    		-49.4466,
    		-49.4901,
    		-51.7125,
    		-51.408,
    		-49.0947,
    		-46.7358,
    		-48.8949,
    		-50.5354,
    		-51.6669,
    		-48.0811,
    		-46.9125,
    		-47.2465,
    		-48.6119,
    		-48.0179,
    		-47.1497,
    		-49.5535,
    		-49.6195,
    		-51.0516,
    		-50.4786,
    		-49.7187,
    		-47.9761,
    		-49.0253,
    		-50.6974,
    		-49.7176,
    		-48.4694,
    		-49.1365,
    		-48.0496,
    		-48.3849,
    		-49.6228,
    		-48.9914,
    		-46.2694,
    		-47.6119,
    		-49.1836,
    		-50.8548,
    		-50.1212,
    		-49.1347,
    		-47.36,
    		-49.579,
    		-47.6367,
    		-48.0236,
    		-50.94,
    		-51.1781,
    		-50.3151,
    		-47.9266,
    		-49.14,
    		-48.8484,
    		-47.8906,
    		-51.3558,
    		-51.0253,
    		-51.8225,
    		-52.3138,
    		-50.3064,
    		-50.2402,
    		-50.6688,
    		-47.7897,
    		-48.0829,
    		-50.0277,
    		-49.8401,
    		-46.2139,
    		-48.474,
    		-48.5406,
    		-46.5788,
    		-46.0183,
    		-48.064,
    		-47.0858,
    		-48.4572,
    		-51.3744,
    		-49.071,
    		-48.7529,
    		-49.3962,
    		-47.3005,
    		-47.7479,
    		-49.1209,
    		-45.7782,
    		-46.6839,
    		-49.1914,
    		-48.0888,
    		-48.3552,
    		-48.7767,
    		-50.5968,
    		-50.9137,
    		-49.9867,
    		-47.3503,
    		-46.2074,
    		-50.2556,
    		-49.8635,
    		-46.9128,
    		-48.4134,
    		-50.8621,
    		-48.2746,
    		-47.2561,
    		-48.3277,
    		-48.462,
    		-49.5798,
    		-51.1221,
    		-49.8699,
    		-49.8763,
    		-52.7402,
    		-51.8437,
    		-50.9413,
    		-49.4195,
    		-48.6313,
    		-48.7089,
    		-48.26,
    		-49.1006,
    		-51.7097,
    		-51.2647,
    		-50.0222,
    		-46.266,
    		-47.6016,
    		-51.4242,
    		-51.2863,
    		-50.4255,
    		-50.777,
    		-50.6262,
    		-52.4123,
    		-51.1417,
    		-48.6119,
    		-49.1773,
    		-49.7257,
    		-51.0008,
    		-51.1137,
    		-49.4485,
    		-47.3073,
    		-46.4001,
    		-49.1763,
    		-49.6873,
    		-48.8188,
    		-47.7588,
    		-48.8807,
    		-49.5315,
    		-50.5,
    		-49.1801,
    		-46.205,
    		-49.0411,
    		-48.2937,
    		-47.7029,
    		-49.864,
    		-49.8018,
    		-51.6115,
    		-50.3661,
    		-49.6347,
    		-48.2495,
    		-51.1527,
    		-50.0531,
    		-50.046,
    		-51.5537,
    		-52.1198,
    		-52.4282,
    		-51.7337,
    		-50.2507,
    		-50.2803,
    		-49.4137,
    		-49.3984,
    		-50.0768,
    		-48.9663,
    		-49.2549,
    		-49.3198,
    		-48.9314,
    		-51.3619,
    		-50.9843,
    		-49.4912,
    		-50.9405,
    		-48.5417,
    		-46.2278,
    		-48.7857,
    		-49.9857,
    		-48.5979,
    		-49.3343,
    		-49.8103,
    		-51.2711,
    		-50.6175,
    		-52.9629,
    		-46.3871,
    		-47.3597,
    		-50.0049,
    		-51.3863,
    		-50.9092,
    		-49.2139,
    		-49.7167,
    		-48.2345,
    		-49.7085,
    		-47.9198,
    		-47.2056,
    		-48.779,
    		-49.5685,
    		-47.9345,
    		-48.9486,
    		-48.4122,
    		-46.8779,
    		-48.9406,
    		-47.3671,
    		-49.5441,
    		-50.6269,
    		-48.1014,
    		-47.5496,
    		-50.8901,
    		-50.5588,
    		-50.3705,
    		-49.6213,
    		-50.9238,
    		-51.3464,
    		-51.3144,
    		-51.2102,
    		-51.0348,
    		-48.9954,
    		-50.0406,
    		-51.2378,
    		-48.9083,
    		-50.871,
    		-49.1628,
    		-49.3872,
    		-47.8336,
    		-45.5733,
    		-45.3397,
    		-48.3252,
    		-49.8814,
    		-49.5617,
    		-52.5514,
    		-50.8642,
    		-47.4364,
    		-46.9441,
    		-49.2649,
    		-48.6666,
    		-48.7245,
    		-52.2812,
    		-50.4663,
    		-48.9467,
    		-50.4195,
    		-49.3005,
    		-48.0456,
    		-49.7586,
    		-51.4669,
    		-49.4233,
    		-49.3954,
    		-51.918,
    		-52.5363,
    		-53.245,
    		-50.1197,
    		-49.5715,
    		-48.6225,
    		-51.4814,
    		-48.6501,
    		-48.435,
    		-49.0636,
    		-46.99,
    		-47.1601,
    		-51.3511,
    		-51.7712,
    		-50.9188,
    		-49.9227,
    		-47.5559,
    		-47.5108,
    		-47.5403,
    		-48.5864,
    		-48.7457,
    		-52.6943,
    		-47.607,
    		-45.5889,
    		-46.5265,
    		-47.079,
    		-46.4308,
    		-46.6699,
    		-46.537,
    		-46.3403,
    		-50.2296,
    		-49.3748,
    		-48.8292,
    		-48.3511,
    		-49.7581,
    		-48.8874,
    		-49.5481,
    		-51.5764,
    		-53.0174,
    		-51.1775,
    		-49.355,
    		-48.1056,
    		-50.0939,
    		-52.3718,
    		-49.6871,
    		-48.6252,
    		-48.5005,
    		-49.1256,
    		-47.7784,
    		-49.501,
    		-49.6147,
    		-50.4504,
    		-52.848,
    		-52.5858,
    		-51.5435,
    		-50.0252,
    		-50.4699,
    		-49.7307,
    		-50.7538,
    		-52.7033,
    		-51.7882,
    		-52.9639,
    		-53.4579,
    		-50.473,
    		-50.4015,
    		-52.9672,
    		-52.2223,
    		-51.081,
    		-52.4087,
    		-53.6466,
    		-53.7278,
    		-51.9755,
    		-50.2002,
    		-48.3145,
    		-50.6177,
    		-51.2229,
    		-48.8809,
    		-52.0095,
    		-53.5939,
    		-50.5413,
    		-52.9807,
    		-53.6694,
    		-53.6789,
    		-54.1299,
    		-51.5615,
    		-51.0408,
    		-54.0533,
    		-51.3977,
    		-49.306,
    		-51.6357,
    		-53.7669,
    		-55.5275,
    		-54.4678,
    		-51.1255,
    		-50.2686,
    		-48.2089,
    		-50.3321,
    		-48.6478,
    		-47.8024,
    		-51.0462,
    		-51.0639,
    		-49.8515,
    		-52.1705,
    		-50.1129,
    		-49.5335,
    		-51.425,
    		-52.8038,
    		-50.2589,
    		-50.7481,
    		-48.5987,
    		-47.1937,
    		-48.4121,
    		-50.5755,
    		-51.7702,
    		-50.9743,
    		-51.1422,
    		-50.6376,
    		-51.6163,
    		-50.8467,
    		-52.6728,
    		-50.7194,
    		-50.9636,
    		-53.1127,
    		-53.6698,
    		-51.9594,
    		-49.8107,
    		-48.4892,
    		-46.9902,
    		-49.1573,
    		-49.527,
    		-49.2974,
    		-53.1054,
    		-51.2926,
    		-50.9592,
    		-50.8261,
    		-48.1979,
    		-48.3261,
    		-49.4646,
    		-48.531,
    		-49.1327,
    		-50.5197,
    		-50.4211,
    		-52.3129,
    		-52.3579,
    		-49.2716,
    		-47.8853,
    		-48.2628,
    		-46.8968,
    		-47.9587,
    		-50.7874,
    		-50.925,
    		-49.1492,
    		-52.0662,
    		-51.2057,
    		-49.733,
    		-49.6531,
    		-50.086,
    		-51.8516,
    		-52.064,
    		-49.5581,
    		-48.727,
    		-52.7099,
    		-51.1081,
    		-48.84,
    		-51.0247,
    		-54.5521,
    		-55.9998,
    		-51.3357,
    		-51.0436,
    		-53.4228,
    		-51.0122,
    		-50.6261,
    		-53.7108,
    		-54.3617,
    		-52.8832,
    		-50.9914,
    		-48.9337,
    		-48.592,
    		-49.4738,
    		-50.0585,
    		-50.9642,
    		-52.1417,
    		-52.0936,
    		-52.8795,
    		-52.6958,
    		-49.9302,
    		-47.6595,
    		-52.1132,
    		-51.3054,
    		-50.0328,
    		-50.9853,
    		-50.9056,
    		-52.5706,
    		-52.3182,
    		-49.0835,
    		-48.2247,
    		-52.7862,
    		-51.8768,
    		-49.5388,
    		-51.7117,
    		-53.3644,
    		-52.5562,
    		-53.1913,
    		-53.2061,
    		-52.064,
    		-51.4112,
    		-52.2875,
    		-51.7046,
    		-53.4237,
    		-51.6789,
    		-48.9602,
    		-49.615,
    		-54.3065,
    		-52.7595,
    		-51.7539,
    		-52.4489,
    		-51.0018,
    		-48.8141,
    		-49.9922,
    		-50.1697,
    		-51.5571,
    		-55.0326,
    		-49.2505,
    		-47.7099,
    		-50.4369,
    		-49.4718,
    		-47.7357,
    		-49.81,
    		-49.7595,
    		-49.5549,
    		-52.5567,
    		-50.5915,
    		-51.071,
    		-50.3581,
    		-48.8385,
    		-47.9719,
    		-50.531,
    		-53.754,
    		-54.5275,
    		-51.6008,
    		-50.5125,
    		-50.2016,
    		-51.6389,
    		-52.0413,
    		-52.9119,
    		-52.7238,
    		-51.7382,
    		-51.692,
    		-50.3941,
    		-52.276,
    		-53.055,
    		-51.7107,
    		-51.5907,
    		-56.1152,
    		-54.4785,
    		-53.1961,
    		-52.6983,
    		-51.7241,
    		-55.7689,
    		-51.4337,
    		-52.7248,
    		-53.1615,
    		-56.9085,
    		-52.0995,
    		-54.9093,
    		-56.176,
    		-55.7428,
    		-55.3085,
    		-55.296,
    		-55.3061,
    		-54.5521,
    		-38.7349,
    		-36.6404,
    		-35.6112,
    		-36.3573,
    		-38.6825,
    		-40.9994,
    		-54.838,
    		-55.4042,
    		-55.9963,
    		-56.5734,
    		-55.3016,
    		-52.379,
    		-54.4772,
    		-57.5687,
    		-55.7754,
    		-56.1422,
    		-58.4314,
    		-56.3081,
    		-58.3597,
    		-54.8967,
    		-55.1681,
    		-54.94,
    		-56.9699,
    		-54.5725,
    		-53.3058,
    		-55.4576,
    		-57.0444,
    		-54.5734,
    		-55.4882,
    		-58.8719,
    		-57.8147,
    		-57.161,
    		-55.9259,
    		-54.1616,
    		-54.9256,
    		-57.9064,
    		-55.5892,
    		-54.4938,
    		-56.6013,
    		-53.3273,
    		-53.5378,
    		-56.8796,
    		-54.122,
    		-54.2593,
    		-56.193,
    		-53.9324,
    		-55.5943,
    		-57.948,
    		-55.9327,
    		-55.7052,
    		-54.8921,
    		-55.0404,
    		-54.565,
    		-55.2447,
    		-53.395,
    		-54.9005,
    		-56.3495,
    		-57.184,
    		-56.2635,
    		-57.2707,
    		-57.4239,
    		-56.9224,
    		-56.0371,
    		-56.0452,
    		-57.16,
    		-58.3847,
    		-58.6806,
    		-56.2668,
    		-58.4003,
    		-56.7104,
    		-56.2934,
    		-57.4744,
    		-56.0358,
    		-54.3808,
    		-54.3828,
    		-54.9765,
    		-55.1621,
    		-55.7418,
    		-55.4705,
    		-58.0448,
    		-56.9212,
    		-57.1734,
    		-55.65,
    		-54.5887,
    		-57.506,
    		-60.9133,
    		-57.8444,
    		-57.463,
    		-60.6389,
    		-57.9056,
    		-56.315,
    		-57.7275,
    		-59.5114,
    		-58.9604,
    		-57.4103,
    		-56.0218,
    		-55.2313,
    		-55.5317,
    		-57.8286,
    		-55.9575,
    		-57.8296,
    		-58.639,
    		-55.4288,
    		-55.5388,
    		-54.5277,
    		-55.7242,
    		-56.5171,
    		-57.9004,
    		-58.5774,
    		-58.0525,
    		-57.3392,
    		-56.6642,
    		-57.3167,
    		-57.4948,
    		-57.6944,
    		-58.4729,
    		-56.7523,
    		-56.0368,
    		-56.9025,
    		-56.2476,
    		-55.9178,
    		-56.8256,
    		-57.2025,
    		-56.0975,
    		-56.4654,
    		-55.9343,
    		-58.3103,
    		-56.9723,
    		-56.2622,
    		-58.8845,
    		-57.8157,
    		-58.9594,
    		-58.1085,
    		-57.076,
    		-58.3772,
    		-61.9133,
    		-59.8652,
    		-58.0047,
    		-60.263,
    		-58.0358,
    		-58.024,
    		-61.0247,
    		-59.0908,
    		-58.1108,
    		-58.3913,
    		-57.9262,
    		-58.2836,
    		-59.0939,
    		-58.8803,
    		-58.1376,
    		-57.91,
    		-58.8683,
    		-58.4782,
    		-59.3043,
    		-58.0344,
    		-57.5405,
    		-57.2232,
    		-56.4142,
    		-55.2308,
    		-58.6367,
    		-60.2894,
    		-58.3026,
    		-57.6476,
    		-58.7072,
    		-57.2483,
    		-57.0139,
    		-58.3794,
    		-58.8506,
    		-58.9216,
    		-61.2998,
    		-60.9501,
    		-60.7788,
    		-57.7742,
    		-56.8946,
    		-56.6763,
    		-58.6238,
    		-59.6427,
    		-58.9964,
    		-60.5465,
    		-58.0314,
    		-57.6388,
    		-59.3954,
    		-58.3974,
    		-57.6562,
    		-58.0348,
    		-58.047,
    		-60.6587,
    		-60.8311,
    		-57.935,
    		-58.2454,
    		-58.5662,
    		-58.1951,
    		-58.0662,
    		-59.569,
    		-59.0606,
    		-58.507,
    		-57.3905,
    		-58.0025,
    		-59.7966,
    		-58.2268,
    		-58.0629,
    		-57.8326,
    		-57.1805,
    		-59.3286,
    		-59.5327,
    		-59.4585,
    		-61.4747,
    		-59.7711,
    		-58.6101,
    		-58.3887,
    		-58.4864,
    		-58.0447,
    		-56.8286,
    		-55.9196,
    		-56.3552,
    		-59.9929,
    		-59.1182,
    		-60.4975,
    		-59.3041,
    		-57.4506,
    		-56.5174,
    		-57.1703,
    		-60.0005,
    		-59.6632,
    		-59.0451,
    		-59.9379,
    		-57.636,
    		-56.5565,
    		-58.4742,
    		-58.3485,
    		-55.38,
    		-59.3836,
    		-57.7059,
    		-57.7295,
    		-57.0076,
    		-56.6843,
    		-58.024,
    		-58.3442,
    		-58.6589,
    		-58.0776,
    		-57.2852,
    		-59.8936,
    		-58.368,
    		-58.8886,
    		-61.1485,
    		-57.9197,
    		-59.1586,
    		-60.8125,
    		-57.1896,
    		-56.3304,
    		-60.1898,
    		-56.4633,
    };
    	double *out = (double *)malloc(sizeof(in));
    	FILE *fp = fopen("smooth.txt","wb");
     
    	printf("
    =================================
    ");
    	if(1)
    	{
    		//const double f = 0.25;
    		double f = 0.01;
    		const size_t nsteps = 3;
    		const size_t n = sizeof(in)/sizeof(in[0]);
    		const double delta = 0.3;
     
    		double *ys  = (double *) malloc(sizeof(double)*n);
    		double *rw  = (double *) malloc(sizeof(double)*n);
    		double *res = (double *) malloc(sizeof(double)*n);
    		const double *y = &in[0];
    		double *x = (double *) malloc(sizeof(double)*n);
    		
    		double start_freq = -125000000;
    		double rbw = 100000;
    		for (int i = 0; i < n; i++)
    		{
    			x[i] = start_freq+(rbw*i);
    		}
     
    		lowess((const double*)x, (const double*)y, n,f, nsteps,delta, ys, rw, res);
    		memcpy(out,in,sizeof(in));
     
    		int center_point = 250;
    		int smooth_count = 10;
    		for (int i = 0; i < smooth_count; i++)
    		{
    			if (abs(abs(in[(center_point-5)+i]) - abs(ys[(center_point-5)+i])) > 3)
    			{
    				out[(center_point-5)+i] = ys[(center_point-5)+i];
    			}
    		}
    		center_point = 2500 - 250;
    		for (int i = 0; i < smooth_count; i++)
    		{
    			if (abs(abs(in[(center_point-5)+i]) - abs(ys[(center_point-5)+i])) > 3)
    			{
    				out[(center_point-5)+i] = ys[(center_point-5)+i];
    			}
    		}
     
    		for (int i = 0; i < n; i++)
    		{
    			fprintf(fp,"%.4f,%.4f
    ",in[i],out[i]);
    		}
    		fclose(fp);
    		
    		fp = fopen("smooth_2.csv","wb");
    		const int column = 50;
    		double *result[column] = {NULL};
    		
    		for (int i = 0; i < column; i++)
    		{
    			f = 0.001 + (i*0.005);
    			result[i] = (double *) malloc(sizeof(double)*n);
    			lowess((const double*)x, (const double*)y, n,f, nsteps,delta,result[i], rw, res);
    		}
    		for (int j = 0; j < n; j++)
    		{
    			for (int i = 0; i < column; i++)
    			{
    				fprintf(fp,"%.4f",result[i][j]);
    				if (i != column-1)
    				{
    					fprintf(fp,",");
    				}	
    			}
    			fprintf(fp,"
    ");
    		}
    		for (int i = 0; i < column; i++)
    		{
    			free(result[i]);
    		}
     
    		free(x);
    		free(ys);
    		free(rw);
    		free(res);
    	}
    	fclose(fp);
    	printf("create ok
    ");
    	getchar();
    }
    

    【1】scatter plots smooth算法 lowess

  • 相关阅读:
    java流程控制02Scanner进阶使用
    java流程控制01用户交互scanner
    java流程控制05Switch选择结构
    java基础10三元运算符
    CSDN的轮换广告JS
    如何在DataGrid中加入javascript以进行客户端的操作
    Json 的日期格式到.net datetime格式
    利用web.config设置用户不被锁定
    用csc.exe编译程序的例子
    严重关注食物安全
  • 原文地址:https://www.cnblogs.com/sggggr/p/15255512.html
Copyright © 2011-2022 走看看