예제 #1
0
void UpdateBeta(vec& beta, mat& rho_m, int V, int K){
	double NEWTON_THRESH = 0.00001;
	int MAX_ITER = 1000;
	double gamma = 0.001;

	vec df(V, fill::zeros);
	vec g(V, fill::zeros);
	vec h(V, fill::zeros);
	int iter = 0;
	do{
		// compute the first derivative
		double digamma_beta = digamma(sum(beta));
		double digamma_theta = 0;
		for(int k = 0; k < K; k++){
			digamma_theta += digamma(sum(rho_m.row(k)));
		}
		for(int w = 0; w < V; w++){
			double temp = 0;
			for(int k = 0; k < K; k++){
				temp += digamma(rho_m(k, w));
			}
			g(w) = K * (digamma_beta - digamma(beta(w))) + temp - digamma_theta;
		}
		cout << "this is g" << endl;
		cout << g.t() << endl;
		// compute the Hessian
		double trigamma_beta = trigamma(sum(beta));
		for(int w = 0; w < V; w++){
			h(w) = K * trigamma(beta(w));
		}

	cout << "this is h" << endl;
	cout << h.t() << endl;
		// compute constant terms needed for gradient
		double c = sum(g / h) / (- 1 / trigamma_beta + sum(1 / h));

		for(int w = 0; w < V; w++){
			df(w) = (g(w) - c) / h(w);
		}
		
		beta -= gamma * df;
		iter++;
		cout << "iteration: " << iter << endl;
		cout << beta.t() << endl;
	} while(iter < MAX_ITER && max(abs(df)) > NEWTON_THRESH);

	return;
}
예제 #2
0
파일: lgamma.hpp 프로젝트: stan-dev/nomad
  inline var<AutodiffOrder, StrictSmoothness, ValidateIO>
    lgamma(const var<AutodiffOrder, StrictSmoothness, ValidateIO>& input) {
    
    if (ValidateIO) validate_input(input.first_val(), "lgamma");
      
    const short partials_order = 3;
    const unsigned int n_inputs = 1;
    
    create_node<unary_var_node<AutodiffOrder, partials_order>>(n_inputs);

    double val = input.first_val();
    
    try {
      push_dual_numbers<AutodiffOrder, ValidateIO>(lgamma(val));
    } catch (nomad_error) {
      throw nomad_output_value_error("lgamma");
    }
      
    push_inputs(input.dual_numbers());
    
    try {
      if (AutodiffOrder >= 1) push_partials<ValidateIO>(digamma(val));
      if (AutodiffOrder >= 2) push_partials<ValidateIO>(trigamma(val));
      if (AutodiffOrder >= 3) push_partials<ValidateIO>(quadrigamma(val));
    } catch (nomad_error) {
      throw nomad_output_partial_error("lgamma");
    }
      
    return var<AutodiffOrder, StrictSmoothness, ValidateIO>(next_node_idx_ - 1);
    
  }
예제 #3
0
void test01 ( void )

