#include <math.h>
#include <stdlib.h>
#if !defined(__APPLE__)
#include <malloc.h>
#endif
#include <stdio.h>
#include <assert.h>
#include <time.h>
#include <string.h>
#include <stdbool.h>

#include <fftw3.h>

#include <gsl/gsl_errno.h>
#include <gsl/gsl_sf_erf.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_spline.h>
#include <gsl/gsl_sf_gamma.h>
#include <gsl/gsl_sf_legendre.h>
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_eigen.h>
#include <gsl/gsl_sf_expint.h>
#include <gsl/gsl_deriv.h>
#include <gsl/gsl_interp2d.h>
#include <gsl/gsl_spline2d.h>

#include "../cosmolike_core/theory/basics.c"
#include "../cosmolike_core/theory/structs.c"
#include "../cosmolike_core/theory/parameters.c"
#include "../cosmolike_core/emu17/P_cb/emu.c"
#include "../cosmolike_core/theory/recompute.c"
#include "../cosmolike_core/theory/cosmo3D.c"
#include "../cosmolike_core/theory/redshift_spline.c"
#include "../cosmolike_core/theory/halo.c"
#include "../cosmolike_core/theory/HOD.c"
#include "../cosmolike_core/theory/pt.c"
#include "../cosmolike_core/theory/cosmo2D_fourier.c"
#include "../cosmolike_core/theory/IA.c"
#include "../cosmolike_core/theory/BAO.c"
#include "../cosmolike_core/theory/external_prior.c"
#include "../cosmolike_core/theory/covariances_3D.c"
#include "../cosmolike_core/theory/covariances_fourier.c"
#include "../cosmolike_core/theory/CMBxLSS_fourier.c"
#include "../cosmolike_core/theory/covariances_CMBxLSS_fourier.c"

#include "init_LSSxCMB.c"

// Naming convention:
// l = galaxy positions ("l" as in "lens sample")
// k = kappa CMB ("k" as in "kappa")
// s = kappa from source galaxies ("s" as in "source sample")
// And alphabetical order

void run_cov_ls_ss(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int n2,int start);
void run_cov_ll_ss(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int n2,int start);
void run_cov_ll_ls(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int n2,int start);
void run_cov_ll_ll(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int n2,int start);
void run_cov_ls_ls(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int n2,int start);
void run_cov_ss_ss(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int n2,int start);

void run_cov_ls_kk(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int start);
void run_cov_ls_ks(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int zs2, int start);
void run_cov_lk_lk(char *OUTFILE, char *PATH, double *ell, double *dell, int zl1, int zl2, int start);
void run_cov_lk_ls(char *OUTFILE, char *PATH, double *ell, double *dell, int zl1, int n2, int start);
void run_cov_lk_kk(char *OUTFILE, char *PATH, double *ell, double *dell, int zl1, int start);
void run_cov_lk_ks(char *OUTFILE, char *PATH, double *ell, double *dell, int zl1, int zs2, int start);
void run_cov_lk_ss(char *OUTFILE, char *PATH, double *ell, double *dell, int zl1, int n2,int start);
void run_cov_kk_kk(char *OUTFILE, char *PATH, double *ell, double *dell,int start);
void run_cov_kk_ks(char *OUTFILE, char *PATH, double *ell, double *dell, int zs2, int start);
void run_cov_kk_ss(char *OUTFILE, char *PATH, double *ell, double *dell, int n2, int start);
void run_cov_ks_ks(char *OUTFILE, char *PATH, double *ell, double *dell, int zs1, int zs2,int start);
void run_cov_ks_ss(char *OUTFILE, char *PATH, double *ell, double *dell, int zs1, int n2, int start);
void run_cov_ll_kk(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int start);
void run_cov_ll_ks(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int zs2, int start);
void run_cov_ll_lk(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int zl2,int start);

void run_cov_ls_ss(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int n2,int start)
{
  int zl,zs,z3,z4,nl1,nl2,weight,i,j;
  double c_ng, c_g;
  FILE *F1;
  char filename[300];
  sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
  F1 =fopen(filename,"w");
  zl = ZL(n1); zs = ZS(n1);
  printf("\nN_ggl = %d (%d, %d)\n", n1,zl,zs);
  z3 = Z1(n2); z4 = Z2(n2);
  printf("N_shear = %d (%d, %d)\n", n2,z3,z4);
  for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
    for (nl2 = 0; nl2 <like.Ncl; nl2 ++){
      c_ng = 0.; c_g = 0.;
      weight = test_kmax(ell[nl1],zl);
      if (weight && ell[nl2] < like.lmax_shear){
        if (test_zoverlap(zl,z3)*test_zoverlap(zl,z4)){
          c_ng = cov_NG_gl_shear_tomo(ell[nl1],ell[nl2],zl,zs,z3,z4);
        }
        if (nl1 == nl2){
          c_g =  cov_G_gl_shear_tomo(ell[nl1],dell[nl1],zl,zs,z3,z4);
        }
      }
      i=like.Ncl*(tomo.shear_Npowerspectra+n1)+nl1;
      j=like.Ncl*n2+nl2;
      fprintf(F1, "%d %d %e %e %d %d %d %d  %e %e\n",i,j,ell[nl1],ell[nl2],zl,zs,z3,z4,c_g,c_ng);
    }
  }
  fclose(F1);
}

void run_cov_ll_ss(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int n2,int start)
{
  int z1,z2,z3,z4,nl1,nl2,i,j,weight;
  double c_ng, c_g;
  FILE *F1;
  char filename[300];
  sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
  F1 =fopen(filename,"w");
  z1 = n1; z2 = n1;
  printf("\nN_cl = %d \n", n1);
  z3 = Z1(n2); z4 = Z2(n2);
  printf("N_shear = %d (%d, %d)\n", n2,z3,z4);
  for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
    for (nl2 = 0; nl2 <like.Ncl; nl2 ++){
      c_ng = 0.; c_g = 0.;
      weight = test_kmax(ell[nl1],z1);
      if (weight && ell[nl2] < like.lmax_shear){
        if (test_zoverlap(z1,z3)*test_zoverlap(z1,z4)){
          c_ng = cov_NG_cl_shear_tomo(ell[nl1],ell[nl2],z1,z2,z3,z4);
        }
        if (nl1 == nl2){
          c_g =  cov_G_cl_shear_tomo(ell[nl1],dell[nl1],z1,z2,z3,z4);
        }
      }
      i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+n1)+nl1;
      j=like.Ncl*n2+nl2;
      fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],z1,z2,z3,z4,c_g,c_ng);
    }
  }
  fclose(F1);
}

void run_cov_ll_ls(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int n2,int start)
{
  int z1,z2,zl,zs,nl1,nl2,i,j,weight;
  double c_ng, c_g;
  FILE *F1;
  char filename[300];
  sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
  F1 =fopen(filename,"w");
  z1 = n1; z2 = n1;
  printf("\nN_cl_1 = %d \n", n1);
  zl = ZL(n2); zs = ZS(n2);
  printf("N_tomo_2 = %d (%d, %d)\n", n2,zl,zs);
  for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
    for (nl2 = 0; nl2 < like.Ncl; nl2 ++){
      c_ng = 0.; c_g = 0.;
      weight = test_kmax(ell[nl1],z1)*test_kmax(ell[nl2],zl);
      if (weight){
        if((z1 == zl)*test_zoverlap(z1,zs)){c_ng = cov_NG_cl_gl_tomo(ell[nl1],ell[nl2],z1,z2,zl,zs);}
        if (nl1 == nl2){
          c_g =  cov_G_cl_gl_tomo(ell[nl1],dell[nl1],z1,z2,zl,zs);
        }
      }
      i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+n1)+nl1;
      j=like.Ncl*(tomo.shear_Npowerspectra+n2)+nl2;
      fprintf(F1, "%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],z1,z2,zl,zs,c_g,c_ng);
    }
  }
  fclose(F1);
}

void run_cov_ll_ll(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int n2,int start)
{
  int z1,z2,z3,z4,nl1,nl2,i,j,weight;
  double c_ng, c_g;
  FILE *F1;
  char filename[300];
  sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
  F1 =fopen(filename,"w");
  z1 = n1; z2 = n1;
  printf("\nN_cl_1 = %d \n", n1);
  z3 = n2; z4 = n2;
  printf("N_cl_2 = %d\n", n2);
  for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
    for (nl2 = 0; nl2 < like.Ncl; nl2 ++){
      c_ng = 0.; c_g = 0.;
      weight = test_kmax(ell[nl1],z1)*test_kmax(ell[nl2],z3);
      if ((z1 == z3) && weight) {
        c_ng = cov_NG_cl_cl_tomo(ell[nl1],ell[nl2],z1,z2,z3,z4);
      }
      if (nl1 == nl2){
        c_g =  cov_G_cl_cl_tomo(ell[nl1],dell[nl1],z1,z2,z3,z4);
      }
      i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+n1)+nl1;
      j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+n2)+nl2;
      fprintf(F1, "%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],z1,z2,z3,z4,c_g,c_ng);
    }
  }
  fclose(F1);
}

void run_cov_ls_ls(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int n2,int start)
{
  int zl1,zl2,zs1,zs2,nl1,nl2,i,j,weight;
  double c_ng, c_g;
  double fsky = survey.area/41253.0;
  FILE *F1;
  char filename[300];
  sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
  F1 =fopen(filename,"w");

  zl1 = ZL(n1); zs1 = ZS(n1);
  printf("\nN_tomo_1 = %d (%d, %d)\n", n1,zl1,zs1);
  zl2 = ZL(n2); zs2 = ZS(n2);
  printf("N_tomo_2 = %d (%d, %d)\n", n2,zl2,zs2);
  for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
    for (nl2 = 0; nl2 < like.Ncl; nl2 ++){
      c_ng = 0.; c_g = 0.;
      weight = test_kmax(ell[nl1],zl1)*test_kmax(ell[nl2],zl2);
      if (weight && zl1 == zl2) {
        c_ng = cov_NG_gl_gl_tomo(ell[nl1],ell[nl2],zl1,zs1,zl2,zs2);
      }
      if (nl1 == nl2){
        c_g =  cov_G_gl_gl_tomo(ell[nl1],dell[nl1],zl1,zs1,zl2,zs2);
      }
      if (weight ==0 && n2 != n1){
        c_g = 0;
      }
      i=like.Ncl*(tomo.shear_Npowerspectra+n1)+nl1;
      j=like.Ncl*(tomo.shear_Npowerspectra+n2)+nl2;
      fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],zl1,zs1,zl2,zs2,c_g,c_ng);
    }
  }
  fclose(F1);
}

void run_cov_ss_ss(char *OUTFILE, char *PATH, double *ell, double *dell,int n1, int n2,int start)
{
  int z1,z2,z3,z4,nl1,nl2,i,j,weight;
  double c_ng, c_g;
  FILE *F1;
  char filename[300];
  z1 = Z1(n1); z2 = Z2(n1);
  printf("N_shear = %d\n", n1);
  z3 = Z1(n2); z4 = Z2(n2);
  printf("N_shear = %d (%d, %d)\n",n2,z3,z4);
  sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
  F1 =fopen(filename,"w");
  for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
    for (nl2 = 0; nl2 < like.Ncl; nl2 ++){
      c_ng = 0.; c_g = 0.;
      if (ell[nl1] < like.lmax_shear && ell[nl2] < like.lmax_shear){
        c_ng = cov_NG_shear_shear_tomo(ell[nl1],ell[nl2],z1,z2,z3,z4);
      }
      if (nl1 == nl2){
        c_g =  cov_G_shear_shear_tomo(ell[nl1],dell[nl1],z1,z2,z3,z4);
        if (ell[nl1] > like.lmax_shear && n1!=n2){c_g = 0.;}
      }
      i=like.Ncl*n1+nl1;
      j=like.Ncl*n2+nl2;
      fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],z1,z2,z3,z4,c_g,c_ng);
      //printf("%d %d %e %e %d %d %d %d %e %e\n", like.Ncl*n1+nl1,like.Ncl*(n2)+nl2, ell[nl1],ell[nl2],z1,z2,z3,z4,c_g,c_ng);
    }
  }
  fclose(F1);
}

/*** CMBkappa part ****/
// ls_kk
void run_cov_ls_kk(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int start)
{
   int zl1, zs1,i,j, weight;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   zl1 = ZL(n1); zs1 = ZS(n1);
   printf("Bin for ls: %d (%d, %d)\n", n1, zl1, zs1);
   for (int nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (int nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         weight = test_kmax(ell[nl1], zl1);
         if (weight && ell[nl2]<like.lmax_kappacmb) {
            c_ng = cov_NG_gs_kk(ell[nl1],ell[nl2], zl1, zs1);
            if (nl1==nl2){
               c_g = cov_G_gs_kk(ell[nl1], dell[nl1], zl1, zs1);
            }
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+n1)+nl1;
         j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+tomo.shear_Nbin)+nl2;
         fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],zl1,zs1,0,0,c_g,c_ng);
      }
   }
   fclose(F1);
}

