/* part of the shansyn spherical harmonics package, see COPYRIGHT for license */
/* $Id: spherical_harmonics_functions.h,v 1.16 2005/10/12 19:16:29 becker Exp becker $ */
/*

  function declarations for spherical harmonics package

*/
// structure for a model consisting of spherical harmonic
// expansions at different depths between dmin and dmax
// can be of type DISCRETE, CHEBYSHEV or SPLINES
//
#include <stdio.h>
#include <math.h>
struct mod{
  int n,lmax;
  int type;
  COMP_PRECISION **a,**b,*d;
  COMP_PRECISION dmin,dmax;
};
/*
  Chebyshev interpolation related, model output types
*/
#define DISCRETE 0
#define CHEBYSHEV 1
#define SPLINES 2
/* model output types */
#define HC_TYPE 3
//
// modes of the linear regression
//
#define REGRESS_XDETERMINED 0
#define REGRESS_ITERATIVE 1
//
// real earth constants
//
#define REARTH 6371.
#define RCMB 2871.

#include "determine_coeff.h"
// macros
#define MEMERROR {fprintf(stderr,"memory allocation error\n");exit(-1);}

// general functions
void plgndr(COMP_PRECISION *, int ,COMP_PRECISION *x, 
	    int lmax);
void dfour1(COMP_PRECISION *,unsigned long ,int );

void plgndr(COMP_PRECISION *, int ,COMP_PRECISION *, 
	    int );
void plgndr2(DATA_PRECISION *, int ,COMP_PRECISION *, 
	     int );
COMP_PRECISION slgndr(int ,int , COMP_PRECISION );
void  pdtheta_lgndr(COMP_PRECISION *, int , COMP_PRECISION *, COMP_PRECISION *, int,
		    COMP_PRECISION *,int );

void gauleg_orig(COMP_PRECISION ,COMP_PRECISION ,
		COMP_PRECISION *,COMP_PRECISION *,
		int );
void plgndr_g(COMP_PRECISION *, int, int,COMP_PRECISION *);

COMP_PRECISION correlation(COMP_PRECISION *, COMP_PRECISION *,
			   COMP_PRECISION *, COMP_PRECISION *,
			   int ,int ,int);
COMP_PRECISION ccl_correlation(COMP_PRECISION *, COMP_PRECISION *,
			       int ,int ,int *);
COMP_PRECISION correlation_gsh(COMP_PRECISION *, COMP_PRECISION *,
			       COMP_PRECISION *, COMP_PRECISION *,
			       COMP_PRECISION *, COMP_PRECISION *,
			       COMP_PRECISION *, COMP_PRECISION *,
			       int ,int ,int ,int);
COMP_PRECISION spearman_corr(COMP_PRECISION *, 
			     COMP_PRECISION *,
			     COMP_PRECISION *, 
			     COMP_PRECISION *,
			     int );
COMP_PRECISION weighted_correlation(COMP_PRECISION *, 
				    COMP_PRECISION *,
				    COMP_PRECISION *, 
				    COMP_PRECISION *,
				    int ,int);
COMP_PRECISION calc_rms(COMP_PRECISION *, 
			COMP_PRECISION *, int);

COMP_PRECISION calc_total_power(COMP_PRECISION *, 
				COMP_PRECISION *, int);

COMP_PRECISION calc_rms_gsh(COMP_PRECISION *, 
			    COMP_PRECISION *,COMP_PRECISION *, 
			    COMP_PRECISION *,  int);

COMP_PRECISION calc_total_power_gsh(COMP_PRECISION *, 
				    COMP_PRECISION *, COMP_PRECISION *, 
				    COMP_PRECISION *, int);


int interpolate_she_model(COMP_PRECISION *, COMP_PRECISION *,
			   struct mod *, COMP_PRECISION , int  ,int);
void read_she_model(char *,struct mod *,int,int);
void mean_expansions(int , COMP_PRECISION **, COMP_PRECISION **,
		     int, struct mod *, COMP_PRECISION , COMP_PRECISION ,
		     int , int);
COMP_PRECISION degree_power(COMP_PRECISION *,
			    COMP_PRECISION *, 
			    int );
COMP_PRECISION degree_power_gsh(COMP_PRECISION *,COMP_PRECISION *, 
				COMP_PRECISION *,COMP_PRECISION *, 
				int );
void write_coefficients(COMP_PRECISION **,
			COMP_PRECISION **,int ,COMP_PRECISION,
			int, FILE *, int);
void write_nonzero_coefficients(COMP_PRECISION **,
				COMP_PRECISION **,int ,COMP_PRECISION,
				int, FILE *, int);
void write_model(struct mod *,COMP_PRECISION,int);
void sphex_lin_reg(COMP_PRECISION *,
		   COMP_PRECISION *, 
		   COMP_PRECISION *, 
		   COMP_PRECISION *,
		   COMP_PRECISION *, 
		   COMP_PRECISION *,
		   int, int ,int,COMP_PRECISION *);
void gser(COMP_PRECISION *,COMP_PRECISION ,
	  COMP_PRECISION ,COMP_PRECISION *);
COMP_PRECISION gammln(COMP_PRECISION  );
void gcf(COMP_PRECISION *,COMP_PRECISION ,
	 COMP_PRECISION ,COMP_PRECISION *);
COMP_PRECISION gammq(COMP_PRECISION ,
		     COMP_PRECISION );
void linreg_fitexy(COMP_PRECISION *,COMP_PRECISION *,int ,
		   COMP_PRECISION *,COMP_PRECISION *,
		   COMP_PRECISION *,COMP_PRECISION *,
		   COMP_PRECISION *,COMP_PRECISION *,
		   COMP_PRECISION *,COMP_PRECISION *);

void  linreg_fit(COMP_PRECISION *,COMP_PRECISION *,int,
		 COMP_PRECISION *,int ,
		 COMP_PRECISION *,COMP_PRECISION *,
		 COMP_PRECISION *,COMP_PRECISION *,
		 COMP_PRECISION *,COMP_PRECISION *);