/******************************************************************************/
/*
  Purpose:

    TEST01 demonstrates the use of TRIGAMMA.

  Licensing:

    This code is distributed under the GNU LGPL license. 

  Modified:

    19 January 2008

  Author:

    John Burkardt
*/
{
  double fx;
  double fx2;
  int ifault;
  int n_data;
  double x;

  printf ( "\n" );
  printf ( "TEST01:\n" );
  printf ( "  TRIGAMMA computes the trigamma function. \n" );
  printf ( "  We compare the result to tabulated values.\n" );
  printf ( "\n" );
  printf ( "          X                     " ); 
  printf ( "FX                        FX2\n" );
  printf ( "                                " );
  printf ( "(Tabulated)               (TRIGAMMA)                DIFF\n" );
  printf ( "\n" );

  n_data = 0;

  for ( ; ; )
  {
    trigamma_values ( &n_data, &x, &fx );

    if ( n_data == 0 )
    {
      break;
    }

    fx2 = trigamma ( x, &ifault );

    printf ( "  %24.16f  %24.16f  %24.16f  %10.4g\n",
      x, fx, fx2, fabs ( fx - fx2 ) );
  }

  return;
}
예제 #4
0
파일: lgamma.c 프로젝트: gbennett71/libstb
static void diffset(void) {
  int i;
  for (i=3; i<FDIM; i++) {
    fg[i] = lgamma(i);
    fp0[i] = digamma(i);
    fp1[i] = trigamma(i);
    fp2[i] = tetragamma(i);
    fp3[i] = pentagamma(i);
  }
  fset = 1;
}
예제 #5
0
파일: zinb.c 프로젝트: rlim19/Biotools
double
eval_zinb_dgda
(
         double   a,
         double   p,
   const tab_t  * tab
)
{
   
   // Convenience variables.
   const unsigned int *val = tab->val;
   const unsigned int *num = tab->num;
   const double ppa = pow(p,a);

   unsigned int nz = 0;
   double retval = 0.0;
   double prev = trigamma(a + val[0]);

   if (val[0] > 0) {
      retval += num[0] * prev;
      nz += num[0];
   }

   // Iterate over the occurrences and compute the new value
   // of digamma either by the recurrence relation, or by
   // a new call to 'trigamma()', whichever is faster.
   const size_t imin = val[0] == 0 ? 1 : 0;
   for (size_t i = imin ; i < tab->size ; i++) {
      nz += num[i];
      prev = (val[i] - val[i-1] == 1) ?
         prev - 1.0 / sq(a-1 + val[i]) :
         trigamma(a + val[i]);
      retval += num[i] * prev;
   }

   retval += nz*(sq(log(p))*ppa / sq(1-ppa) - trigamma(a));
   return retval;

}
예제 #6
0
파일: BetaModel.cpp 프로젝트: comenerv/Boom
  double BM::Loglike(const Vector &ab, Vec &g, Mat &h, uint nd) const{
    if (ab.size() != 2) {
      report_error("Wrong size argument.");
    }
    double alpha = ab[0];
    double beta = ab[1];
    if (alpha <= 0 || beta <= 0) {
      if (nd > 0) {
        g[0] = (alpha <= 0) ? 1.0 : 0.0;
        g[1] = (beta <= 0) ? 1.0 : 0.0;
        if (nd > 1) {
          h = 0.0;
          h.diag() = -1.0;
        }
      }
      return negative_infinity();
    }

    double n = suf()->n();
    double sumlog = suf()->sumlog();
    double sumlogc = suf()->sumlogc();

    double ans = n*(lgamma(alpha + beta) - lgamma(alpha)-lgamma(beta));
    ans += (alpha-1)*sumlog + (beta-1)*sumlogc;

    if(nd>0){
      double psisum = digamma(alpha + beta);
      g[0] = n*(psisum-digamma(alpha)) + sumlog;
      g[1] = n*(psisum-digamma(beta)) + sumlogc;

      if(nd>1){
 	double trisum = trigamma(alpha+beta);
 	h(0,0) = n*(trisum - trigamma(alpha));
 	h(0,1) = h(1,0) = n*trisum;
 	h(1,1) = n*(trisum - trigamma(beta));}}
    return ans;
  }