// ls_ks
void run_cov_ls_ks(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int zs2, int start)
{
   int zl1, zs1,i,j,weight;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   zl1 = ZL(n1); zs1 = ZS(n1);
   printf("Bin for ls: %d (%d, %d)\n", n1, zl1, zs1);
   printf("Bin for ks: %d\n", zs2);
   for (int nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (int nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         weight = test_kmax(ell[nl1], zl1);
         if (weight && ell[nl2]<like.lmax_kappacmb) {
            if (test_zoverlap(zl1, zs2)) {
               c_ng = cov_NG_gs_ks(ell[nl1],ell[nl2], zl1, zs1, zs2);
            }
            if (nl1==nl2){
               c_g = cov_G_gs_ks(ell[nl1], dell[nl1], zl1, zs1, zs2);
            }
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+n1)+nl1;
         j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+zs2)+nl2;
         fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],zl1,zs1,0,zs2,c_g,c_ng);
      }
   }
   fclose(F1);
}
// lk_lk
void run_cov_lk_lk(char *OUTFILE, char *PATH, double *ell, double *dell, int zl1, int zl2, int start)
{
   int weight,i,j;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   printf("Lens bins: %d, %d\n", zl1, zl2);

   for (int nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (int nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         weight = test_kmax(ell[nl1],zl1)*test_kmax(ell[nl2],zl2);
         bool compute = weight * (ell[nl1]<like.lmax_kappacmb) * (ell[nl2]<like.lmax_kappacmb);
         if (compute && (zl1==zl2)) {
            c_ng = cov_NG_gk_gk(ell[nl1],ell[nl2], zl1, zl2);
         }
         if (nl1==nl2){
            c_g = cov_G_gk_gk(ell[nl1], dell[nl1], zl1, zl2);
         }
         if (!compute && (zl2!=zl1)) {
            c_g = 0;
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+zl1)+nl1;
         j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+zl2)+nl2;
         fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],zl1,0,zl2,0,c_g,c_ng);
      }
   }
   fclose(F1);
}

// lk_ls
void run_cov_lk_ls(char *OUTFILE, char *PATH, double *ell, double *dell, int zl1, int n2, int start)
{
   int zl2,zs2,nl1,nl2,i,j, weight;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   // sprintf(filename,"%scov/%s_%s_cov_gkgs_Nell%d_Ns%d_Ng%d_%d", PATH, survey.name, cmb.name, like.Ncl, tomo.shear_Nbin, tomo.clustering_Nbin, start);
   // printf("Saving to: %s\n",filename);
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   printf("Lens bin for lk: %d\n", zl1);
   zl2 = ZL(n2); zs2 = ZS(n2);
   printf("N_tomo for ls = %d (%d, %d)\n", n2,zl2,zs2);

   for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         weight = test_kmax(ell[nl1],zl1)*test_kmax(ell[nl2],zl2);
         if (weight && ell[nl1]<like.lmax_kappacmb && ell[nl2]<like.lmax_kappacmb) {
            if (zl1==zl2) {
               c_ng = cov_NG_gk_gs(ell[nl1],ell[nl2],zl1,zl2,zs2);
            }
            if (nl1==nl2){
               c_g = cov_G_gk_gs(ell[nl1], dell[nl1], zl1,zl2,zs2);
            }
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+zl1)+nl1;
         j=like.Ncl*(tomo.shear_Npowerspectra+n2)+nl2;
         fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],zl1,0,zl2,zs2,c_g,c_ng);
      }
   }
   fclose(F1);
}

// lk_kk
void run_cov_lk_kk(char *OUTFILE, char *PATH, double *ell, double *dell, int zl1, int start)
{
   int weight,i,j;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   // sprintf(filename,"%scov/%s_%s_cov_gkkk_Nell%d_Ns%d_Ng%d_%d", PATH, survey.name, cmb.name, like.Ncl, tomo.shear_Nbin, tomo.clustering_Nbin, start);
   // printf("Saving to: %s\n",filename);
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   printf("Bin for lk: %d\n", zl1);

   for (int nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (int nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         weight = test_kmax(ell[nl1],zl1);
         if (weight && ell[nl1]<like.lmax_kappacmb && ell[nl2]<like.lmax_kappacmb) {
            c_ng = cov_NG_gk_kk(ell[nl1],ell[nl2],zl1);
            if (nl1==nl2){
               c_g = cov_G_gk_kk(ell[nl1],dell[nl1],zl1);
            }
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+zl1)+nl1;
         j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+tomo.shear_Nbin)+nl2;
         fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],zl1,0,0,0,c_g,c_ng);
      }
   }
   fclose(F1);
}

// lk_ks
void run_cov_lk_ks(char *OUTFILE, char *PATH, double *ell, double *dell, int zl1, int zs2, int start)
{
   int weight,i,j;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   // sprintf(filename,"%scov/%s_%s_cov_gkks_Nell%d_Ns%d_Ng%d_%d", PATH, survey.name, cmb.name, like.Ncl, tomo.shear_Nbin, tomo.clustering_Nbin, start);
   // printf("Saving to: %s\n",filename);
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   printf("Bin for lk: %d\n", zl1);
   printf("Bin for ks: %d\n", zs2);

   for (int nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (int nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         weight = test_kmax(ell[nl1], zl1);
         if (weight && ell[nl1]<like.lmax_kappacmb && ell[nl2]<like.lmax_kappacmb) {
            if (test_zoverlap(zl1, zs2)) {
               c_ng = cov_NG_gk_ks(ell[nl1],ell[nl2], zl1, zs2);
            }
            if (nl1==nl2){
               c_g =  cov_G_gk_ks(ell[nl1], dell[nl1], zl1, zs2);
            }
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+zl1)+nl1;
         j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+zs2)+nl2;
         fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],zl1,0,0,zs2,c_g,c_ng);
      }
   }
   fclose(F1);
}

// lk_ss
void run_cov_lk_ss(char *OUTFILE, char *PATH, double *ell, double *dell, int zl1, int n2,int start)
{
   int zs2,zs3,nl1,nl2,weight,i,j;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   // sprintf(filename,"%scov/%s_%s_cov_gkss_Nell%d_Ns%d_Ng%d_%d",PATH,survey.name, cmb.name, like.Ncl, tomo.shear_Nbin, tomo.clustering_Nbin, start);
   // printf("Saving to: %s\n",filename);
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   printf("Bin for lk: %d\n", zl1);
   zs2 = Z1(n2); zs3 = Z2(n2);
   printf("Bin for ss: %d (%d, %d)\n", n2, zs2, zs3);
   for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (nl2 = 0; nl2 <like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         weight = test_kmax(ell[nl1],zl1);
         if (weight && ell[nl1]<like.lmax_kappacmb && ell[nl2]<like.lmax_shear){
            if (test_zoverlap(zl1, zs2)*test_zoverlap(zl1, zs3)) {
               c_ng = cov_NG_gk_ss(ell[nl1],ell[nl2],zl1,zs2,zs3);
            }
            if (nl1==nl2){
               c_g = cov_G_gk_ss(ell[nl1],dell[nl1],zl1,zs2, zs3);
            }
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+zl1)+nl1;
         j=like.Ncl*n2+nl2;
         fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],zl1,0,zs2,zs3,c_g,c_ng);
      }
   }
   fclose(F1);
}

// kk_kk
void run_cov_kk_kk(char *OUTFILE, char *PATH, double *ell, double *dell,int start)
{
   int nl1,nl2,i,j,weight;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   // sprintf(filename,"%scov/%s_%s_cov_kkkk_Nell%d_Ns%d_Ng%d_%d",PATH,survey.name, cmb.name,like.Ncl, tomo.shear_Nbin, tomo.clustering_Nbin, start);
   // printf("Saving to: %s\n",filename);
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         if (ell[nl1]<like.lmax_kappacmb && ell[nl2]<like.lmax_kappacmb){
            c_ng = cov_NG_kk_kk(ell[nl1],ell[nl2]);
         }
         if (nl1==nl2){
            c_g = cov_G_kk_kk(ell[nl1], dell[nl1]);
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+tomo.shear_Nbin)+nl1;
         j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+tomo.shear_Nbin)+nl2;
         fprintf(F1, "%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],0,0,0,0,c_g,c_ng);
//         printf("l1, l2, Cg, Cng = %le, %le, %le, %le\n", ell[nl1], ell[nl2], c_g, c_ng);
      }
   }
   fclose(F1);
}

// kk_ks
void run_cov_kk_ks(char *OUTFILE, char *PATH, double *ell, double *dell, int zs2, int start)
{
   int nl1,nl2,i,j, weight;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   // sprintf(filename,"%scov/%s_%s_cov_kkks_Nell%d_Ns%d_Ng%d_%d", PATH, survey.name, cmb.name, like.Ncl, tomo.shear_Nbin, tomo.clustering_Nbin, start);
   // printf("Saving to: %s\n",filename);
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   printf("Source bin for ks: %d\n", zs2);
   for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         if (ell[nl1]<like.lmax_kappacmb && ell[nl2]<like.lmax_kappacmb) {
            c_ng = cov_NG_kk_ks(ell[nl1],ell[nl2],zs2);
            if (nl1==nl2){
               c_g = cov_G_kk_ks(ell[nl1],dell[nl1], zs2);
            }
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+tomo.shear_Nbin)+nl1;
         j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+zs2)+nl2;
         fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],0,0,0,zs2,c_g,c_ng);
      }
   }
   fclose(F1);
}

// kk_ss
void run_cov_kk_ss(char *OUTFILE, char *PATH, double *ell, double *dell, int n2, int start)
{
   int z2,z3,nl1,nl2,i,j,weight;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   z2 = Z1(n2); z3 = Z2(n2);
   printf("Bin for ss: %d (%d, %d)\n", n2, z2, z3);
   // sprintf(filename,"%scov/%s_%s_cov_kkss_Nell%d_Ns%d_Ng%d_%d",PATH,survey.name, cmb.name,like.Ncl, tomo.shear_Nbin, tomo.clustering_Nbin, start);
   // printf("Saving to: %s\n",filename);
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         if (ell[nl1]<like.lmax_kappacmb && ell[nl2]<like.lmax_shear){
            c_ng = cov_NG_kk_ss(ell[nl1],ell[nl2],z2,z3);
            if (nl1==nl2){
               c_g = cov_G_kk_ss(ell[nl1],dell[nl1],z2,z3);
            }
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+tomo.shear_Nbin)+nl1;
         j=like.Ncl*n2+nl2;
         fprintf(F1, "%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],0,0,z2,z3,c_g,c_ng);
      }
   }
   fclose(F1);
}

// ks_ks
void run_cov_ks_ks(char *OUTFILE, char *PATH, double *ell, double *dell, int zs1, int zs2,int start)
{
   int nl1,nl2,i,j, weight;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   // sprintf(filename,"%scov/%s_%s_cov_ksks_Nell%d_Ns%d_Ng%d_%d", PATH, survey.name, cmb.name, like.Ncl, tomo.shear_Nbin, tomo.clustering_Nbin, start);
   // printf("Saving to: %s\n",filename);
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   printf("Source bins for ks: %d, %d\n", zs1, zs2);
   for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         if (ell[nl1]<like.lmax_kappacmb && ell[nl2]<like.lmax_kappacmb) {
            c_ng = cov_NG_ks_ks(ell[nl1],ell[nl2],zs1,zs2);
         }
         if (nl1==nl2){
            c_g = cov_G_ks_ks(ell[nl1],dell[nl1], zs1, zs2);
         }
         if ((ell[nl1]>like.lmax_kappacmb || ell[nl2]>like.lmax_kappacmb) && zs2!=zs1){
            c_g = 0;
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+zs1)+nl1;
         j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+zs2)+nl2;
         fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],0,zs1,0,zs2,c_g,c_ng);
      }
   }
   fclose(F1);
}

// ks_ss
void run_cov_ks_ss(char *OUTFILE, char *PATH, double *ell, double *dell, int zs1, int n2, int start)
{
   int z2,z3,nl1,nl2,i,j,weight;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   z2 = Z1(n2); z3 = Z2(n2);
   printf("Source bin for ks: %d\n", zs1);
   printf("Bin for ss: %d (%d, %d)\n", n2, z2, z3);

   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         if (ell[nl1]<like.lmax_kappacmb && ell[nl2]<like.lmax_shear){
            c_ng = cov_NG_ks_ss(ell[nl1],ell[nl2],zs1,z2,z3);
            if (nl1==nl2){
               c_g = cov_G_ks_ss(ell[nl1],dell[nl1],zs1,z2,z3);
            }
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+zs1)+nl1;
         j=like.Ncl*n2+nl2;
         fprintf(F1, "%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],0,zs1,z2,z3,c_g,c_ng);
      }
   }
   fclose(F1);
}

// ll_kk
void run_cov_ll_kk(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int start)
{
   int i,j, weight;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   // zl1 = ZL(n1); zs1 = ZS(n1);
   printf("Bin for ll: %d \n", n1);
   for (int nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (int nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         weight = test_kmax(ell[nl1], n1);
         if (weight && ell[nl2]<like.lmax_kappacmb) {
            c_ng = cov_NG_gg_kk(ell[nl1],ell[nl2], n1, n1);
            if (nl1==nl2){
               c_g = cov_G_gg_kk(ell[nl1], dell[nl1], n1, n1);
            }
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+n1)+nl1;
         j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+tomo.shear_Nbin)+nl2;
         fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],n1,n1,0,0,c_g,c_ng);
      }
   }
   fclose(F1);
}

