/****************************************************************************
 *                                                                          *
 *     Loki - Programs for genetic analysis of complex traits using MCMC    *
 *                                                                          *
 *                   Simon Heath - MSKCC                                    *
 *                                                                          *
 *                       August 2000                                        *
 *                                                                          *
 * sample_nu.c:                                                             *
 *                                                                          *
 * Sampling routines connected to t-distribution of residuals               *
 *                                                                          *
 * Copyright (C) Simon C. Heath 1997, 2000, 2002                            *
 * This is free software.  You can distribute it and/or modify it           *
 * under the terms of the Modified BSD license, see the file COPYING        *
 *                                                                          *
 ****************************************************************************/

#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef USE_DMALLOC
#include <dmalloc.h>
#endif
#include <math.h>
#include <stdio.h>
#include <float.h>
#include <errno.h>

#include "ranlib.h"
#include "utils.h"
#include "loki.h"
#include "sample_nu.h"

double res_nu;
int use_student_t;
static double nu_list[]={1,1.5,2,5,10,25,50,100,-1};
static double *nu_prob;
static int n_nu;

#ifdef FUNC_NAME
#undef FUNC_NAME
#endif
#define FUNC_NAME "init_sample_nu"
void init_sample_nu(void)
{
	int i,type,nrec;
	double n,v;
	
	n_nu=0;
	while(nu_list[n_nu]>=0.0) n_nu++;	
	if(n_nu) {
		res_nu=nu_list[n_nu-1];
		if(!(nu_prob=malloc(sizeof(double)*2*n_nu))) ABT_FUNC(MMsg);
	}
	n=0.0;
	type=models[0].var.type;
	for(i=0;i<ped_size;i++) if(id_array[i].res) {
		if(type&ST_CONSTANT) nrec=1;
		else nrec=id_array[i].n_rec;
		n+=(double)nrec;
	}
	for(i=0;i<n_nu;i++) {
		v=nu_list[i];
		nu_prob[i]=lgamma((v+n)*.5)-lgamma(.5*v)-log(v*M_PI*residual_var[0])*.5*n;
	}
	res_nu=.25;
}

void free_sample_nu(void)
{
	if(nu_prob) free(nu_prob);
	nu_prob=0;
}

void sample_weights(void) 
{
	int i,j,type,nrec;
	double y,n,s,kk;
  
	type=models[0].var.type;
	if(res_nu<1.0e-6) {
		for(i=0;i<ped_size;i++) if(id_array[i].res[0]) {
			if(type&ST_CONSTANT) nrec=1;
			else nrec=id_array[i].n_rec;
			for(j=0;j<nrec;j++) id_array[i].vv[0][j]=1.0;
		}
	} else {
		kk=residual_var[0]/res_nu;
		n=(1.0/res_nu)+1.0;
		for(i=0;i<ped_size;i++) if(id_array[i].res[0]) {
			if(type&ST_CONSTANT) nrec=1;
			else nrec=id_array[i].n_rec;
			for(j=0;j<nrec;j++) {
				y=id_array[i].res[0][j];
				s=y*y;
				y=(s+kk)/(sgamma(n*0.5)*2.0);
				id_array[i].vv[0][j]=y/residual_var[0];
			}
		}
	}
}

void sample_nu(void)
{
#if 0
	int i,j,type,nrec;
	double y,n,s,s1,v,z,nu,np,np1;
#endif
	
	res_nu=.25;
	sample_weights();
	return;
#if 0	
	nu=ranf();
	if(nu>=1.0e-6 && nu<=1.0) {
		type=models[0].var.type;
		n=0.0;
		np=np1=s1=0.0;
		for(i=0;i<ped_size;i++) if(id_array[i].res[0]) {
			if(type&ST_CONSTANT) nrec=1;
			else nrec=id_array[i].n_rec;
			for(j=0;j<nrec;j++) {
				n++;
				y=id_array[i].res[0][j];
				s=y*y/residual_var[0];
				np+=s*res_nu;
				np1+=s*nu;
				s1+=s;
			}
		}
		v=1.0/res_nu;
		z=lgamma((v+n)*.5)-lgamma(.5*v)-log(v*M_PI*residual_var[0])*.5*n;
		np=z-.5*(v+n)*log(1.0+np);
		v=1.0/nu;
		z=lgamma((v+n)*.5)-lgamma(.5*v)-log(v*M_PI*residual_var[0])*.5*n;
		np1=z-.5*(v+n)*log(1.0+np1);
		s1=-.5*(n*log(2.0*M_PI*residual_var[0])+s1);
		if(np1>np) z=1.0;
		else z=exp(np1-np);
		if(ranf()<=z) {
			res_nu=nu;
		}
	}
	sample_weights();
#endif
}

