/* $OpenXM: OpenXM/src/hgm/fisher-bingham/src/hgm_ko_nc_fb.c,v 1.1 2014/03/26 04:38:38 takayama Exp $ The original source was tkoyama-initial.c, which evaluates the normalizing constant of the Fisher-Bingham distribution. gcc hgm_ko_fb.c -lm -lgsl -lblas on orange */ #include #include #include #include #include #include #include #include #define MAXSIZE 10 /* maximum size of the matrix x */ #define RKERROR 1e-6 /* error of runge-kutta */ #define NEWINITIAL #define RANGE 1000 /*#define DEBUG_INITIAL*/ struct list{ double c; struct list *next; }; struct tkoyama_params { int dim; gsl_matrix *pfs0, *pfs1; }; #if SAMPLE > 0 double *fbnd(int dim, double x[MAXSIZE][MAXSIZE], double y[], int maxdeg, int weight[]); #else double *fbnd(int dim, double **x, double *y, int maxdeg, int *weight); #endif double *fbnd_diag(int dim, double x1[], double y1[], int maxdeg, int *weight); int rk_func (double t, const double y[], double f[], void *params); struct tkoyama_params* set_pfs(int dim, double x[], double y[]); int free_pfs(struct tkoyama_params *params); double *fbnd_internal(int dim, double x[], double y[], double r, int maxdeg, int *weight); struct list *mk_coeff(int dim, double r, int maxdeg, int *weight); void free_coeff(struct list *coeff); struct list *cons(double c, struct list *coeff); double fbnd_internal_dyi(int dim, double x[], double y[], double r, int maxdeg, int *weight, struct list *coeff, int i); double fbnd_internal_dyii(int dim, double x[], double y[], double r, int maxdeg, int *weight, struct list *coeff, int i); int set_tdev(double); static double eps_pert = 0.0; #if SAMPLE == 0 int main(int argc, char *argv[]) { int dim; /* dimension of the sphere */ double r = 1.0; double Two; int maxdeg = 10; int i,j,k,M; FILE *fp; char fname[1024]; double **X, *Xy, *Y; int *weight; if (argc<2) {usage(); return(-1);} for (k=1; k0){ dim=M-1; printf("dim: %d\n",dim); X = (double **)malloc(sizeof(double *) * M); Xy = (double *)malloc(sizeof(double) * M*M); Y = (double *)malloc(sizeof(double) * M); for (i=0; ii) X[i][j] *= Two; X[j][i] = X[i][j]; k++; if (k >= argc) break; } if (k>= argc) break; } for (i=0; i= argc) break; } } } for (i=0; i 0 double* fbnd(int dim, double x[MAXSIZE][MAXSIZE], double y[], int maxdeg, int weight[]) #else double *fbnd(int dim, double **x, double *y, int maxdeg, int *weight) #endif { gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc( dim+1); gsl_matrix *A = gsl_matrix_alloc(dim+1, dim+1); gsl_vector *eval = gsl_vector_alloc(dim+1); gsl_matrix *evec = gsl_matrix_alloc(dim+1, dim+1); double xdiag[dim+1], ydiag[dim+1]; double *f; double h[dim+1][dim+1]; double *ans = (double *) malloc((2*dim+2)*sizeof(double)); int i,j,k; for(i=0; i RANGE){ return (int)(rr/RANGE) ; } else { return 1; } } double* fbnd_diag(int dim, double x1[], double y1[], int maxdeg, int *weight) { int i, status; double sum, r; double x[dim+1], y[dim+1]; double *g, tmp; sum = 0.0; for(i=0; i %f \n", ii,t, t1); while (t < t1){ status = gsl_odeiv_evolve_apply (e, c, s, &sys, &t, t1, &h, g); if (status != GSL_SUCCESS) break; #ifdef DEBUG_INITIAL printf("s = %f [", t); for(i = 0; i< 2*dim+1; i++) printf("%g, ", g[i]); printf("%g]\n ", g[i]); /* printf("[%f,%f,%f,%f,%f,%f,%f,%f,%f]\n", g_x11 + t * params[0], g_x12 + t * params[1], g_x13 + t * params[2], g_x22 + t * params[3], g_x23 + t * params[4], g_x33 + t * params[5], g_y1 + t * params[6], g_y2 + t * params[7], g_y3 + t * params[8]); */ #endif } gsl_odeiv_evolve_free (e); gsl_odeiv_control_free (c); gsl_odeiv_step_free (s); free_pfs(params); /* if(ii%1 == 0){ printf("enter"); scanf("%s", sss); }*/ } tmp = exp(r*r*x[0]); for(i=0; i<2*dim+2; i++){g[i] *= tmp;} tmp = pow(r, dim+1); for(i=0; idim; gsl_matrix *pfs0 = prms->pfs0; gsl_matrix *pfs1 = prms->pfs1; int i, j; for (i = 0; i < 2*dim+2; i++) { f[i] = 0.0; for (j = 0; j < 2*dim+2; j++) f[i] += (gsl_matrix_get(pfs0, i, j)+ gsl_matrix_get(pfs1, i, j)/(2*s) )* y[j]; } return GSL_SUCCESS; } struct tkoyama_params* set_pfs(int dim, double x[], double y[]) { struct tkoyama_params *ans = (struct tkoyama_params *)malloc(sizeof(struct tkoyama_params)); gsl_matrix *pfs0, *pfs1; int i,j; pfs0 = gsl_matrix_alloc(2*dim+2, 2*dim+2); pfs1 = gsl_matrix_alloc(2*dim+2, 2*dim+2); gsl_matrix_set_zero(pfs0); gsl_matrix_set_zero(pfs1); for(i=1; idim = dim; ans->pfs0 = pfs0; ans->pfs1 = pfs1; return ans; } int free_pfs(struct tkoyama_params *params) { gsl_matrix_free(params->pfs0); gsl_matrix_free(params->pfs1); free(params); return 1; } double* fbnd_internal(int dim, double x[], double y[], double r, int maxdeg, int *weight) { double *ans = (double*) malloc((2*dim+2)*sizeof(double)); double s = 2*pow(M_PI,((dim+1)/2.0)) / gsl_sf_gamma((dim+1)/2.0); struct list *coeff = mk_coeff(dim,r,maxdeg, weight);; int i; #ifdef DEBUG_INITIAL printf("fbnd_interal:runge-kutta initial value \n"); #endif for(i=0; i -1){ if(sum[dp] < max+1){ if(dp == maxdp-1){ coeff = cons( ans[dp], coeff); }else{ dp++; sum[dp] = sum[dp-1]; s[dp] = s[dp-1]; ans[dp] = ans[dp-1]; continue; } }else{ dp--; if(dp == -1){ break; }else{ idx[dp+1] = 0; } } if(dp < dim+1){ ans[dp] = ans[dp]*r*r*(2*idx[dp]+2*idx[dp+dim+1]+1)/(dim+1+2*s[dp]); } else { ans[dp] = ans[dp]*r*r*(2*idx[dp-dim-1]+2*idx[dp]+1)/(dim+1+2*s[dp]); } s[dp+1] = 0; idx[dp]++; sum[dp] = sum[dp] + weight[dp]; s[dp]++; } return coeff; } void free_coeff(struct list *coeff) { struct list *tmp; while(coeff != NULL){ tmp = coeff->next; free(coeff); coeff = tmp; } } struct list* cons(double c, struct list *coeff) { struct list *ans = malloc(sizeof(struct list)); ans->c = c; ans->next = coeff; return ans; } double fbnd_internal_dyi(int dim, double x[], double y[], double r, int maxdeg, int *weight, struct list *coeff, int i) { int maxdp = 2*dim+2; int max = maxdeg; double ans[maxdp+1]; int s[maxdp+1]; int idx[maxdp]; int sum[maxdp]; int dp=0; int ic; for(ic=0; ic -1){ if(idx[dp] > -1){ if(dp == maxdp-1){ ans[dp+1] = coeff->c; coeff = coeff->next; }else{ dp++; idx[dp] = (max - sum[dp-1]) / weight[dp]; sum[dp] = sum[dp-1] + idx[dp]*weight[dp]; continue; } }else { dp--; if(dp == -1){ break; } } if(dp == dim+1+i){ if(idx[dp] > 1){ ans[dp] = (ans[dp] + ans[dp+1]) * y[dp -(dim +1)]*y[dp -(dim+1)] /(double)( (2*idx[dp]-1)*(2*idx[dp]-2)); } else if(idx[dp] == 1){ ans[dp] = (ans[dp] + ans[dp+1]) * y[dp -(dim +1)]; } }else { if(idx[dp] > 0){ if(dp < dim+1){ ans[dp] = (ans[dp] + ans[dp+1]) * x[dp]/idx[dp]; } else { ans[dp] = (ans[dp] + ans[dp+1]) * y[dp -(dim +1)]*y[dp -(dim+1)] /(double)( 2*idx[dp]*(2*idx[dp]-1)); } }else if(idx[dp] == 0){ ans[dp] = ans[dp] + ans[dp+1]; } } ans[dp+1] = 0; idx[dp]--; sum[dp] = sum[dp] - weight[dp]; } return ans[0]; } double fbnd_internal_dyii(int dim, double x[], double y[], double r, int maxdeg, int *weight, struct list *coeff, int i) { int maxdp = 2*dim+2; int max = maxdeg; double ans[maxdp+1]; int s[maxdp+1]; int idx[maxdp]; int sum[maxdp]; int dp=0; int ic; for(ic=0; ic -1){ if(idx[dp] > -1){ if(dp == maxdp-1){ ans[dp+1] = coeff->c; coeff = coeff->next; }else{ dp++; idx[dp] = (max - sum[dp-1])/ weight[dp]; sum[dp] = sum[dp-1] + idx[dp]*weight[dp]; continue; } }else { dp--; if(dp == -1){ break; } } if(dp == dim+1+i){ if(idx[dp] > 1){ ans[dp] = (ans[dp] + ans[dp+1]) * y[dp -(dim +1)]*y[dp -(dim+1)] /( (2*idx[dp]-2)*(2*idx[dp]-3)); } else if(idx[dp] == 1){ ans[dp] = ans[dp] + ans[dp+1]; } }else { if(idx[dp] > 0){ if(dp < dim+1){ ans[dp] = (ans[dp] + ans[dp+1]) * x[dp]/idx[dp]; } else { ans[dp] = (ans[dp] + ans[dp+1]) * y[dp -(dim +1)]*y[dp -(dim+1)] /( 2*idx[dp]*(2*idx[dp]-1)); } }else if(idx[dp] == 0){ ans[dp] = ans[dp] + ans[dp+1]; } } ans[dp+1] = 0; idx[dp]--; sum[dp] = sum[dp] - weight[dp]; } return ans[0]; }