// ll_ks
void run_cov_ll_ks(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int zs2, int start)
{
   int i,j,weight;
   double c_ng, c_g;
   FILE *F1;
   char filename[300];
   sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
   F1 =fopen(filename,"w");
   // zl1 = ZL(n1); zs1 = ZS(n1);
   printf("Bin for ll: %d\n", n1);
   printf("Bin for ks: %d\n", zs2);
   for (int nl1 = 0; nl1 < like.Ncl; nl1 ++){
      for (int nl2 = 0; nl2 < like.Ncl; nl2 ++){
         c_ng = 0.; c_g = 0.;
         weight = test_kmax(ell[nl1], n1);
         if (weight && ell[nl2]<like.lmax_kappacmb) {
            if (test_zoverlap(n1, zs2)) {
               c_ng = cov_NG_gg_ks(ell[nl1],ell[nl2], n1, n1, zs2);
            }
            if (nl1==nl2){
               c_g = cov_G_gg_ks(ell[nl1], dell[nl1], n1, n1, zs2);
            }
         }
         i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+n1)+nl1;
         j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+tomo.clustering_Nbin+zs2)+nl2;
         fprintf(F1,"%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],n1,n1,0,zs2,c_g,c_ng);
      }
   }
   fclose(F1);
}

// ll_lk
void run_cov_ll_lk(char *OUTFILE, char *PATH, double *ell, double *dell, int n1, int zl2,int start)
{
  int z1,z2,zl,zs,nl1,nl2,i,j,weight;
  double c_ng, c_g;
  FILE *F1;
  char filename[300];
  sprintf(filename,"%s%s_%d",PATH,OUTFILE,start);
  F1 =fopen(filename,"w");
  z1 = n1; z2 = n1;
  printf("\nN_cl_1 = %d \n", n1);
  // zl = ZL(n2); zs = ZS(n2);
  zl = zl2;
  printf("N_tomo_2 = %d\n", zl2);
  for (nl1 = 0; nl1 < like.Ncl; nl1 ++){
    for (nl2 = 0; nl2 < like.Ncl; nl2 ++){
      c_ng = 0.; c_g = 0.;
      weight = test_kmax(ell[nl1],z1)*test_kmax(ell[nl2],zl);
      if (weight){
        if((z1 == zl)) {c_ng = cov_NG_gg_gk(ell[nl1],ell[nl2],z1,z2,zl);}
        if (nl1 == nl2){
          c_g =  cov_G_gg_gk(ell[nl1],dell[nl1],z1,z2,zl);
        }
      }
      i=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+n1)+nl1;
      j=like.Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra+tomo.clustering_Nbin+zl)+nl2;
      fprintf(F1, "%d %d %e %e %d %d %d %d %e %e\n",i,j,ell[nl1],ell[nl2],z1,z2,zl,0,c_g,c_ng);
    }
  }
  fclose(F1);
}

