Mercurial > hg > medcouple
view mlmc.c @ 17:8e35dcdb8dec
Add missing mlmc for MEX medcouple
author | Jordi Gutiérrez Hermoso <jordigh@octave.org> |
---|---|
date | Fri, 16 Jan 2015 13:39:17 -0500 |
parents | |
children |
line wrap: on
line source
#include<stdlib.h> #include<math.h> /*matlabmc.c Algorithm for the skewness estimator medcouple (MC) Needed variables: x: real array containing observations n: number of observations (n>=2) Includes the functions *whimed(a,iw,n): finds the weighted high median of an array a of length n, using the array iw (also of length n) with positive longinteger weights. *sort(x,n,y): sorts an array x of length n and stores the result in an array y (of size at least n) *pull(a,n,k): finds the k-th order statistic of an array a of length n *calwork(a,b,ai,bi,ab,eps): calculates the values needed to compute the mc NOTE: array[0] is empty */ /*declaration of functions*/ #define TRUE 1 #define FALSE 0 void sort(double x[],long n, double y[]); double pull(double a[],long n, long k); double whimed(double a[],long iw[],long n); double calwork(double a,double b,long ai,long bi,long ab,double eps); void mlmc(double *out, double z[],long *in) { double medc,xmed2,yden,xmed,trial,eps; double *work,*y,*x,*y1,*y2; long *left,*right,*weight,*q,*p; long k,knew,nl,nr,sumq,sump,i,j,jj,IsFound,h1,h2,n; n=*in; y=(double *) malloc((n+1)*sizeof(double)); x=(double *) malloc((n+1)*sizeof(double)); y1=(double *) malloc((n+1)*sizeof(double)); y2=(double *) malloc((n+1)*sizeof(double)); work=(double *) malloc((n+1)*sizeof(double)); left=(long *) malloc((n+1)*sizeof(long)); right=(long *) malloc((n+1)*sizeof(long)); weight=(long *) malloc((n+1)*sizeof(long)); q=(long *) malloc((n+1)*sizeof(long)); p=(long *) malloc((n+1)*sizeof(long)); eps=0.0000000000001; x[0]=0; for (i=0;i<n;i++) { x[i+1]=-z[i]; } xmed=pull(x,n,floor(n/2)+1); if (n%2 == 0) { xmed2=pull(x,n,floor(n/2)); xmed=(xmed+xmed2)/2; } for (i=1;i<=n;i++) { x[i]=x[i]-xmed; } sort(x,n,y); if (-y[1] > y[n]) { yden=-2*y[1]; } else { yden=2*y[n]; } for (i=1;i<=n;i++) { y[i]=-y[i]/yden; } j=1; while (y[j] > eps) { y1[j]=y[j]; j++; } i=1; while (y[j] > -eps) { y1[j]=y[j]; y2[i]=y[j]; j++; i++; } h1=j-1; while (j < n+1) { y2[i]=y[j]; j++; i++; } h2=i-1; for (i=1;i<=h2;i++) { left[i]=1; right[i]=h1; } nl=0; nr=h1*h2; knew=floor(nr/2)+1; IsFound=FALSE; while ((nr-nl>n)& (!IsFound)) { j=1; for (i=1;i<=h2;i++) { if (left[i]<=right[i]) { weight[j]=right[i]-left[i]+1; k = left[i]+floor(weight[j]/2); work[j]=calwork(y1[k],y2[i],k,i,h1+1,eps); j++; } } trial=whimed(work,weight,j-1); j=1; for (i=h2;i>=1;i--) { while ((j<=h1)&(calwork(y1[j],y2[i],j,i,h1+1,eps)>trial)) { j++; } p[i]=j-1; } j=h1; for (i=1;i<=h2;i++) { while ((j>=1)&(calwork(y1[j],y2[i],j,i,h1+1,eps)<trial)) { j--; } q[i]=j+1; } sump=0; sumq=0; for (i=1;i<=h2;i++) { sump=sump+p[i]; sumq=sumq+q[i]-1; } if (knew<=sump) { for (i=1;i<=h2;i++) { right[i]=p[i]; } nr=sump; } else { if (knew>sumq) { for (i=1;i<=h2;i++) { left[i]=q[i]; } nl=sumq; } else { medc=trial; IsFound=TRUE; } } } /*end while-lus*/ if (!IsFound) { j=1; for (i=1;i<=h2;i++) { if (left[i]<=right[i]) { for (jj=left[i];jj<=right[i];jj++) { work[j]=-calwork(y1[jj],y2[i],jj,i,h1+1,eps); j++; } } } medc=pull(work,j-1,knew-nl); medc=-medc; } free(y); free(x); free(y1); free(y2); free(work); free(left); free(right); free(weight); free(p); free(q); *out=medc; } /*sort*/ void sort(double a[],long n, double b[]) { double xx,amm; long i,jss,jndl,jr,jnc,j,jtwe; long *jlv,*jrv; jlv=(long *) malloc((n+1)*sizeof(long)); jrv=(long *) malloc((n+1)*sizeof(long)); for (i=1;i<=n;i++) { b[i]=a[i]; } jss=1; jlv[1]=1; jrv[1]=n; do { jndl=jlv[jss]; jr=jrv[jss]; jss=jss-1; do { jnc=jndl; j=jr; jtwe=floor((jndl+jr)/2); xx=b[jtwe]; do { while (b[jnc]<xx) { jnc++; } while (xx<b[j]) { j--; } if (jnc<=j) { amm=b[jnc]; b[jnc]=b[j]; b[j]=amm; jnc++; j--; } } while (jnc<=j) ; if ((j-jndl)>=(jr-jnc)) { if (jndl<j) { jss++; jlv[jss]=jndl; jrv[jss]=j; } jndl=jnc; } else { if (jnc<jr) { jss++; jlv[jss]=jnc; jrv[jss]=jr; } jr=j; } } while (jndl<jr); } while (jss!=0); free(jrv); free(jlv); } /*pull*/ double pull(double a[],long n, long k) { double* b; double outp,ax,buffer; long l,lr,jnc,j,i; b=(double *) malloc((n+1)*sizeof(double)); for (i=1;i<=n;i++) { b[i]=a[i]; } l=1; lr=n; while (l<lr) { ax=b[k]; jnc=l; j=lr; while (jnc<=j) { while (b[jnc]<ax) { jnc++; } while (b[j]>ax) { j--; } if (jnc<=j) { buffer=b[jnc]; b[jnc]=b[j]; b[j]=buffer; jnc++; j--; } } if (j<k) { l=jnc; } if (k<jnc) { lr=j; } } outp=b[k]; free(b); return(outp); } double whimed(double a[],long iw[],long n) { double* acand; double trial,whmed; long* iwcand; long nn; long i,wtotal,wrest,wleft,wmid,wright,kcand,IsFound; acand=(double *) malloc((n+1)*sizeof(double)); iwcand=(long *) malloc((n+1)*sizeof(long)); nn=n; wtotal=0; for (i=1;i<=nn;i++) { wtotal+=iw[i]; } wrest=0; IsFound=FALSE; while (!IsFound) { wleft=0; wmid=0; wright=0; trial=pull(a,nn,floor(nn/2)+1); for (i=1;i<=nn;i++) { if (a[i]<trial) { wleft+=iw[i]; } else { if (a[i]>trial) { wright+=iw[i]; } else { wmid+=iw[i]; } /*end else 2*/ } /*end else 1*/ } /*end for*/ if ((2*wrest+2*wleft)>wtotal) { kcand=0; for (i=1;i<=nn;i++) { if (a[i]<trial) { kcand++; acand[kcand]=a[i]; iwcand[kcand]=iw[i]; } } nn=kcand; } else { if ((2*wrest+2*wleft+2*wmid) >wtotal) { whmed=trial; IsFound=TRUE; } else { kcand=0; for (i=1;i<=nn;i++) { if (a[i]>trial) { kcand++; acand[kcand]=a[i]; iwcand[kcand]=iw[i]; } }/*end for*/ nn=kcand; wrest=wrest+wleft+wmid; } /*end else 2*/ } /*end else 1*/ for(i=1;i<=nn;i++) { a[i]=acand[i]; iw[i]=iwcand[i]; } }/*end while*/ free(iwcand); free(acand); return(whmed); } /*calwork*/ double calwork(double a,double b,long ai,long bi,long ab,double eps) { double cwork; if (fabs(a-b) < 2.0*eps) { if (ai+bi == ab) { cwork = 0; } else { if (ai+bi < ab) { cwork = 1; } else { cwork = -1; } } } else { cwork = (a+b)/(a-b); } return(cwork); }