예제 #7
0
파일: zinb.c 프로젝트: rlim19/Biotools
double
eval_nb_dfda
(
   double a,
   const tab_t *tab
)
{

   double retval;
   double prev;
   // Convenience variables.
   const unsigned int *val = tab->val;
   const unsigned int *num = tab->num;

   size_t nobs = num[0];
   double mean = num[0] * val[0];

   prev = trigamma(a + val[0]);
   retval = num[0] * prev;
   // Iterate over the occurrences and compute the new value
   // of trigamma either by the recurrence relation, or by
   // a new call to 'trigamma()', whichever is faster.
   for (size_t i = 1 ; i < tab->size ; i++) {
      nobs += num[i];
      mean += num[i] * val[i];
      prev = (val[i] - val[i-1] == 1) ?
         prev - 1.0 / sq(a-1 +val[i]) :
         trigamma(a + val[i]);
      retval += num[i] * prev;
   }

   mean /= nobs;
   retval += nobs*(mean/(a*(a+mean)) - trigamma(a));

   return retval;

}
예제 #8
0
파일: gamma.c 프로젝트: kriepy/Afstuderen
/* The trigamma function is the derivative of the digamma function.

   Reference:

    B Schneider,
    Trigamma Function,
    Algorithm AS 121,
    Applied Statistics, 
    Volume 27, Number 1, page 97-99, 1978.

    From http://www.psc.edu/~burkardt/src/dirichlet/dirichlet.f
    (with modification for negative arguments and extra precision)
*/
double trigamma(double x)
{
  double result;
  double neginf = -1.0/0.0,
	  small = 1e-4,
	  large = 8,
	  c = 1.6449340668482264365, /* pi^2/6 = Zeta(2) */
	  c1 = -2.404113806319188570799476,  /* -2 Zeta(3) */
	  b2 =  1./6,
	  b4 = -1./30,
	  b6 =  1./42,
	  b8 = -1./30,
	  b10 = 5./66;
  /* Illegal arguments */
  if((x == neginf) || isnan(x)) {
    return 0.0/0.0;
  }
  /* Singularities */
  if((x <= 0) && (floor(x) == x)) {
    return -neginf;
  }
  /* Negative values */
  /* Use the derivative of the digamma reflection formula:
   * -trigamma(-x) = trigamma(x+1) - (pi*csc(pi*x))^2
   */
  if(x < 0) {
    result = M_PI/sin(-M_PI*x);
    return -trigamma(1-x) + result*result;
  }
  /* Use Taylor series if argument <= small */
  if(x <= small) {
    return 1/(x*x) + c + c1*x;
  }
  result = 0;
  /* Reduce to trigamma(x+n) where ( X + N ) >= B */
  while(x < large) {
    result += 1/(x*x);
    x++;
  }
  /* Apply asymptotic formula when X >= B */
  /* This expansion can be computed in Maple via asympt(Psi(1,x),x) */
  if(x >= large) {
    double r = 1/(x*x);
    result += 0.5*r + (1 + r*(b2 + r*(b4 + r*(b6 + r*(b8 + r*b10)))))/x;
  }
  return result;
}
예제 #9
0
void mexFunction(int nlhs, mxArray *plhs[],
		 int nrhs, const mxArray *prhs[])
{
  int ndims, len, i, nnz;
  int *dims;
  double *indata, *outdata;

  if((nrhs != 1) || (nlhs > 1))    
    mexErrMsgTxt("Usage: x = trigamma(n)");

  /* prhs[0] is first argument.
   * mxGetPr returns double*  (data, col-major)
   * mxGetM returns int  (rows)
   * mxGetN returns int  (cols)
   */
  ndims = mxGetNumberOfDimensions(prhs[0]);
  dims = (int*)mxGetDimensions(prhs[0]);
  indata = mxGetPr(prhs[0]);
  len = mxGetNumberOfElements(prhs[0]);

  if(mxIsSparse(prhs[0])) {
    plhs[0] = mxDuplicateArray(prhs[0]);
    /* number of nonzero entries */
    nnz = mxGetJc(prhs[0])[mxGetN(prhs[0])];
    if(nnz != mxGetNumberOfElements(prhs[0])) {
      mexErrMsgTxt("Cannot handle sparse n.");
    }
  } else {
    /* plhs[0] is first output */
    plhs[0] = mxCreateNumericArray(ndims, dims, mxDOUBLE_CLASS, mxREAL);
  }
  outdata = mxGetPr(plhs[0]);

  /* compute trigamma of every element */
  for(i=0;i<len;i++)
    *outdata++ = trigamma(*indata++);
}
예제 #10
0
double d2_alhood(double a, double alpha_sum, int D, int K)
{ return(D * (trigamma(alpha_sum) - trigamma(a))); }
예제 #11
0
double d2_alhood(double a, int D, int K)
{ return(D * (K * K * trigamma(K * a) - K * trigamma(a))); }
예제 #12
0
inline typename tools::promote_args<T>::type
   trigamma(T x)
{
   return trigamma(x, policies::policy<>());
}
예제 #13
0
void diff2PDF_nu_tCopula_new(double* u, double* v, int* n, double* param, int* copula, double* out)
{
	double out1=0, out2=0, out3=0, out4=0, x1, x2, diff_nu=0;
	int j=0, k=1;

	double t1, t2, t3, t4, t5, t6, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23, t24, t25, M_nu, M, M_nu_nu, c;

	double rho = param[0];
	double nu = param[1];

	
	t1=(nu+1.0)/2.0;
	t2=nu/2.0;
	t23=nu*nu;
	t3=1.0/t23;
	t4=1.0/(2.0*nu);
	t5=0.5*trigamma(t1);
	t6=(1.0-rho*rho);
	t9=0.5*trigamma(t2);
	t10=-t5+t9-t3-t4;
	

	for(j=0;j<*n;j++)
	{
		LL(copula, &k, &u[j], &v[j], &rho, &nu, &c);
		c=exp(c);
		x1=qt(u[j],nu,1,0);
		x2=qt(v[j],nu,1,0);
		diffX_nu_tCopula(&x1, param, &out1);
		diffX_nu_tCopula(&x2, param, &out2);
		M = ( nu*t6 + x1*x1 + x2*x2 - 2.0*rho*x1*x2 );

		t8=(x1*out2+out1*x2);
		M_nu=t6+2.0*x1*out1+2.0*x2*out2-2.0*rho*t8;

		t24=x1*x1;
		t25=x2*x2;

		t11=1.0+2.0*x1*out1;
		t12=nu+t24;
		t13=t11/t12;

		t14=1.0+2.0*x2*out2;
		t15=nu+t25;
		t16=t14/t15;

		diff2_x_nu(&x1,&nu,&out3);
		diff2_x_nu(&x2,&nu,&out4);

		t17=2.0*out1*out1 + 2.0*x1*out3;
		t18=t17/t12;

		t19=2.0*out2*out2 + 2.0*x2*out4;
		t20=t19/t15;

		t21=t13*t13;
		t22=t16*t16;

		M_nu_nu=2.0*out1*out1 + 2.0*x1*out3 + 2.0*out2*out2 + 2.0*x2*out4 - 4.0*rho*out1*out2 - 2.0*rho*(x2*out3 + x1*out4);
		
		diffPDF_nu_tCopula_new(&u[j], &v[j], &k, param, copula, &diff_nu);

		out[j]=c*( t10+0.5*(t13+t16) + t1*(t18-t21+t20-t22) + 0.5*t13 + 0.5*t16 - M_nu/M - (nu/2.0+1.0)*(M_nu_nu/M-M_nu*M_nu/M/M )) + diff_nu*diff_nu/c;
	}
}
예제 #14
0
void train() {
	/* initialize output */
	printf("init train\n");
	initTrain();

	/* initialize temp variables */
	double *myalpha_new = (double *) malloc(sizeof(double)*K);
	double *psi_sum_beta = (double *) malloc(sizeof(double)*M);
	double *psi_myalpha = (double *) malloc(sizeof(double)*K);
	double **log_myrho = (double **) malloc(sizeof(double*)*M);
	double **psi_mybeta = (double **) malloc(sizeof(double*)*M);
	for (int m = 0; m < M; m++) {
		log_myrho[m] = (double *) malloc(sizeof(double)*K);
		psi_mybeta[m] = (double *) malloc(sizeof(double)*K);
	}
	double **old_mytheta = (double **) malloc(sizeof(double*)*K);
	double **log_mytheta = (double **) malloc(sizeof(double*)*K);
	double **log_inv_mytheta = (double **) malloc(sizeof(double*)*K);
	for (int k = 0; k < K; k++) {
		old_mytheta[k] = (double *) malloc(sizeof(double)*L);
		for (int l = 0; l < L; l++) old_mytheta[k][l] = 0;
		log_mytheta[k] = (double *) malloc(sizeof(double)*L);
		log_inv_mytheta[k] = (double *) malloc(sizeof(double)*L);
	}
	double *g = (double *) malloc(sizeof(double)*K);
	double *q = (double *) malloc(sizeof(double)*K);

	double maxDiff = 0;

	for (int out_iter = 0; out_iter < OUT_LOOP; out_iter++) {
		if (out_iter % 100 == 0) printf("Iter: %d\n", out_iter);
		for (int k = 0; k < K; k++) {
			for (int l = 0; l < L; l++) {
#ifdef NEW_PRIOR
				if (A[l] == 0) continue;
#endif
				log_mytheta[k][l] = log(mytheta[k][l]);
				//printf("%lf ", log(mytheta[k][l]));
				log_inv_mytheta[k][l] = log(1-mytheta[k][l]);
			}
			//printf("\n");
		}
		/* e-step */
//		for (int in_iter = 0; in_iter < IN_LOOP; in_iter++) {
			//printf("in iter: %d\n", in_iter);
#pragma omp parallel shared(M,N,K,L,mybeta,psi_mybeta,log_myrho,log_mytheta,log_inv_mytheta,r)
			{
#pragma omp for schedule(dynamic,1)
				for (int m = 0; m < M; m++) {
					/* computer r */
					double sum_beta = 0;
					for (int k = 0; k < K; k++) {
						sum_beta += mybeta[m][k];
						psi_mybeta[m][k] = DiGamma_Function(mybeta[m][k]);
					}
					psi_sum_beta[m] = DiGamma_Function(sum_beta);
					for (int n = 0; n < N[m]; n++) {
						for (int k = 0; k < K; k++) {
							log_myrho[m][k] = psi_mybeta[m][k]-psi_sum_beta[m];
							for (int l = 0; l < L; l++) {
#ifdef NEW_PRIOR
								if (A[l] == 0) continue;
#endif

								if (R[m][n][l]) {
									log_myrho[m][k] += log_mytheta[k][l];
								} else {
									log_myrho[m][k] += log_inv_mytheta[k][l];
								}
							}
						}
						double log_sum_rho = logsumexp(log_myrho[m], K);
						for (int k = 0; k < K; k++) {
							r[m][n][k] = exp(log_myrho[m][k] - log_sum_rho);
						}
					}

					/* compute mybeta */
					for (int k = 0; k < K; k++) {
						mybeta[m][k] = myalpha[k];
						for (int n = 0; n < N[m]; n++) {
							mybeta[m][k] = mybeta[m][k] + r[m][n][k];
						}
					}
				}
			}
			/*
			printf("beta:\n");
			for (int m = 0; m < M; m++) {
				for (int k = 0; k < K; k++) {
					printf("%lf ", mybeta[m][k]);
				}
				printf("\n");
			}
			*/
//		}
#ifdef DEBUG
		printf("beta:\n");
		for (int m = 0; m < M; m++) {
			for (int k = 0; k < K; k++) {
				printf("%lf ", mybeta[m][k]);
			}
			printf("\n");
		}
#endif
		/* m-step */
		if (out_iter != OUT_LOOP - 1) {
			/* update alpha */
			if (mode == UPDATE_ALPHA) {
				for (int m = 0; m < M; m++) {
					double sum_beta = 0;
					for (int k = 0; k < K; k++) {
						sum_beta += mybeta[m][k];
						psi_mybeta[m][k] = DiGamma_Function(mybeta[m][k]);
					}
					psi_sum_beta[m] = DiGamma_Function(sum_beta);
				}
				int converge = 0;
				for (int iter = 0; iter < 1000; iter++) {
					double sum_alpha = 0;
					for (int k = 0; k < K; k++) {
						sum_alpha += myalpha[k];
						psi_myalpha[k] = DiGamma_Function(myalpha[k]);
					}
					double psi_sum_alpha = DiGamma_Function(sum_alpha);
					int fault;
					for (int k = 0; k < K; k++) {
						g[k] = M * (psi_sum_alpha - psi_myalpha[k]);
						for (int m = 0; m < M; m++) {
							g[k] += psi_mybeta[m][k] - psi_sum_beta[m];
						}
						q[k] = -M * trigamma(myalpha[k], &fault);
					}
					double z = M * trigamma(sum_alpha, &fault);
					double gq = 0;
					double rq = 0;
					for (int k = 0; k < K; k++) {
						gq = gq + g[k] / q[k];
						rq = rq + 1 / q[k];
					}
					double b = gq / (1 / z + rq);
					for (int k = 0; k < K; k++) {
						myalpha_new[k] = myalpha[k] - (g[k] - b) / q[k];
						if (myalpha_new[k] < 0) {
							printf("warning alpha small than zero\n");
						}
					}
#ifdef DEBUG
					printf("alpha:\n");
					for (int k = 0; k < K; k++) {
						printf("%lf ", myalpha[k]);
					}
					printf("\n");
#endif

					converge = 1; 
					for (int k = 0; k < K; k++) {
						double diff = myalpha_new[k] - myalpha[k];
						if (diff > 1e-6 || diff < -1e-6) {
							converge = 0;
							break;
						}
					}
					if (converge) {
						break;
					}

					double *tmpalpha = myalpha;
					myalpha = myalpha_new;
					myalpha_new = tmpalpha;
				}
				if (!converge) {
					printf("warning: not converge\n");
				}
			}

			/* update theta */
#pragma omp parallel shared(K,N,L,M,mytheta,r,R)
			{
#pragma omp for schedule(dynamic,1)
				for (int k = 0; k < K; k++) {
					for (int l = 0; l < L; l++) {
						double rR = 0;
						double sum_r = 0;
#ifdef PRIOR
						rR += A;
						sum_r += A + B;
#endif

#ifdef NEW_PRIOR
						if (A[l] == 0) continue;
						rR += A[l];
						sum_r += A[l] + B[l];
#endif

						for (int m = 0; m < M; m++) {
							for (int n = 0; n < N[m]; n++) {
								rR += r[m][n][k]*R[m][n][l];
								sum_r += r[m][n][k];
							}
						}
						mytheta[k][l] = rR / sum_r;
						if (EQUAL(rR,0.0)) {
							mytheta[k][l] = 0;
						}
						if (mytheta[k][l] < 0 || mytheta[k][l] > 1 || mytheta[k][l] != mytheta[k][l]) {
							printf("error %lf %lf\n", rR, sum_r);
						}
					}
				}
			}

			maxDiff = 0;
			for (int k = 0; k < K; k++ ){
				for (int l = 0; l < L; l++) {
#ifdef NEW_PRIOR
					if (A[l] == 0) continue;
#endif
					double diff = old_mytheta[k][l] - mytheta[k][l];
					if (diff > maxDiff) maxDiff = diff;
					if	(-diff > maxDiff) maxDiff = -diff;
					old_mytheta[k][l] = mytheta[k][l];
				}
			}
			if (maxDiff < 1e-6) {
				printf("Finished.\n");
				break;
			}

#ifdef DEBUG
			printf("theta:\n");
			for (int k = 0; k < K; k++) {
				for (int l = 0; l < L; l++) {
					printf("%lf ", mytheta[k][l]);
				}
				printf("\n");
			}
#endif
		}
	}

	/* free temp variables */
	free(g);
	free(q);
	for (int k = 0; k < K; k++) {
		free(log_inv_mytheta[k]);
		free(log_mytheta[k]);
		free(old_mytheta[k]);
	}
	free(old_mytheta);
	free(log_inv_mytheta);
	free(log_mytheta);
	for (int m = 0; m < M; m++) {
		free(psi_mybeta[m]);
		free(log_myrho[m]);
	}
	free(psi_mybeta);
	free(log_myrho);
	free(psi_sum_beta);
	free(psi_myalpha);
	free(myalpha_new);
}
예제 #15
0
파일: trigamma.hpp 프로젝트: stan-dev/math
 static inline T fun(const T& x) {
   return trigamma(x);
 }