int main(int argc, char** argv)
{

  int i,l,m,n,o,s,p,nl1,t,k;
  char OUTFILE[400],filename[400],arg1[400],arg2[400];

  int N_scenarios=2;
  double area_table[2]={18000.0,2000.0};
  double nsource_table[2]={43.0,51.0};
  double nlens_table[2]={50.0,66.0};

  char survey_designation[2][200]={"WFIRSTwidexSO5","WFIRSTstdxSO5"};

  char source_zfile[2][400]={"zdistri_WFIRST_LSST_lensing_fine_bin","zdistri_WFIRST_LSST_lensing_fine_bin"};

#ifdef ONESAMPLE
  char lens_zfile[2][400]={"zdistri_WFIRST_LSST_lensing_fine_bin","zdistri_WFIRST_LSST_lensing_fine_bin"};
  nlens_table[0] = nsource_table[0];
  nlens_table[1] = nsource_table[1];
#else
  char lens_zfile[2][400]={"zdistri_WFIRST_LSST_clustering_fine_bin","zdistri_WFIRST_LSST_clustering_fine_bin"};
#endif

  int hit=atoi(argv[1]);
  Ntable.N_a=100;
  k=1;

  t = atoi(argv[2]);

  //RUN MODE setup
  init_cosmo_runmode("emu");
  // init_binning_fourier(20,30.0,3000.0,3000.0,21.0,10,10);
  init_binning_fourier(15,20.0,3000.0,3000.0,21.0,10,10);
  init_survey(survey_designation[t],nsource_table[t],nlens_table[t],area_table[t]);
  sprintf(arg1,"zdistris/%s",source_zfile[t]);
  sprintf(arg2,"zdistris/%s",lens_zfile[t]);
  init_galaxies(arg1,arg2,"none","none","source_std","WF_SN10");
  init_IA("none","GAMA");
  init_probes("6x2pt");

  init_cmb("so_Y5");

  //set l-bins for shear, ggl, clustering, clusterWL
  double logdl=(log(like.lmax)-log(like.lmin))/like.Ncl;
  double *ell, *dell, *ell_Cluster, *dell_Cluster;
  ell=create_double_vector(0,like.Ncl-1);
  dell=create_double_vector(0,like.Ncl-1);
  ell_Cluster=create_double_vector(0,Cluster.lbin-1);
  dell_Cluster=create_double_vector(0,Cluster.lbin-1);
  int j=0;
  for(i=0;i<like.Ncl;i++){
    ell[i]=exp(log(like.lmin)+(i+0.5)*logdl);
    dell[i]=exp(log(like.lmin)+(i+1)*logdl)-exp(log(like.lmin)+(i*logdl));
    if(ell[i]<like.lmax_shear) printf("%le\n",ell[i]);
  }

  printf("----------------------------------\n");
  sprintf(survey.name,"%s_area%le_ng%le_nl%le",survey_designation[t],survey.area,survey.n_gal,survey.n_lens);
  printf("area: %le n_source: %le n_lens: %le\n",survey.area,survey.n_gal,survey.n_lens);

  // sprintf(covparams.outdir,"/home/u17/timeifler/covparallel/");
#ifdef ONESAMPLE
  sprintf(covparams.outdir,"out_cov_wfirstxso_1sample/");
#else
  sprintf(covparams.outdir,"out_cov_wfirstxso/");
  //sprintf(covparams.outdir,"/halo_nobackup/cosmos/teifler/covparallel/");
#endif

  printf("----------------------------------\n");
  sprintf(OUTFILE,"%s_ssss_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.shear_Npowerspectra; l++){
    for (m=l;m<tomo.shear_Npowerspectra; m++){
      if(k==hit){
        sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
        run_cov_ss_ss(OUTFILE,covparams.outdir,ell,dell,l,m,k);
      }
      k=k+1;
      //printf("%d\n",k);
    }
  }

  sprintf(OUTFILE,"%s_lsls_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.ggl_Npowerspectra; l++){
    for (m=l;m<tomo.ggl_Npowerspectra; m++){
      if(k==hit){
        sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
        run_cov_ls_ls(OUTFILE,covparams.outdir,ell,dell,l,m,k);
      }
     //printf("%d\n",k);
      k=k+1;
    }
  }
  sprintf(OUTFILE,"%s_llll_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.clustering_Npowerspectra; l++){ //auto bins only for now!
    for (m=l;m<tomo.clustering_Npowerspectra; m++){
      if(k==hit){
        sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
        run_cov_ll_ll(OUTFILE,covparams.outdir,ell,dell,l,m,k);
      }
      k=k+1;
      //printf("%d %d %d\n",l,m,k);
    }
  }
  sprintf(OUTFILE,"%s_llss_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.clustering_Npowerspectra; l++){
    for (m=0;m<tomo.shear_Npowerspectra; m++){
      if(k==hit){
        sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
        run_cov_ll_ss(OUTFILE,covparams.outdir,ell,dell,l,m,k);
      }
      k=k+1;
      //printf("%d\n",k);
    }
  }
  sprintf(OUTFILE,"%s_llls_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.clustering_Npowerspectra; l++){
    for (m=0;m<tomo.ggl_Npowerspectra; m++){
      if(k==hit){
        sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
        run_cov_ll_ls(OUTFILE,covparams.outdir,ell,dell,l,m,k);
      }
      k=k+1;
      //printf("%d\n",k);
    }
  }
  sprintf(OUTFILE,"%s_lsss_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.ggl_Npowerspectra; l++){
    for (m=0;m<tomo.shear_Npowerspectra; m++){
      if(k==hit){
        sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
        run_cov_ls_ss(OUTFILE,covparams.outdir,ell,dell,l,m,k);
      }
      k=k+1;
      //printf("%d\n",k);
    }
  }

 // lk_lk
  sprintf(OUTFILE,"%s_lklk_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.clustering_Nbin; l++){
     for (m=l;m<tomo.clustering_Nbin; m++){
        if (k==hit){
          sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
          run_cov_lk_lk(OUTFILE,covparams.outdir,ell,dell,l,m,k);
        }
        k=k+1;
     }
  }

  printf("lklk %d\n",k);

  // lk_ls
  sprintf(OUTFILE,"%s_lkls_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.clustering_Nbin; l++){
     for (m=0;m<tomo.ggl_Npowerspectra; m++){
        if (k==hit){
          sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
          run_cov_lk_ls(OUTFILE,covparams.outdir,ell,dell,l,m,k);
        }
        k=k+1;
     }
  }
  printf("lkls %d\n",k);

  // lk_kk
  sprintf(OUTFILE,"%s_lkkk_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.clustering_Nbin; l++){
     if (k==hit){
        sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
        run_cov_lk_kk(OUTFILE,covparams.outdir,ell,dell,l,k);
     }
     // printf("%d\n",k);
     k=k+1;
  }
  printf("lkkk %d\n",k);

  // lk_ks
  sprintf(OUTFILE,"%s_lkks_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.clustering_Nbin; l++){
     for (m=0;m<tomo.shear_Nbin;m++) {
        if (k==hit){
          sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
          run_cov_lk_ks(OUTFILE,covparams.outdir,ell,dell,l,m,k);
        }
        // printf("%d\n",k);
        k=k+1;
     }
  }
  printf("lkks %d\n",k);

  // lk_ss
  sprintf(OUTFILE,"%s_lkss_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.clustering_Nbin; l++){
     for (m=0;m<tomo.shear_Npowerspectra; m++){
        if (k==hit){
          sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
          run_cov_lk_ss(OUTFILE,covparams.outdir,ell,dell,l,m,k);
        }
        k=k+1;
        // printf("%d\n",k);
     }
  }
  printf("lkss %d\n",k);

  // ls_kk
  sprintf(OUTFILE,"%s_lskk_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.ggl_Npowerspectra; l++){
     if (k==hit){
          sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
          run_cov_ls_kk(OUTFILE,covparams.outdir,ell,dell,l,k);
        }
    // printf("%d\n",k);
     k=k+1;
  }
  printf("lskk%d\n",k);

  // ls_ks
  sprintf(OUTFILE,"%s_lsks_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.ggl_Npowerspectra; l++){
     for (m=0;m<tomo.shear_Nbin;m++) {
        if (k==hit){
          sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
          run_cov_ls_ks(OUTFILE,covparams.outdir,ell,dell,l,m,k);
        }
        // printf("%d\n",k);
        k=k+1;
     }
  }
  printf("lsks %d\n",k);

  // kk_kk
  sprintf(OUTFILE,"%s_kkkk_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  if (k==hit){
    sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
    run_cov_kk_kk(OUTFILE,covparams.outdir,ell,dell,k);
  }
  // printf("%d\n",k);
  k=k+1;
  printf("kkkk %d\n",k);

  // kk_ks
  sprintf(OUTFILE,"%s_kkks_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.shear_Nbin; l++){
     if (k==hit){
        sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
        run_cov_kk_ks(OUTFILE,covparams.outdir,ell,dell,l,k);
     }
     // printf("%d\n",k);
     k=k+1;
  }
  printf("kkks %d\n",k);

  // kk_ss
  sprintf(OUTFILE,"%s_kkss_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.shear_Npowerspectra; l++){
     if (k==hit){
      sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
      run_cov_kk_ss(OUTFILE,covparams.outdir,ell,dell,l,k);
     }
     k=k+1;
     // printf("%d\n",k);
  }
  printf("kkss %d\n",k);

  // ks_ks
  sprintf(OUTFILE,"%s_ksks_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.shear_Nbin; l++){
     for (m=l;m<tomo.shear_Nbin; m++){
        if (k==hit){
          sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
          run_cov_ks_ks(OUTFILE,covparams.outdir,ell,dell,l,m,k);
        }
        // printf("%d\n",k);
        k=k+1;
     }
  }
  printf("ksks %d\n",k);

 // ks_ss
 sprintf(OUTFILE,"%s_ksss_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
 for (l=0;l<tomo.shear_Nbin; l++){
   for (m=0;m<tomo.shear_Npowerspectra; m++){
     if (k==hit){
        sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
        run_cov_ks_ss(OUTFILE,covparams.outdir,ell,dell,l,m,k);
     }
     k=k+1;
     // printf("%d\n",k);
    }
  }
  printf("ksss %d\n",k);

  // ll_kk
  sprintf(OUTFILE,"%s_llkk_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.clustering_Npowerspectra; l++){
     if (k==hit){
          sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
          run_cov_ll_kk(OUTFILE,covparams.outdir,ell,dell,l,k);
        }
    // printf("%d\n",k);
     k=k+1;
  }
  printf("llkk %d\n",k);

  // ll_ks
  sprintf(OUTFILE,"%s_llks_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.clustering_Npowerspectra; l++){
     for (m=0;m<tomo.shear_Nbin;m++) {
        if (k==hit){
          sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
          run_cov_ll_ks(OUTFILE,covparams.outdir,ell,dell,l,m,k);
        }
        // printf("%d\n",k);
        k=k+1;
     }
  }
  printf("llks %d\n",k);

  // ll_lk
  sprintf(OUTFILE,"%s_lllk_cov_Ncl%d_Ntomo%d",survey.name,like.Ncl,tomo.shear_Nbin);
  for (l=0;l<tomo.clustering_Npowerspectra; l++){
     for (m=0;m<tomo.clustering_Nbin;m++) {
        if (k==hit){
          sprintf(filename,"%s%s_%d",covparams.outdir,OUTFILE,k);
          run_cov_ll_lk(OUTFILE,covparams.outdir,ell,dell,l,m,k);
        }
        // printf("%d\n",k);
        k=k+1;
     }
  }
  printf("lllk %d\n",k);

  printf("number of cov blocks for parallelization: %d\n",k-1);
  printf("-----------------\n");
  printf("PROGRAM EXECUTED\n");
  printf("-----------------\n");
  return 0;
}


/* blas/gsl_blas.h
 *
 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

/*
 * Author:  G. Jungman
 */
#ifndef __GSL_BLAS_H__
#define __GSL_BLAS_H__

#include <gsl/gsl_vector.h>
#include <gsl/gsl_matrix.h>

#include <gsl/gsl_blas_types.h>
#include <gsl/gsl_types.h>

#undef __BEGIN_DECLS
#undef __END_DECLS
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS /* empty */
# define __END_DECLS /* empty */
#endif

__BEGIN_DECLS

/* ========================================================================
 * Level 1
 * ========================================================================
 */

GSL_EXPORT int gsl_blas_sdsdot (float alpha,
                                const gsl_vector_float * X,
                                const gsl_vector_float * Y,
                                float * result
                                );

GSL_EXPORT int gsl_blas_dsdot (const gsl_vector_float * X,
                               const gsl_vector_float * Y,
                               double * result
                               );

GSL_EXPORT int gsl_blas_sdot (const gsl_vector_float * X,
                              const gsl_vector_float * Y,
                              float * result
                              );

GSL_EXPORT int gsl_blas_ddot (const gsl_vector * X,
                              const gsl_vector * Y,
                              double * result
                              );

GSL_EXPORT int  gsl_blas_cdotu (const gsl_vector_complex_float * X,
                                const gsl_vector_complex_float * Y,
                                gsl_complex_float * dotu);

GSL_EXPORT int  gsl_blas_cdotc (const gsl_vector_complex_float * X,
                                const gsl_vector_complex_float * Y,
                                gsl_complex_float * dotc);

GSL_EXPORT int  gsl_blas_zdotu (const gsl_vector_complex * X,
                                const gsl_vector_complex * Y,
                                gsl_complex * dotu);

GSL_EXPORT int  gsl_blas_zdotc (const gsl_vector_complex * X,
                                const gsl_vector_complex * Y,
                                gsl_complex * dotc);

GSL_EXPORT float  gsl_blas_snrm2  (const gsl_vector_float * X);
GSL_EXPORT float  gsl_blas_sasum  (const gsl_vector_float * X);
GSL_EXPORT double gsl_blas_dnrm2  (const gsl_vector * X);
GSL_EXPORT double gsl_blas_dasum  (const gsl_vector * X);
GSL_EXPORT float  gsl_blas_scnrm2 (const gsl_vector_complex_float * X);
GSL_EXPORT float  gsl_blas_scasum (const gsl_vector_complex_float * X);
GSL_EXPORT double gsl_blas_dznrm2 (const gsl_vector_complex * X);
GSL_EXPORT double gsl_blas_dzasum (const gsl_vector_complex * X);

GSL_EXPORT CBLAS_INDEX_t gsl_blas_isamax (const gsl_vector_float * X);
GSL_EXPORT CBLAS_INDEX_t gsl_blas_idamax (const gsl_vector * X);
GSL_EXPORT CBLAS_INDEX_t gsl_blas_icamax (const gsl_vector_complex_float * X);
GSL_EXPORT CBLAS_INDEX_t gsl_blas_izamax (const gsl_vector_complex * X);

GSL_EXPORT int  gsl_blas_sswap (gsl_vector_float * X,
                                gsl_vector_float * Y);

GSL_EXPORT int  gsl_blas_scopy (const gsl_vector_float * X,
                                gsl_vector_float * Y);

GSL_EXPORT int  gsl_blas_saxpy (float alpha,
                                const gsl_vector_float * X,
                                gsl_vector_float * Y);

GSL_EXPORT int  gsl_blas_dswap (gsl_vector * X,
                                gsl_vector * Y);

GSL_EXPORT int  gsl_blas_dcopy (const gsl_vector * X,
                                gsl_vector * Y);

GSL_EXPORT int  gsl_blas_daxpy (double alpha,
                                const gsl_vector * X,
                                gsl_vector * Y);

GSL_EXPORT int  gsl_blas_cswap (gsl_vector_complex_float * X,
                                gsl_vector_complex_float * Y);

GSL_EXPORT int  gsl_blas_ccopy (const gsl_vector_complex_float * X,
                                gsl_vector_complex_float * Y);

GSL_EXPORT int  gsl_blas_caxpy (const gsl_complex_float alpha,
                                const gsl_vector_complex_float * X,
                                gsl_vector_complex_float * Y);

GSL_EXPORT int  gsl_blas_zswap (gsl_vector_complex * X,
                                gsl_vector_complex * Y);

GSL_EXPORT int  gsl_blas_zcopy (const gsl_vector_complex * X,
                                gsl_vector_complex * Y);

GSL_EXPORT int  gsl_blas_zaxpy (const gsl_complex alpha,
                                const gsl_vector_complex * X,
                                gsl_vector_complex * Y);

GSL_EXPORT int  gsl_blas_srotg (float a[], float b[], float c[], float s[]);

GSL_EXPORT int  gsl_blas_srotmg (float d1[], float d2[], float b1[], float b2, float P[]);

GSL_EXPORT int  gsl_blas_srot (gsl_vector_float * X,
                               gsl_vector_float * Y,
                               float c, float s);

GSL_EXPORT int  gsl_blas_srotm (gsl_vector_float * X,
                                gsl_vector_float * Y,
                                const float P[]);

GSL_EXPORT int  gsl_blas_drotg (double a[], double b[], double c[], double s[]);

GSL_EXPORT int  gsl_blas_drotmg (double d1[], double d2[], double b1[],
                                 double b2, double P[]);

GSL_EXPORT int  gsl_blas_drot (gsl_vector * X,
                               gsl_vector * Y,
                               const double c, const double s);

GSL_EXPORT int  gsl_blas_drotm (gsl_vector * X,
                                gsl_vector * Y,
                                const double P[]);

GSL_EXPORT void gsl_blas_sscal  (float  alpha, gsl_vector_float * X);
GSL_EXPORT void gsl_blas_dscal  (double alpha, gsl_vector * X);
GSL_EXPORT void gsl_blas_cscal  (const gsl_complex_float alpha, gsl_vector_complex_float * X);
GSL_EXPORT void gsl_blas_zscal  (const gsl_complex alpha, gsl_vector_complex * X);
GSL_EXPORT void gsl_blas_csscal (float  alpha, gsl_vector_complex_float * X);
GSL_EXPORT void gsl_blas_zdscal (double alpha, gsl_vector_complex * X);

/* ===========================================================================
 * Level 2
 * ===========================================================================
 */

/*
 * Routines with standard 4 prefixes (S, D, C, Z)
 */
GSL_EXPORT int  gsl_blas_sgemv (CBLAS_TRANSPOSE_t TransA,
                                float alpha,
                                const gsl_matrix_float * A,
                                const gsl_vector_float * X,
                                float beta,
                                gsl_vector_float * Y);

GSL_EXPORT int  gsl_blas_strmv (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t TransA, CBLAS_DIAG_t Diag,
                                const gsl_matrix_float * A,
                                gsl_vector_float * X);

GSL_EXPORT int  gsl_blas_strsv (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t TransA, CBLAS_DIAG_t Diag,
                                const gsl_matrix_float * A,
                                gsl_vector_float * X);

GSL_EXPORT int  gsl_blas_dgemv (CBLAS_TRANSPOSE_t TransA,
                                double alpha,
                                const gsl_matrix * A,
                                const gsl_vector * X,
                                double beta,
                                gsl_vector * Y);

GSL_EXPORT int  gsl_blas_dtrmv (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t TransA, CBLAS_DIAG_t Diag,
                                const gsl_matrix * A,
                                gsl_vector * X);

GSL_EXPORT int  gsl_blas_dtrsv (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t TransA, CBLAS_DIAG_t Diag,
                                const gsl_matrix * A,
                                gsl_vector * X);

GSL_EXPORT int  gsl_blas_cgemv (CBLAS_TRANSPOSE_t TransA,
                                const gsl_complex_float alpha,
                                const gsl_matrix_complex_float * A,
                                const gsl_vector_complex_float * X,
                                const gsl_complex_float beta,
                                gsl_vector_complex_float * Y);

GSL_EXPORT int  gsl_blas_ctrmv (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t TransA, CBLAS_DIAG_t Diag,
                                const gsl_matrix_complex_float * A,
                                gsl_vector_complex_float * X);

GSL_EXPORT int  gsl_blas_ctrsv (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t TransA, CBLAS_DIAG_t Diag,
                                const gsl_matrix_complex_float * A,
                                gsl_vector_complex_float * X);

GSL_EXPORT int  gsl_blas_zgemv (CBLAS_TRANSPOSE_t TransA,
                                const gsl_complex alpha,
                                const gsl_matrix_complex * A,
                                const gsl_vector_complex * X,
                                const gsl_complex beta,
                                gsl_vector_complex * Y);

GSL_EXPORT int  gsl_blas_ztrmv (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t TransA, CBLAS_DIAG_t Diag,
                                const gsl_matrix_complex * A,
                                gsl_vector_complex * X);

GSL_EXPORT int  gsl_blas_ztrsv (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t TransA, CBLAS_DIAG_t Diag,
                                const gsl_matrix_complex * A,
                                gsl_vector_complex *X);

/*
 * Routines with S and D prefixes only
 */
GSL_EXPORT int  gsl_blas_ssymv (CBLAS_UPLO_t Uplo,
                                float alpha,
                                const gsl_matrix_float * A,
                                const gsl_vector_float * X,
                                float beta,
                                gsl_vector_float * Y);

GSL_EXPORT int  gsl_blas_sger (float alpha,
                               const gsl_vector_float * X,
                               const gsl_vector_float * Y,
                               gsl_matrix_float * A);

GSL_EXPORT int  gsl_blas_ssyr (CBLAS_UPLO_t Uplo,
                               float alpha,
                               const gsl_vector_float * X,
                               gsl_matrix_float * A);

GSL_EXPORT int  gsl_blas_ssyr2 (CBLAS_UPLO_t Uplo,
                                float alpha,
                                const gsl_vector_float * X,
                                const gsl_vector_float * Y,
                                gsl_matrix_float * A);

GSL_EXPORT int  gsl_blas_dsymv (CBLAS_UPLO_t Uplo,
                                double alpha,
                                const gsl_matrix * A,
                                const gsl_vector * X,
                                double beta,
                                gsl_vector * Y);

GSL_EXPORT int  gsl_blas_dger (double alpha,
                               const gsl_vector * X,
                               const gsl_vector * Y,
                               gsl_matrix * A);

GSL_EXPORT int  gsl_blas_dsyr (CBLAS_UPLO_t Uplo,
                               double alpha,
                               const gsl_vector * X,
                               gsl_matrix * A);

GSL_EXPORT int  gsl_blas_dsyr2 (CBLAS_UPLO_t Uplo,
                                double alpha,
                                const gsl_vector * X,
                                const gsl_vector * Y,
                                gsl_matrix * A);

/*
 * Routines with C and Z prefixes only
 */

GSL_EXPORT int  gsl_blas_chemv (CBLAS_UPLO_t Uplo,
                                const gsl_complex_float alpha,
                                const gsl_matrix_complex_float * A,
                                const gsl_vector_complex_float * X,
                                const gsl_complex_float beta,
                                gsl_vector_complex_float * Y);

GSL_EXPORT int  gsl_blas_cgeru (const gsl_complex_float alpha,
                                const gsl_vector_complex_float * X,
                                const gsl_vector_complex_float * Y,
                                gsl_matrix_complex_float * A);

GSL_EXPORT int  gsl_blas_cgerc (const gsl_complex_float alpha,
                                const gsl_vector_complex_float * X,
                                const gsl_vector_complex_float * Y,
                                gsl_matrix_complex_float * A);

GSL_EXPORT int  gsl_blas_cher (CBLAS_UPLO_t Uplo,
                              float alpha,
                              const gsl_vector_complex_float * X,
                              gsl_matrix_complex_float * A);

GSL_EXPORT int  gsl_blas_cher2 (CBLAS_UPLO_t Uplo,
                                const gsl_complex_float alpha,
                                const gsl_vector_complex_float * X,
                                const gsl_vector_complex_float * Y,
                                gsl_matrix_complex_float * A);

GSL_EXPORT int  gsl_blas_zhemv (CBLAS_UPLO_t Uplo,
                                const gsl_complex alpha,
                                const gsl_matrix_complex * A,
                                const gsl_vector_complex * X,
                                const gsl_complex beta,
                                gsl_vector_complex * Y);

GSL_EXPORT int  gsl_blas_zgeru (const gsl_complex alpha,
                                const gsl_vector_complex * X,
                                const gsl_vector_complex * Y,
                                gsl_matrix_complex * A);

GSL_EXPORT int  gsl_blas_zgerc (const gsl_complex alpha,
                                const gsl_vector_complex * X,
                                const gsl_vector_complex * Y,
                                gsl_matrix_complex * A);

GSL_EXPORT int  gsl_blas_zher (CBLAS_UPLO_t Uplo,
                              double alpha,
                              const gsl_vector_complex * X,
                              gsl_matrix_complex * A);

GSL_EXPORT int  gsl_blas_zher2 (CBLAS_UPLO_t Uplo,
                                const gsl_complex alpha,
                                const gsl_vector_complex * X,
                                const gsl_vector_complex * Y,
                                gsl_matrix_complex * A);

/*
 * ===========================================================================
 * Prototypes for level 3 BLAS
 * ===========================================================================
 */

/*
 * Routines with standard 4 prefixes (S, D, C, Z)
 */
GSL_EXPORT int  gsl_blas_sgemm (CBLAS_TRANSPOSE_t TransA,
                                CBLAS_TRANSPOSE_t TransB,
                                float alpha,
                                const gsl_matrix_float * A,
                                const gsl_matrix_float * B,
                                float beta,
                                gsl_matrix_float * C);

GSL_EXPORT int  gsl_blas_ssymm (CBLAS_SIDE_t Side, CBLAS_UPLO_t Uplo,
                                float alpha,
                                const gsl_matrix_float * A,
                                const gsl_matrix_float * B,
                                float beta,
                                gsl_matrix_float * C);

GSL_EXPORT int  gsl_blas_ssyrk (CBLAS_UPLO_t Uplo, CBLAS_TRANSPOSE_t Trans,
                                float alpha,
                                const gsl_matrix_float * A,
                                float beta,
                                gsl_matrix_float * C);

GSL_EXPORT int  gsl_blas_ssyr2k (CBLAS_UPLO_t Uplo, CBLAS_TRANSPOSE_t Trans,
                                 float alpha,
                                 const gsl_matrix_float * A,
                                 const gsl_matrix_float * B,
                                 float beta,
                                 gsl_matrix_float * C);

GSL_EXPORT int  gsl_blas_strmm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo, CBLAS_TRANSPOSE_t TransA,
                                CBLAS_DIAG_t Diag,
                                float alpha,
                                const gsl_matrix_float * A,
                                gsl_matrix_float * B);

GSL_EXPORT int  gsl_blas_strsm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo, CBLAS_TRANSPOSE_t TransA,
                                CBLAS_DIAG_t Diag,
                                float alpha,
                                const gsl_matrix_float * A,
                                gsl_matrix_float * B);

GSL_EXPORT int  gsl_blas_dgemm (CBLAS_TRANSPOSE_t TransA,
                                CBLAS_TRANSPOSE_t TransB,
                                double alpha,
                                const gsl_matrix * A,
                                const gsl_matrix * B,
                                double beta,
                                gsl_matrix * C);

GSL_EXPORT int  gsl_blas_dsymm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo,
                                double alpha,
                                const gsl_matrix * A,
                                const gsl_matrix * B,
                                double beta,
                                gsl_matrix * C);

GSL_EXPORT int  gsl_blas_dsyrk (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t Trans,
                                double alpha,
                                const gsl_matrix * A,
                                double beta,
                                gsl_matrix * C);

GSL_EXPORT int  gsl_blas_dsyr2k (CBLAS_UPLO_t Uplo,
                                 CBLAS_TRANSPOSE_t Trans,
                                 double alpha,
                                 const  gsl_matrix * A,
                                 const  gsl_matrix * B,
                                 double beta,
                                 gsl_matrix * C);

GSL_EXPORT int  gsl_blas_dtrmm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo, CBLAS_TRANSPOSE_t TransA,
                                CBLAS_DIAG_t Diag,
                                double alpha,
                                const gsl_matrix * A,
                                gsl_matrix * B);

GSL_EXPORT int  gsl_blas_dtrsm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo, CBLAS_TRANSPOSE_t TransA,
                                CBLAS_DIAG_t Diag,
                                double alpha,
                                const gsl_matrix * A,
                                gsl_matrix * B);

GSL_EXPORT int  gsl_blas_cgemm (CBLAS_TRANSPOSE_t TransA,
                                CBLAS_TRANSPOSE_t TransB,
                                const gsl_complex_float alpha,
                                const gsl_matrix_complex_float * A,
                                const gsl_matrix_complex_float * B,
                                const gsl_complex_float beta,
                                gsl_matrix_complex_float * C);

GSL_EXPORT int  gsl_blas_csymm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo,
                                const gsl_complex_float alpha,
                                const gsl_matrix_complex_float * A,
                                const gsl_matrix_complex_float * B,
                                const gsl_complex_float beta,
                                gsl_matrix_complex_float * C);

GSL_EXPORT int  gsl_blas_csyrk (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t Trans,
                                const gsl_complex_float alpha,
                                const gsl_matrix_complex_float * A,
                                const gsl_complex_float beta,
                                gsl_matrix_complex_float * C);

GSL_EXPORT int  gsl_blas_csyr2k (CBLAS_UPLO_t Uplo,
                                 CBLAS_TRANSPOSE_t Trans,
                                 const gsl_complex_float alpha,
                                 const gsl_matrix_complex_float * A,
                                 const gsl_matrix_complex_float * B,
                                 const gsl_complex_float beta,
                                 gsl_matrix_complex_float * C);

GSL_EXPORT int  gsl_blas_ctrmm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo, CBLAS_TRANSPOSE_t TransA,
                                CBLAS_DIAG_t Diag,
                                const gsl_complex_float alpha,
                                const gsl_matrix_complex_float * A,
                                gsl_matrix_complex_float * B);

GSL_EXPORT int  gsl_blas_ctrsm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo, CBLAS_TRANSPOSE_t TransA,
                                CBLAS_DIAG_t Diag,
                                const gsl_complex_float alpha,
                                const gsl_matrix_complex_float * A,
                                gsl_matrix_complex_float * B);

GSL_EXPORT int  gsl_blas_zgemm (CBLAS_TRANSPOSE_t TransA,
                                CBLAS_TRANSPOSE_t TransB,
                                const gsl_complex alpha,
                                const gsl_matrix_complex * A,
                                const gsl_matrix_complex * B,
                                const gsl_complex beta,
                                gsl_matrix_complex * C);

GSL_EXPORT int  gsl_blas_zsymm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo,
                                const gsl_complex alpha,
                                const gsl_matrix_complex * A,
                                const gsl_matrix_complex * B,
                                const gsl_complex beta,
                                gsl_matrix_complex * C);

GSL_EXPORT int  gsl_blas_zsyrk (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t Trans,
                                const gsl_complex alpha,
                                const gsl_matrix_complex * A,
                                const gsl_complex beta,
                                gsl_matrix_complex * C);

GSL_EXPORT int  gsl_blas_zsyr2k (CBLAS_UPLO_t Uplo,
                                 CBLAS_TRANSPOSE_t Trans,
                                 const gsl_complex alpha,
                                 const gsl_matrix_complex * A,
                                 const gsl_matrix_complex * B,
                                 const gsl_complex beta,
                                 gsl_matrix_complex *C);

GSL_EXPORT int  gsl_blas_ztrmm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo, CBLAS_TRANSPOSE_t TransA,
                                CBLAS_DIAG_t Diag,
                                const gsl_complex alpha,
                                const gsl_matrix_complex * A,
                                gsl_matrix_complex * B);

GSL_EXPORT int  gsl_blas_ztrsm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo, CBLAS_TRANSPOSE_t TransA,
                                CBLAS_DIAG_t Diag,
                                const gsl_complex alpha,
                                const gsl_matrix_complex * A,
                                gsl_matrix_complex * B);

/*
 * Routines with prefixes C and Z only
 */
GSL_EXPORT int  gsl_blas_chemm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo,
                                const gsl_complex_float alpha,
                                const gsl_matrix_complex_float * A,
                                const gsl_matrix_complex_float * B,
                                const gsl_complex_float beta,
                                gsl_matrix_complex_float * C);

GSL_EXPORT int  gsl_blas_cherk (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t Trans,
                                float alpha,
                                const gsl_matrix_complex_float * A,
                                float beta,
                                gsl_matrix_complex_float * C);

GSL_EXPORT int  gsl_blas_cher2k (CBLAS_UPLO_t Uplo,
                                 CBLAS_TRANSPOSE_t Trans,
                                 const gsl_complex_float alpha,
                                 const gsl_matrix_complex_float * A,
                                 const gsl_matrix_complex_float * B,
                                 float beta,
                                 gsl_matrix_complex_float * C);

GSL_EXPORT int  gsl_blas_zhemm (CBLAS_SIDE_t Side,
                                CBLAS_UPLO_t Uplo,
                                const gsl_complex alpha,
                                const gsl_matrix_complex * A,
                                const gsl_matrix_complex * B,
                                const gsl_complex beta,
                                gsl_matrix_complex * C);

GSL_EXPORT int  gsl_blas_zherk (CBLAS_UPLO_t Uplo,
                                CBLAS_TRANSPOSE_t Trans,
                                double alpha,
                                const gsl_matrix_complex * A,
                                double beta,
                                gsl_matrix_complex * C);

GSL_EXPORT int  gsl_blas_zher2k (CBLAS_UPLO_t Uplo,
                                 CBLAS_TRANSPOSE_t Trans,
                                 const gsl_complex alpha,
                                 const gsl_matrix_complex * A,
                                 const gsl_matrix_complex * B,
                                 double beta,
                                 gsl_matrix_complex * C);

__END_DECLS

#endif /* __GSL_BLAS_H__ */


#include <math.h>
#include <stdlib.h>
#if !defined(__APPLE__)
#include <malloc.h>
#endif
#include <stdio.h>
#include <assert.h>
#include <time.h>
#include <string.h>

#include <fftw3.h>

#include <gsl/gsl_errno.h>
#include <gsl/gsl_sf_erf.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_spline.h>
#include <gsl/gsl_sf_gamma.h>
#include <gsl/gsl_sf_legendre.h>
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_eigen.h>
#include <gsl/gsl_sf_expint.h>
#include <gsl/gsl_deriv.h>
#include <gsl/gsl_interp2d.h>
#include <gsl/gsl_spline2d.h>

#include "../cosmolike_core/theory/basics.c"
#include "../cosmolike_core/theory/structs.c"
#include "../cosmolike_core/theory/parameters.c"
#include "../cosmolike_core/emu17/P_cb/emu.c"
#include "../cosmolike_core/theory/recompute.c"
#include "../cosmolike_core/theory/cosmo3D.c"
#include "../cosmolike_core/theory/redshift_spline.c"
#include "../cosmolike_core/theory/halo.c"
#include "../cosmolike_core/theory/HOD.c"
#include "../cosmolike_core/theory/pt.c"
#include "../cosmolike_core/theory/cosmo2D_fourier.c"
#include "../cosmolike_core/theory/IA.c"
#include "../cosmolike_core/theory/cluster.c"
#include "../cosmolike_core/theory/BAO.c"
#include "../cosmolike_core/theory/external_prior.c"
#include "../cosmolike_core/theory/init_baryon.c"
#include "init_DESxPlanck.c"

// Naming convention:
// g = galaxy positions ("g" as in "galaxy")
// k = kappa CMB ("k" as in "kappa")
// s = kappa from source galaxies ("s" as in "shear")
// And alphabetical order

typedef double (*C_tomo_pointer)(double l, int n1, int n2);
void twopoint_via_hankel(double **xi, double *logthetamin, double *logthetamax, C_tomo_pointer C_tomo, int ni, int nj, int N_Bessel);

#include "../cosmolike_core/theory/CMBxLSS_fourier.c"

typedef struct input_nuisance_params_des {
    double bias[10];
    // double bias2[10];
    double b_mag[10];
    double source_z_bias[10];
    double lens_z_bias[10];
    double shear_m[10];
    double A_ia;
    double eta_ia;
    // double bary[3];
} input_nuisance_params_des;

typedef struct input_cosmo_params_des {
    double omega_m;
    double sigma_8;
    double n_s;
    double w0;
    double wa;
    double omega_b;
    double h0;
    double MGSigma;
    double MGmu;
} input_cosmo_params_des;

double C_shear_tomo_sys(double ell,int z1,int z2);
double C_cgl_tomo_sys(double ell_Cluster,int zl,int nN, int zs);
double C_gl_tomo_sys(double ell,int zl,int zs);
double C_ks_sys(double ell, int zs);
void set_data_shear(int Ncl, double *ell, double *data, int start);
void set_data_ggl(int Ncl, double *ell, double *data, int start);
void set_data_clustering(int Ncl, double *ell, double *data, int start);
void set_data_gk(double *ell, double *data, int start);
void set_data_ks(double *ell, double *data, int start);
void set_data_kk(double *ell, double *data, int start);
void compute_data_vector(char *details, double OMM, double S8, double NS, double W0,double WA, double OMB, double H0, double MGSigma, double MGmu, double B1, double B2, double B3, double B4,double B5, double B6, double B7, double B8, double B9, double B10, double BMAG1, double BMAG2, double BMAG3, double BMAG4,double BMAG5, double BMAG6, double BMAG7, double BMAG8, double BMAG9, double BMAG10, double SP1, double SP2, double SP3, double SP4, double SP5,double SP6, double SP7, double SP8, double SP9, double SP10, double CP1, double CP2, double CP3, double CP4, double CP5, double CP6, double CP7, double CP8, double CP9, double CP10, double M1, double M2, double M3, double M4, double M5, double M6, double M7, double M8, double M9, double M10, double A_ia, double eta_ia);
double log_multi_like(double OMM, double S8, double NS, double W0,double WA, double OMB, double H0, double MGSigma, double MGmu, double B1, double B2, double B3, double B4,double B5, double B6, double B7, double B8, double B9, double B10, double BMAG1, double BMAG2, double BMAG3, double BMAG4,double BMAG5, double BMAG6, double BMAG7, double BMAG8, double BMAG9, double BMAG10, double SP1, double SP2, double SP3, double SP4, double SP5, double SP6, double SP7, double SP8, double SP9, double SP10, double CP1, double CP2, double CP3, double CP4, double CP5, double CP6, double CP7, double CP8, double CP9, double CP10, double M1, double M2, double M3, double M4, double M5, double M6, double M7, double M8, double M9, double M10, double A_ia, double eta_ia);
void write_datavector_wrapper(char *details, input_cosmo_params_des ic, input_nuisance_params_des in);
double log_like_wrapper(input_cosmo_params_des ic, input_nuisance_params_des in);
int get_N_tomo_shear(void);
int get_N_tomo_clustering(void);
int get_N_ggl(void);
int get_N_ell(void);