예제 #16
0
void inbeder(double* x_in, double* p_in, double* q_in, double* der)
{

  double lbet, pa, pa1, pb, pb1, pab, pab1, err=1e-12;
  double p, q, x;
  int minappx=3, maxappx=200, n=0;

  // falls x>p/(p+q)
  if (*x_in>*p_in/(*p_in+*q_in))
  {
	  x=1-*x_in;
	  p=*q_in;
	  q=*p_in;
  }
  else
  {
	  x=*x_in;
	  p=*p_in;
	  q=*q_in;
  }
  
  // Compute Log Beta, digamma, and trigamma functions
  
  lbet=lbeta(p,q);
  pa=digamma(p);
  pa1=trigamma(p);
  pb=digamma(q);
  pb1=trigamma(q);
  pab=digamma(p+q);
  pab1=trigamma(p+q);


  double omx=1-x;
  double logx=log(x);
  double logomx=log(omx);

  // Compute derivatives of K(x,p,q)=x^p(1-x)^(q-1)/[p beta(p,q)

  double *c;
  double c0, d;
  c=Calloc(3,double);
  c[0]=p*logx+(q-1)*logomx-lbet-log(p);
  c0=exp(c[0]);
  if (*x_in>*p_in/(*p_in+*q_in))
  {
	 c[1]=logomx-pb+pab;
  	c[2]=c[1]*c[1]-pb1+pab1;
  }
  else
  {
  	c[1]=logx-1/p-pa+pab;
 	 c[2]=c[1]*c[1]+1/p/p-pa1+pab1;
  }
  

  int del=1, i=0;
  double *an, *bn, *an1, *an2, *bn1, *bn2, *dr;
  an=Calloc(3,double);
  bn=Calloc(3,double);
  an1=Calloc(3,double);
  bn1=Calloc(3,double);
  an2=Calloc(3,double);
  bn2=Calloc(3,double);
  dr=Calloc(3,double);
  double *dan, *dbn, *der_old, *d1;
  dan=Calloc(3,double);
  dbn=Calloc(3,double);
  der_old=Calloc(3,double);
  d1=Calloc(3,double);

  double Rn=0, pr=0;

  an1[0]=1;
  an2[0]=1;
  bn1[0]=1;
  bn2[0]=0;
  der_old[0]=0;
  for(i=1;i<3;i++)
  {
	  an1[i]=0;
	  an2[i]=0;
	  bn1[i]=0;
	  bn2[i]=0;
	  der_old[i]=0;
  }

	
  while(del==1)
  {
	  n++;
	  if(n==1)
	  {
		  if (*x_in>*p_in/(*p_in+*q_in))
		  {
			  incompleBeta_an1_bn1_q(&x, p, q, an, bn);
		  }
		  else
		  {
			  incompleBeta_an1_bn1_p(&x, p, q, an, bn);

		  }
	  }
	  else
	  {
		  if (*x_in>*p_in/(*p_in+*q_in))
		  {
			  incompleBeta_an_bn_q(&x, p, q, n, an, bn);
		  }
		  else
		  {
			  incompleBeta_an_bn_p(&x, p, q, n, an, bn);
		  }
	  }
	  

	  // Use forward recurrance relations to compute An, Bn, and their derivatives
	  
	  dan[0]=an[0]*an2[0]+bn[0]*an1[0];
	  dbn[0]=an[0]*bn2[0]+bn[0]*bn1[0];
	  dan[1]=an[1]*an2[0]+an[0]*an2[1]+bn[1]*an1[0]+bn[0]*an1[1];
	  dbn[1]=an[1]*bn2[0]+an[0]*bn2[1]+bn[1]*bn1[0]+bn[0]*bn1[1];
	  dan[2]=an[2]*an2[0]+2*an[1]*an2[1]+an[0]*an2[2]+bn[2]*an1[0]+2*bn[1]*an1[1]+bn[0]*an1[2];
	  dbn[2]=an[2]*bn2[0]+2*an[1]*bn2[1]+an[0]*bn2[2]+bn[2]*bn1[0]+2*bn[1]*bn1[1]+bn[0]*bn1[2];
	  
	  
	  // Scale derivatives to prevent overflow
	  
	  Rn=dan[0];
	  if(fabs(dbn[0])>fabs(dan[0]))
	  {
	    Rn=dbn[0];
	  }
	  for(i=0;i<3;i++)
	  {
	      an1[i]=an1[i]/Rn;
	      bn1[i]=bn1[i]/Rn;
	  }
	  dan[1]=dan[1]/Rn;
	  dan[2]=dan[2]/Rn;
	  dbn[1]=dbn[1]/Rn;
	  dbn[2]=dbn[2]/Rn;
	  if(fabs(dbn[0])>fabs(dan[0]))
	  {
	    dan[0]=dan[0]/dbn[0];
	    dbn[0]=1;
	  }
	  else
	  {
	    dbn[0]=dbn[0]/dan[0];
	    dan[0]=1;
	  }
	  
	  // Compute components of derivatives of the nth approximant
	  
	  dr[0]=dan[0]/dbn[0];
	  Rn=dr[0];
	  dr[1]=(dan[1]-Rn*dbn[1])/dbn[0];
	  dr[2]=(-2*dan[1]*dbn[1]+2*Rn*dbn[1]*dbn[1])/dbn[0]/dbn[0]+(dan[2]-Rn*dbn[2])/dbn[0];
	  
	  // Save terms corresponding to approximants n-1 and n-2
	  
	  for(i=0;i<3;i++)
	  {
	    an2[i]=an1[i];
	    an1[i]=dan[i];
	    bn2[i]=bn1[i];
	    bn1[i]=dbn[i];
	  }
	  
	  //  Compute nth approximants
	  pr=0;
	  if(dr[0]>0)
	  {
	    pr=exp(c[0]+log(dr[0]));
	  }
	  der[0]=pr;
	  der[1]=pr*c[1]+c0*dr[1];
	  der[2]=pr*c[2]+2*c0*c[1]*dr[1]+c0*dr[2];
	  
	  
	  // Check for convergence, check for maximum and minimum iterations.
	  
	  for(i=0;i<3;i++)
	  {
	    d1[i]=MAX(err,fabs(der[i]));
	    d1[i]=fabs(der_old[i]-der[i])/d1[i];
	    der_old[i]=der[i];
	  }
	  d=MAX(MAX(d1[0],d1[1]),d1[2]);
	  
	  if(n< minappx)
	  {
	    d=1;
	  }
	  if(n>= maxappx)
	  {
	    d=0;
	  }
	  del=0;
	  if(d> err)
	  {
	    del=1;
	  }
	  
	  
  }
 
  	// Adjust results if I(x,p,q) = 1- I(1-x,q,p) was used
	  
	  if (*x_in>*p_in/(*p_in+*q_in))
	  {
		der[0]=1-der[0];
		der[1]=-der[1];
		der[2]=-der[2];
	  }

  Free(c);
  Free(an);
  Free(bn);
  Free(dan);
  Free(dbn);
  Free(dr);
  Free(an1);
  Free(an2);
  Free(bn1);
  Free(bn2);
  Free(d1);
  Free(der_old);
  
}
예제 #17
0
double F77_SUB(trigamm)(double *x)
{
	return trigamma(*x);
}