int get_N_tomo_shear(void){
  return tomo.shear_Nbin;
}
int get_N_tomo_clustering(void){
  return tomo.clustering_Nbin;
}
int get_N_ggl(void){
  return tomo.ggl_Npowerspectra;
}
int get_N_ell(void){
  return like.Ncl;
}

double C_shear_tomo_sys(double ell, int z1, int z2)
{
  double C;
  // C= C_shear_tomo_nointerp(ell,z1,z2);
  // if(like.IA==1) C+=C_II_nointerp(ell,z1,z2)+C_GI_nointerp(ell,z1,z2);

  // if(like.IA!=1) C= C_shear_tomo_nointerp(ell,z1,z2);
  // //if(like.IA==1) C= C_shear_shear_IA(ell,z1,z2);
  // if(like.IA==1) C = C_shear_tomo_nointerp(ell,z1,z2)+C_II_nointerp(ell,z1,z2)+C_GI_nointerp(ell,z1,z2);
  // if(like.IA==2) C += C_II_lin_nointerp(ell,z1,z2)+C_GI_lin_nointerp(ell,z1,z2);
  if(like.IA==4){C = C_shear_shear_IA_tab(ell,z1,z2);}
  else{printf("only support IA==4!\n");exit(1);}
  if(like.shearcalib==1) C *=(1.0+nuisance.shear_calibration_m[z1])*(1.0+nuisance.shear_calibration_m[z2]);
  //printf("%le %d %d %le\n",ell,z1,z2,C_shear_tomo_nointerp(ell,z1,z2)+C_II_JB_nointerp(ell,z1,z2)+C_GI_JB_nointerp(ell,z1,z2));
return C;
}

double C_gl_tomo_sys(double ell,int zl,int zs)
{
  double C;
  // C=C_gl_tomo_nointerp(ell,zl,zs);
  // if(like.IA==1) C += C_gI_nointerp(ell,zl,zs);

  // if(like.IA!=1) C=C_gl_tomo_nointerp(ell,zl,zs);
  // if(like.IA==1) C = C_ggl_IA(ell,zl,zs);
  // if(like.IA==2) C += C_gI_lin_nointerp(ell,zl,zs);
  if(like.IA==4){C = C_ggl_IA_tab(ell,zl,zs);}
  else{printf("only support IA==4!\n");exit(1);}
  if(like.shearcalib==1) C *=(1.0+nuisance.shear_calibration_m[zs]);
return C;
}

double C_cgl_tomo_sys(double ell_Cluster, int zl,int nN, int zs)
{
  double C;
  C=C_cgl_tomo_nointerp(ell_Cluster,zl,nN,zs);
  //if(like.IA!=0) C +=
  if(like.shearcalib==1) C *=(1.0+nuisance.shear_calibration_m[zs]);
return C;
}

double C_ks_sys(double ell, int zs)
{
   double C;
   C = C_ks(ell,zs);
   if(like.shearcalib==1) C *=(1.0+nuisance.shear_calibration_m[zs]);
   return C;
}

void set_data_shear(int Ncl, double *ell, double *data, int start)
{
  int i,z1,z2,nz;
  double a;
  for (nz = 0; nz < tomo.shear_Npowerspectra; nz++){
    z1 = Z1(nz); z2 = Z2(nz);
    for (i = 0; i < Ncl; i++){
      // if (ell[i] < like.lmax_shear){ data[Ncl*nz+i] = C_shear_tomo_sys(ell[i],z1,z2);}
      if (mask(Ncl*nz+i)){ data[Ncl*nz+i] = C_shear_tomo_sys(ell[i],z1,z2);}
      else {data[Ncl*nz+i] = 0.;}
    }
  }
}

void set_data_ggl(int Ncl, double *ell, double *data, int start)
{
  int i, zl,zs,nz;
  for (nz = 0; nz < tomo.ggl_Npowerspectra; nz++){
    zl = ZL(nz); zs = ZS(nz);
    for (i = 0; i < Ncl; i++){
      // if (test_kmax(ell[i],zl)){
      if (mask(start+(Ncl*nz)+i)){
        data[start+(Ncl*nz)+i] = C_gl_tomo_sys(ell[i],zl,zs);
      }
      else{
        data[start+(Ncl*nz)+i] = 0.;
      }
    }
  }
}

void set_data_clustering(int Ncl, double *ell, double *data, int start){
  int i, nz;
  for (nz = 0; nz < tomo.clustering_Npowerspectra; nz++){
    //printf("%d %e %e\n",nz, gbias.b[nz][1],pf_photoz(gbias.b[nz][1],nz));
    for (i = 0; i < Ncl; i++){
      // if (test_kmax(ell[i],nz))
      if (mask(start+(Ncl*nz)+i)) {
        data[start+(Ncl*nz)+i] = C_cl_tomo_nointerp(ell[i],nz,nz);
      }
      else{data[start+(Ncl*nz)+i] = 0.;}
      //printf("%d %d %le %le\n",nz,nz,ell[i],data[Ncl*(tomo.shear_Npowerspectra+tomo.ggl_Npowerspectra + nz)+i]);
    }
  }
}

void set_data_gk(double *ell, double *data, int start)
{
   for (int nz=0; nz<tomo.clustering_Nbin; nz++){
      for (int i=0; i<like.Ncl; i++){
         // if (ell[i]<like.lmax_kappacmb && test_kmax(ell[i],nz)){
         if (mask(start+(like.Ncl*nz)+i)) {
            data[start+(like.Ncl*nz)+i] = C_gk(ell[i],nz);
         }
         else{
            data[start+(like.Ncl*nz)+i] = 0.;
         }
      }
   }
}

void set_data_ks(double *ell, double *data, int start)
{
   for (int nz=0; nz<tomo.shear_Nbin; nz++){
      for (int i=0; i<like.Ncl; i++){
         // if (ell[i]<like.lmax_kappacmb) {
         if (mask(start+(like.Ncl*nz)+i)) {
            data[start+(like.Ncl*nz)+i] = C_ks_sys(ell[i],nz);
         }
         else{
            data[start+(like.Ncl*nz)+i] = 0.;
         }
      }
   }
}

void set_data_kk(double *ell, double *data, int start)
{
   for (int i=0; i<like.Ncl; i++){
      // if (ell[i]<like.lmax_kappacmb){
      if (mask(start+i)) {
         data[start+i] = C_kk(ell[i]);
      }
      else{
         data[start+i] = 0.;
      }
   }
}

int set_cosmology_params(double OMM, double S8, double NS, double W0,double WA, double OMB, double H0, double MGSigma, double MGmu)
{
  cosmology.Omega_m=OMM;
  cosmology.Omega_v= 1.0-cosmology.Omega_m;
  cosmology.sigma_8=S8;
  cosmology.n_spec= NS;
  cosmology.w0=W0;
  cosmology.wa=WA;
  cosmology.omb=OMB;
  cosmology.h0=H0;
  cosmology.MGSigma=MGSigma;
  cosmology.MGmu=MGmu;

  if (cosmology.Omega_m < 0.05 || cosmology.Omega_m > 0.6) return 0;
  if (cosmology.omb < 0.04 || cosmology.omb > 0.055) return 0;
  if (cosmology.sigma_8 < 0.5 || cosmology.sigma_8 > 1.1) return 0;
  if (cosmology.n_spec < 0.84 || cosmology.n_spec > 1.06) return 0;
  if (cosmology.w0 < -2.1 || cosmology.w0 > -0.0) return 0;
  if (cosmology.wa < -2.6 || cosmology.wa > 2.6) return 0;
  if (cosmology.h0 < 0.4 || cosmology.h0 > 0.9) return 0;
  //CH BEGINS
  //CH: to use for running planck15_BA0_w0_wa prior alone)
  //printf("like_fourier.c from WFIRST_forecasts: cosmology bounds set for running with planck15_BA0_w0_wa prior\n");
  //if (cosmology.Omega_m < 0.05 || cosmology.Omega_m > 0.6) return 0;
  //if (cosmology.omb < 0.01 || cosmology.omb > 0.1) return 0;
  //if (cosmology.sigma_8 < 0.5 || cosmology.sigma_8 > 1.1) return 0;
  //if (cosmology.n_spec < 0.84 || cosmology.n_spec > 1.06) return 0;
  //if (cosmology.w0 < -2.1 || cosmology.w0 > 1.5) return 0;
  //if (cosmology.wa < -5.0 || cosmology.wa > 2.6) return 0;
  //if (cosmology.h0 < 0.3 || cosmology.h0 > 0.9) return 0;
  //CH ENDS
  return 1;
}

void set_nuisance_shear_calib(double M1, double M2, double M3, double M4, double M5, double M6, double M7, double M8, double M9, double M10)
{
  nuisance.shear_calibration_m[0] = M1;
  nuisance.shear_calibration_m[1] = M2;
  nuisance.shear_calibration_m[2] = M3;
  nuisance.shear_calibration_m[3] = M4;
  nuisance.shear_calibration_m[4] = M5;
  nuisance.shear_calibration_m[5] = M6;
  nuisance.shear_calibration_m[6] = M7;
  nuisance.shear_calibration_m[7] = M8;
  nuisance.shear_calibration_m[8] = M9;
  nuisance.shear_calibration_m[9] = M10;
}

int set_nuisance_shear_photoz(double SP1,double SP2,double SP3,double SP4,double SP5,double SP6,double SP7,double SP8,double SP9,double SP10)
{
  int i;
  nuisance.bias_zphot_shear[0]=SP1;
  nuisance.bias_zphot_shear[1]=SP2;
  nuisance.bias_zphot_shear[2]=SP3;
  nuisance.bias_zphot_shear[3]=SP4;
  nuisance.bias_zphot_shear[4]=SP5;
  nuisance.bias_zphot_shear[5]=SP6;
  nuisance.bias_zphot_shear[6]=SP7;
  nuisance.bias_zphot_shear[7]=SP8;
  nuisance.bias_zphot_shear[8]=SP9;
  nuisance.bias_zphot_shear[9]=SP10;

  // for (i=0;i<tomo.shear_Nbin; i++){
  //   nuisance.sigma_zphot_shear[i]=SPS1;
  //   if (nuisance.sigma_zphot_shear[i]<0.0001) return 0;
  // }
  return 1;
}

int set_nuisance_clustering_photoz(double CP1,double CP2,double CP3,double CP4,double CP5,double CP6,double CP7,double CP8,double CP9,double CP10)
{
  int i;
  nuisance.bias_zphot_clustering[0]=CP1;
  nuisance.bias_zphot_clustering[1]=CP2;
  nuisance.bias_zphot_clustering[2]=CP3;
  nuisance.bias_zphot_clustering[3]=CP4;
  nuisance.bias_zphot_clustering[4]=CP5;
  nuisance.bias_zphot_clustering[5]=CP6;
  nuisance.bias_zphot_clustering[6]=CP7;
  nuisance.bias_zphot_clustering[7]=CP8;
  nuisance.bias_zphot_clustering[8]=CP9;
  nuisance.bias_zphot_clustering[9]=CP10;

  // for (i=0;i<tomo.clustering_Nbin; i++){
  //   nuisance.sigma_zphot_clustering[i]=CPS1;
  //   if (nuisance.sigma_zphot_clustering[i]<0.0001) return 0;
  // }
  return 1;
}

int set_nuisance_ia(double A_ia, double eta_ia)
{
  nuisance.A_ia=A_ia;
  nuisance.eta_ia=eta_ia;
  nuisance.oneplusz0_ia = 1.62;
  if (nuisance.A_ia < 0.0 || nuisance.A_ia > 10.0) return 0;
  if (nuisance.eta_ia < -10.0 || nuisance.eta_ia> 10.0) return 0;
return 1;
}

// int set_nuisance_ia(double A_ia, double beta_ia, double eta_ia, double eta_ia_highz, double LF_alpha, double LF_P, double LF_Q, double LF_red_alpha, double LF_red_P, double LF_red_Q)
// {
//   nuisance.A_ia=A_ia;
//   nuisance.beta_ia=beta_ia;
//   nuisance.eta_ia=eta_ia;
//   nuisance.eta_ia_highz=eta_ia_highz;
//   nuisance.LF_alpha=LF_alpha;
//   nuisance.LF_P=LF_P;
//   nuisance.LF_Q=LF_Q;
//   nuisance.LF_red_alpha=LF_red_alpha;
//   nuisance.LF_red_P=LF_red_P;
//   nuisance.LF_red_Q=LF_red_Q;
//   if (nuisance.A_ia < 0.0 || nuisance.A_ia > 10.0) return 0;
//   if (nuisance.beta_ia < -4.0 || nuisance.beta_ia > 6.0) return 0;
//   if (nuisance.eta_ia < -10.0 || nuisance.eta_ia> 10.0) return 0;
//   if (nuisance.eta_ia_highz < -1.0 || nuisance.eta_ia_highz> 1.0) return 0;
//   // if(like.IA!=0){
//   //  if (check_LF()) return 0;
//   // }
// return 1;
// }

int set_nuisance_cluster_Mobs(double cluster_Mobs_lgN0,  double cluster_Mobs_alpha, double cluster_Mobs_beta, double cluster_Mobs_sigma0, double cluster_Mobs_sigma_qm, double cluster_Mobs_sigma_qz)
{
  //  nuisance.cluster_Mobs_lgM0 = mass_obs_norm;  //fiducial : 1.72+log(1.e+14*0.7); could use e.g. sigma = 0.2 Gaussian prior
  //  nuisance.cluster_Mobs_alpha = mass_obs_slope; //fiducial: 1.08; e.g. sigma = 0.1 Gaussian prior
  //  nuisance.cluster_Mobs_beta = mass_z_slope; //fiducial: 0.0; e.g. sigma = 0.1 Gaussian prior
  //  nuisance.cluster_Mobs_sigma = mass_obs_scatter; //fiducial 0.25; e.g. sigma = 0.05 Gaussian prior

  // fiducial values and priors from Murata et al. (2018) except for redshift-related parameters
  nuisance.cluster_Mobs_lgN0 = cluster_Mobs_lgN0; //fiducial: 3.207, flat prior [0.5, 5.0]
  nuisance.cluster_Mobs_alpha = cluster_Mobs_alpha; //fiducial: 0.993, flat prior [0.0, 2.0]
  nuisance.cluster_Mobs_beta = cluster_Mobs_beta; //fiducial: 0.0, flat prior [-1.5, 1.5]
  nuisance.cluster_Mobs_sigma0 = cluster_Mobs_sigma0; //fiducial: 0.456, flat prior [0.0, 1.5]
  nuisance.cluster_Mobs_sigma_qm = cluster_Mobs_sigma_qm; //fiducial: -0.169, flat prior [-1.5, 1.5]
  nuisance.cluster_Mobs_sigma_qz = cluster_Mobs_sigma_qz; //fiducial: 0.0, flat prior [-1.5, 1.5]

  if (nuisance.cluster_Mobs_lgN0 < 0.5 || nuisance.cluster_Mobs_lgN0 > 5.0) return 0;
  if (nuisance.cluster_Mobs_alpha < 0.0 || nuisance.cluster_Mobs_alpha > 2.0) return 0;
  if (nuisance.cluster_Mobs_beta < -1.5 || nuisance.cluster_Mobs_beta > 1.5) return 0;
  if (nuisance.cluster_Mobs_sigma0 < 0.0|| nuisance.cluster_Mobs_sigma0 > 1.5) return 0;
  if (nuisance.cluster_Mobs_sigma_qm < -1.5 && nuisance.cluster_Mobs_sigma_qm > 1.5) return 0;
  if (nuisance.cluster_Mobs_sigma_qz < -1.5 && nuisance.cluster_Mobs_sigma_qz > 1.5)return 0;

return 1;
}

int set_nuisance_gbias(double B1, double B2, double B3, double B4,double B5, double B6, double B7, double B8,double B9, double B10)
{

  int i;
  gbias.b[0] = B1;
  gbias.b[1] = B2;
  gbias.b[2] = B3;
  gbias.b[3] = B4;
  gbias.b[4] = B5;
  gbias.b[5] = B6;
  gbias.b[6] = B7;
  gbias.b[7] = B8;
  gbias.b[8] = B9;
  gbias.b[9] = B10;
  for (i = 0; i < tomo.clustering_Nbin; i++){
  //    printf("in set routine %d %le\n",i,gbias.b[i]);
    if (gbias.b[i] < 0.4 || gbias.b[i] > 3.0) return 0;
  }

  return 1;
}

int set_nuisance_bmag(double B1, double B2, double B3, double B4,double B5, double B6, double B7, double B8,double B9, double B10)
{

  int i;
  gbias.b_mag[0] = B1;
  gbias.b_mag[1] = B2;
  gbias.b_mag[2] = B3;
  gbias.b_mag[3] = B4;
  gbias.b_mag[4] = B5;
  gbias.b_mag[5] = B6;
  gbias.b_mag[6] = B7;
  gbias.b_mag[7] = B8;
  gbias.b_mag[8] = B9;
  gbias.b_mag[9] = B10;
  for (i = 0; i < tomo.clustering_Nbin; i++){
  //    printf("in set routine %d %le\n",i,gbias.b[i]);
    if (gbias.b_mag[i] < -5.0 || gbias.b_mag[i] > 5.0) return 0;
  }

  return 1;
}

double log_multi_like(double OMM, double S8, double NS, double W0,double WA, double OMB, double H0, double MGSigma, double MGmu, double B1, double B2, double B3, double B4,double B5, double B6, double B7, double B8, double B9, double B10, double BMAG1, double BMAG2, double BMAG3, double BMAG4,double BMAG5, double BMAG6, double BMAG7, double BMAG8, double BMAG9, double BMAG10, double SP1, double SP2, double SP3, double SP4, double SP5, double SP6, double SP7, double SP8, double SP9, double SP10, double CP1, double CP2, double CP3, double CP4, double CP5, double CP6, double CP7, double CP8, double CP9, double CP10, double M1, double M2, double M3, double M4, double M5, double M6, double M7, double M8, double M9, double M10, double A_ia, double eta_ia)
{
  int i,j,k,m=0,l;
  static double *pred;
  static double *ell;
  static double *ell_Cluster;
  static double darg;
  double chisqr,a,log_L_prior=0.0, log_L=0.0;;

  if(ell==0){
    pred= create_double_vector(0, like.Ndata-1);
    ell= create_double_vector(0, like.Ncl-1);
    darg=(log(like.lmax)-log(like.lmin))/like.Ncl;
    for (l=0;l<like.Ncl;l++){
      ell[l]=exp(log(like.lmin)+(l+0.5)*darg);
    }
    // ell_Cluster= create_double_vector(0, Cluster.lbin-1);
    // darg=(log(Cluster.l_max)-log(Cluster.l_min))/Cluster.lbin;
    // for (l=0;l<Cluster.lbin;l++){
    //   ell_Cluster[l]=exp(log(Cluster.l_min)+(l+0.5)*darg);
    // }
  }
  if (set_cosmology_params(OMM,S8,NS,W0,WA,OMB,H0,MGSigma,MGmu)==0){
    printf("Cosmology out of bounds\n");
    return -1.0e15;
  }
  set_nuisance_shear_calib(M1,M2,M3,M4,M5,M6,M7,M8,M9,M10);
  if (set_nuisance_shear_photoz(SP1,SP2,SP3,SP4,SP5,SP6,SP7,SP8,SP9,SP10)==0){
    printf("Shear photo-z sigma too small\n");
    return -1.0e15;
  }
  if (set_nuisance_clustering_photoz(CP1,CP2,CP3,CP4,CP5,CP6,CP7,CP8,CP9,CP10)==0){
    printf("Clustering photo-z sigma too small\n");
    return -1.0e15;
  }
  if (set_nuisance_ia(A_ia,eta_ia)==0){
    printf("IA parameters out of bounds\n");
    return -1.0e15;
  }
  if (set_nuisance_gbias(B1,B2,B3,B4,B5,B6,B7,B8,B9,B10)==0){
    printf("Bias out of bounds\n");
    return -1.0e15;
  }
  if (set_nuisance_bmag(BMAG1,BMAG2,BMAG3,BMAG4,BMAG5,BMAG6,BMAG7,BMAG8,BMAG9,BMAG10)==0){
    printf("Bmag out of bounds\n");
    return -1.0e15;
  }
  // if (set_nuisance_cluster_Mobs(mass_obs_norm, mass_obs_slope, mass_z_slope, mass_obs_scatter_norm, mass_obs_scatter_mass_slope, mass_obs_scatter_z_slope)==0){
  //   printf("Mobs out of bounds\n");
  //   return -1.0e15;
  // }

  // for (i=0; i<10; i++){
  //   printf("nuisance %le %le %le\n",nuisance.shear_calibration_m[i],nuisance.bias_zphot_shear[i],nuisance.sigma_zphot_shear[i]);
  // }

  log_L_prior=0.0;
  // if(like.Aubourg_Planck_BAO_SN==1) log_L_prior+=log_L_Planck_BAO_SN();
  // if(like.SN==1) log_L_prior+=log_L_SN();
  //if(like.BAO==1) log_L_prior+=log_L_BAO();
  // if(like.Planck==1) log_L_prior+=log_L_Planck();
  // if(like.Planck15_BAO_w0wa==1) log_L_prior+=log_L_Planck15_BAO_w0wa();//CH
  //if(like.Planck15_BAO_H070p6_JLA_w0wa==1) log_L_prior+=log_L_Planck15_BAO_H070p6_JLA_w0wa();//CH
  // if(like.IA!=0) log_L_prior+=log_L_ia();
  // if(like.IA!=0) log_L_prior+=log_like_f_red();
  if(like.wlphotoz!=0) log_L_prior+=log_L_wlphotoz();
  if(like.clphotoz!=0) log_L_prior+=log_L_clphotoz();
  if(like.shearcalib==1) log_L_prior+=log_L_shear_calib();
  // if(like.IA!=0) {
  //   log_L = 0.0;
  //   log_L -= pow((nuisance.A_ia - prior.A_ia[0])/prior.A_ia[1],2.0);
  //   log_L -= pow((nuisance.beta_ia - prior.beta_ia[0])/prior.beta_ia[1],2.0);
  //   log_L -= pow((nuisance.eta_ia - prior.eta_ia[0])/prior.eta_ia[1],2.0);
  //   log_L -= pow((nuisance.eta_ia_highz - prior.eta_ia_highz[0])/prior.eta_ia_highz[1],2.0);
  //   log_L_prior+=0.5*log_L;
  // }
  // if(like.baryons==1){
  //   log_L = 0.0;
  //   log_L -= pow((Q1 - prior.bary_Q1[0])/prior.bary_Q1[1],2.0);
  //   log_L -= pow((Q2 - prior.bary_Q2[0])/prior.bary_Q2[1],2.0);
  //   log_L -= pow((Q3 - prior.bary_Q3[0])/prior.bary_Q3[1],2.0);
  //   log_L_prior+=0.5*log_L;
  // }

  // if(like.clusterMobs==1) log_L_prior+=log_L_clusterMobs();

  // printf("%d %d %d %d\n",like.BAO,like.wlphotoz,like.clphotoz,like.shearcalib);
  // printf("logl %le %le %le %le\n",log_L_shear_calib(),log_L_wlphotoz(),log_L_clphotoz(),log_L_clusterMobs());
  int start=0;

  if(like.shear_shear==1) {
    set_data_shear(like.Ncl, ell, pred, start);
    start=start+like.Ncl*tomo.shear_Npowerspectra;
  }
  if(like.shear_pos==1){
    set_data_ggl(like.Ncl, ell, pred, start);
    start=start+like.Ncl*tomo.ggl_Npowerspectra;
  }
  if(like.pos_pos==1){
    set_data_clustering(like.Ncl,ell,pred, start);
    start=start+like.Ncl*tomo.clustering_Npowerspectra;
  }
  if(like.gk==1) {
    set_data_gk(ell, pred, start);
    start += like.Ncl*tomo.clustering_Nbin;
  }
  if(like.ks==1) {
    set_data_ks(ell, pred, start);
    start += like.Ncl*tomo.shear_Nbin;
  }
  if(like.kk==1) {
    set_data_kk(ell, pred, start);
    start += like.Ncl;
  }

  chisqr=0.0;
  for (i=0; i<like.Ndata; i++){
    for (j=0; j<like.Ndata; j++){
      // a=(pred[i]-data_read(1,i)+Q1*bary_read(1,0,i)+Q2*bary_read(1,1,i)+Q3*bary_read(1,2,i))*invcov_read(1,i,j)*(pred[j]-data_read(1,j)+Q1*bary_read(1,0,j)+Q2*bary_read(1,1,j)+Q3*bary_read(1,2,j));
      a=(pred[i]-data_read(1,i))*invcov_mask(1,i,j)*(pred[j]-data_read(1,j));
      // if(a>10){printf("a,i,j: %le, %d, %d, %le, %le, %le\n",a,i,j,pred[i]-data_read(1,i),pred[j]-data_read(1,j), invcov_mask(1,i,j));}
      chisqr=chisqr+a;
    }
    // if (fabs(data_read(1,i)) < 1.e-25){
    //    printf("%d %le %le %le\n",i,data_read(1,i),pred[i],invcov_read(1,i,i));
    // }
  }
  if (chisqr<0.0){
    printf("error: chisqr = %le\n",chisqr);
    //exit(EXIT_FAILURE);
  }
  printf("%le\n",chisqr);
  return -0.5*chisqr+log_L_prior;
}

void compute_data_vector(char *details, double OMM, double S8, double NS, double W0,double WA, double OMB, double H0, double MGSigma, double MGmu, double B1, double B2, double B3, double B4,double B5, double B6, double B7, double B8, double B9, double B10, double BMAG1, double BMAG2, double BMAG3, double BMAG4,double BMAG5, double BMAG6, double BMAG7, double BMAG8, double BMAG9, double BMAG10, double SP1, double SP2, double SP3, double SP4, double SP5,double SP6, double SP7, double SP8, double SP9, double SP10, double CP1, double CP2, double CP3, double CP4, double CP5, double CP6, double CP7, double CP8, double CP9, double CP10, double M1, double M2, double M3, double M4, double M5, double M6, double M7, double M8, double M9, double M10, double A_ia, double eta_ia)
{

  int i,j,k,m=0,l;
  static double *pred;
  static double *ell;
  static double *ell_Cluster;
  static double darg;
  double chisqr,a,log_L_prior=0.0;

  if(ell==0){
    pred= create_double_vector(0, like.Ndata-1);
    ell= create_double_vector(0, like.Ncl-1);
    darg=(log(like.lmax)-log(like.lmin))/like.Ncl;
    for (l=0;l<like.Ncl;l++){
      ell[l]=exp(log(like.lmin)+(l+0.5)*darg);
    }
    // ell_Cluster= create_double_vector(0, Cluster.lbin-1);
    // darg=(log(Cluster.l_max)-log(Cluster.l_min))/Cluster.lbin;
    // for (l=0;l<Cluster.lbin;l++){
    //   ell_Cluster[l]=exp(log(Cluster.l_min)+(l+0.5)*darg);
    // }
  }
// for (l=0;l<like.Ncl;l++){
//   printf("%d %le\n",i,ell[l]);
// }

  set_cosmology_params(OMM,S8,NS,W0,WA,OMB,H0,MGSigma,MGmu);
  set_nuisance_shear_calib(M1,M2,M3,M4,M5,M6,M7,M8,M9,M10);
  set_nuisance_shear_photoz(SP1,SP2,SP3,SP4,SP5,SP6,SP7,SP8,SP9,SP10);
  set_nuisance_clustering_photoz(CP1,CP2,CP3,CP4,CP5,CP6,CP7,CP8,CP9,CP10);
  set_nuisance_ia(A_ia,eta_ia);
  set_nuisance_gbias(B1,B2,B3,B4,B5,B6,B7,B8,B9,B10);
  set_nuisance_bmag(BMAG1,BMAG2,BMAG3,BMAG4,BMAG5,BMAG6,BMAG7,BMAG8,BMAG9,BMAG10);
  // set_nuisance_cluster_Mobs(mass_obs_norm,mass_obs_slope,mass_z_slope,mass_obs_scatter_norm,mass_obs_scatter_mass_slope,mass_obs_scatter_z_slope);

  int start=0;
  if(like.shear_shear==1) {
    set_data_shear(like.Ncl, ell, pred, start);
    start=start+like.Ncl*tomo.shear_Npowerspectra;
  }
  if(like.shear_pos==1){
    //printf("ggl\n");
    set_data_ggl(like.Ncl, ell, pred, start);
    start=start+like.Ncl*tomo.ggl_Npowerspectra;
  }
  if(like.pos_pos==1){
    //printf("clustering\n");
    set_data_clustering(like.Ncl,ell,pred, start);
    start=start+like.Ncl*tomo.clustering_Npowerspectra;
  }

  if(like.gk==1) {
    printf("Computing data vector: gk\n");
    set_data_gk(ell, pred, start);
    start += like.Ncl * tomo.clustering_Nbin;
  }
  if(like.ks==1) {
    printf("Computing data vector: ks\n");
    set_data_ks(ell, pred, start);
    start += like.Ncl * tomo.shear_Nbin;
  }
  if (like.kk) {
    printf("Computing data vector: kk\n");
    set_data_kk(ell, pred, start);
    start += like.Ncl;
  }

  FILE *F;
  char filename[300];
  if (strstr(details,"FM") != NULL){
    sprintf(filename,"%s",details);
  }
  else {sprintf(filename,"datav/%s_%s",like.probes,details);}
  F=fopen(filename,"w");
  for (i=0;i<like.Ndata; i++){
    fprintf(F,"%d %le\n",i,pred[i]);
    //printf("%d %le\n",i,pred[i]);
  }
  fclose(F);
  // printf("&gbias.b1_function %p\n",&gbias.b1_function);
  // printf("gbias.b1_function  %p\n",gbias.b1_function);
  // printf("bgal_z   %p\n",bgal_z);
  // printf("&bgal_z  %p\n",&bgal_z);
  // printf("b1_per_bin   %p\n",b1_per_bin);
  // printf("&b1_per_bin  %p\n",&b1_per_bin);

}

void write_datavector_wrapper(char *details, input_cosmo_params_des ic, input_nuisance_params_des in)
{
  compute_data_vector(details, ic.omega_m, ic.sigma_8, ic.n_s, ic.w0, ic.wa, ic.omega_b, ic.h0, ic.MGSigma, ic.MGmu,
    in.bias[0], in.bias[1], in.bias[2], in.bias[3],in.bias[4], in.bias[5], in.bias[6], in.bias[7],in.bias[8], in.bias[9],
    in.b_mag[0], in.b_mag[1], in.b_mag[2], in.b_mag[3],in.b_mag[4], in.b_mag[5], in.b_mag[6], in.b_mag[7],in.b_mag[8], in.b_mag[9],
    in.source_z_bias[0], in.source_z_bias[1], in.source_z_bias[2], in.source_z_bias[3], in.source_z_bias[4],
    in.source_z_bias[5], in.source_z_bias[6], in.source_z_bias[7], in.source_z_bias[8], in.source_z_bias[9],
    in.lens_z_bias[0], in.lens_z_bias[1], in.lens_z_bias[2], in.lens_z_bias[3], in.lens_z_bias[4],
    in.lens_z_bias[5], in.lens_z_bias[6], in.lens_z_bias[7], in.lens_z_bias[8], in.lens_z_bias[9],
    in.shear_m[0], in.shear_m[1], in.shear_m[2], in.shear_m[3], in.shear_m[4],
    in.shear_m[5], in.shear_m[6], in.shear_m[7], in.shear_m[8], in.shear_m[9],
    in.A_ia, in.eta_ia);
}

double log_like_wrapper(input_cosmo_params_des ic, input_nuisance_params_des in)
{
  double like = log_multi_like(ic.omega_m, ic.sigma_8, ic.n_s, ic.w0, ic.wa, ic.omega_b, ic.h0, ic.MGSigma, ic.MGmu,
    in.bias[0], in.bias[1], in.bias[2], in.bias[3],in.bias[4], in.bias[5], in.bias[6], in.bias[7],in.bias[8], in.bias[9],
    in.b_mag[0], in.b_mag[1], in.b_mag[2], in.b_mag[3],in.b_mag[4], in.b_mag[5], in.b_mag[6], in.b_mag[7],in.b_mag[8], in.b_mag[9],
    in.source_z_bias[0], in.source_z_bias[1], in.source_z_bias[2], in.source_z_bias[3], in.source_z_bias[4],
    in.source_z_bias[5], in.source_z_bias[6], in.source_z_bias[7], in.source_z_bias[8], in.source_z_bias[9],
    in.lens_z_bias[0], in.lens_z_bias[1], in.lens_z_bias[2], in.lens_z_bias[3], in.lens_z_bias[4],
    in.lens_z_bias[5], in.lens_z_bias[6], in.lens_z_bias[7], in.lens_z_bias[8], in.lens_z_bias[9],
    in.shear_m[0], in.shear_m[1], in.shear_m[2], in.shear_m[3], in.shear_m[4],
    in.shear_m[5], in.shear_m[6], in.shear_m[7], in.shear_m[8], in.shear_m[9],
    in.A_ia, in.eta_ia);
  return like;
}

void save_zdistr_sources(int zs){
  double z,dz =(redshift.shear_zdistrpar_zmax-redshift.shear_zdistrpar_zmin)/300.0;
  printf("Printing redshift distribution n(z) for source redshift bin %d\n",zs);

   FILE *F1;
   char filename[300];
   sprintf(filename,"zdistris/zdist_sources_bin%d.txt",zs);
   F1 = fopen(filename,"w");
   for (z =redshift.shear_zdistrpar_zmin; z< redshift.shear_zdistrpar_zmax; z+= dz){
      fprintf(F1,"%e %e\n", z, zdistr_photoz(z,zs));
   }
}

void save_zdistr_lenses(int zl){
   double z,dz =(redshift.clustering_zdistrpar_zmax-redshift.clustering_zdistrpar_zmin)/300.0;
  printf("Printing redshift distribution n(z) and bias b(z) for lens redshift bin %d\n",zl);

   FILE *F1;
   char filename[300];
   sprintf(filename,"zdistris/zdist_lenses_bin%d.txt", zl);
   F1 = fopen(filename,"w");
   for (z =redshift.clustering_zdistrpar_zmin; z< redshift.clustering_zdistrpar_zmax; z+= dz){
      fprintf(F1,"%e %e\n", z, pf_photoz(z,zl));
   }
}

 int main(int argc, char** argv)
{
  int i;
  // char arg1[400],arg2[400],arg3[400];
/* here, do your time-consuming job */
  // int sce=atoi(argv[1]);

  // int N_scenarios=2;

  // double sigma_zphot_shear[3]={0.05,0.05};
  // double sigma_zphot_clustering[3]={0.03,0.03};

  // double area_table[2]={12300.0,16500.0}; // Y1 corresponds to DESC SRD Y1, Y6 corresponds to assuming that we cover the full SO area=0.4*fsky and at a depth of 26.1 which is in a range of reasonable scenarios (see https://github.com/LSSTDESC/ObsStrat/tree/static/static )
  // double nsource_table[2]={11.0,23.0};
  // double nlens_table[2]={18.0,41.0};

  // char survey_designation[2][200]={"LSSTxSO_Y1","LSSTxSO_Y6"};
  // char tomo_binning_source[2][200]={"source_std","source_std"};
  // char tomo_binning_lens[2][200]={"LSST_gold","LSST_gold"};

  // char source_zfile[2][400]={"src_LSSTY1","src_LSSTY6"};
  // char lens_zfile[2][400]={"lens_LSSTY1", "lens_LSSTY6"};

  init_cosmo_runmode("halofit");
  // init_bary(argv[2]);
  init_binning_fourier(20,30.0,3000.0,3000.0,20.0);

  // init_priors(0.002,sigma_zphot_shear[sce],0.001,0.001,sigma_zphot_clustering[sce],0.001,0.001,3.0,1.2,3.8,2.0,16.0,5.0,0.8);
  // init_survey(survey_designation[sce],nsource_table[sce],nlens_table[sce],area_table[sce]);
  // sprintf(arg1,"zdistris/%s",source_zfile[sce]);
  // sprintf(arg2,"zdistris/%s",lens_zfile[sce]);
  // init_galaxies(arg1,arg2,"gaussian","gaussian",tomo_binning_source[sce],tomo_binning_lens[sce]);

  double b1[10]={0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}, b2[10] ={0.,0.,0.,0.,0.,0.,0.,0.,0.,0.},b_mag[10] ={0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
  b1[0] = 1.7;
  b1[1] = 1.7;
  b1[2] = 1.7;
  b1[3] = 2.0;
  b1[4] = 2.0;

  b_mag[0] = -0.19375;
  b_mag[1] = -0.6285407;
  b_mag[2] = -0.69319886;
  b_mag[3] = 1.17735723;
  b_mag[4] = 1.87509758;

  // init_source_sample_mpp("./zdistris/mcal_1101_source.nz",4);
  init_source_sample_mpp("./zdistris/source_DESY6_3bins.nz",3);
  init_lens_sample_mpp("./zdistris/mcal_1101_lens.nz",5);
  init_IA_mpp(4);
  init_probes("6x2pt");

  init_cmb("planck");
  compute_data_vector("desy6xplanck_6x2pt_3bins_2.txt",0.25,0.75,0.97,-1.,0.,0.048,0.69,0.,0.,\
    b1[0],b1[1],b1[2],b1[3],b1[4],\
    b1[5],b1[6],b1[7],b1[8],b1[9],\
    b_mag[0],b_mag[1],b_mag[2],b_mag[3],b_mag[4],\
    b_mag[5],b_mag[6],b_mag[7],b_mag[8],b_mag[9],\
    0.0,0.0,0.0,0.0,0.0,\
    0.0,0.0,0.0,0.0,0.0,\
    0.0,0.0,0.0,0.0,0.0,\
    0.0,0.0,0.0,0.0,0.0,\
    0.0,0.0,0.0,0.0,0.0,\
    0.0,0.0,0.0,0.0,0.0,\
    0.5,0.0);

  // init_data_cov_mask("cov/cov_desy3xplanck","datav/6x2pt_desy3xplanck_6x2pt.txt", "datav/xi_Y3_6x2pt.mask");
  // // init_data_cov_mask("cov/cov_desy6xplanck_3src","datav/6x2pt_desy6xplanck_6x2pt_3bins.txt", "datav/xi_Y6_6x2pt_3src.mask");

  // for(double omm=0.2;omm<0.5; omm+=0.01){
  // printf("%le, %le\n", omm, log_multi_like(omm,0.82355,0.97,-1.,0.,0.048,0.69,0.,0.,\
  //   b1[0],b1[1],b1[2],b1[3],b1[4],\
  //   b1[5],b1[6],b1[7],b1[8],b1[9],\
  //   b_mag[0],b_mag[1],b_mag[2],b_mag[3],b_mag[4],\
  //   b_mag[5],b_mag[6],b_mag[7],b_mag[8],b_mag[9],\
  //   0.0,0.0,0.0,0.0,0.0,\
  //   0.0,0.0,0.0,0.0,0.0,\
  //   0.0,0.0,0.0,0.0,0.0,\
  //   0.0,0.0,0.0,0.0,0.0,\
  //   0.0,0.0,0.0,0.0,0.0,\
  //   0.0,0.0,0.0,0.0,0.0,\
  //   0.5,0.0));
  // exit(0);
  // }
  return 0;
}