/* integration/err.c
 *
 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Brian Gough
 *
 * 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.
 */

#include <config.h>
#include <math.h>
#include <float.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_integration.h>

static double rescale_error (double err, const double result_abs, const double result_asc) ;

static double
rescale_error (double err, const double result_abs, const double result_asc)
{
  err = fabs(err) ;

  if (result_asc != 0 && err != 0)
      {
        double scale = pow((200 * err / result_asc), 1.5) ;

        if (scale < 1)
          {
            err = result_asc * scale ;
          }
        else
          {
            err = result_asc ;
          }
      }
  if (result_abs > GSL_DBL_MIN / (50 * GSL_DBL_EPSILON))
    {
      double min_err = 50 * GSL_DBL_EPSILON * result_abs ;

      if (min_err > err)
        {
          err = min_err ;
        }
    }

  return err ;
}


#include "compute_signal.h"
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_histogram.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "parameters.h"

void compute_signal(double * signal, const size_t length, const double delta,
    gsl_rng * r, gsl_histogram * hist){

  static double x0 = XINIT;

  puts("Building signal ...");

  double x = x0;
  double t_begin = 0.0; //Distance from the beginning of time discretization
                        //interval to current point in time

  for(size_t j=0; j<length; j++){
    //Perfom integration using method of rectangles.
    double sum = 0.0;         //Sum of signal areas
    double delta_t = t_begin; //part of time step in the new interval

    while(t_begin < delta) {
      sum += x*delta_t;

      double z = gsl_ran_gaussian_ziggurat(r,1.0);
      //Milstein approximation:
      x += 0.5*KAPPA*KAPPA*XMIN + KAPPA*x*z + 0.5*KAPPA*KAPPA*x*(z*z-1.0);
      //Euler-Marujama approximation:
      //x += 0.5*KAPPA*KAPPA*XMIN + KAPPA*x*z

      if(x > XOVER) {x = XINIT; puts("Too large");}
      if(x < 0) {x = -x; puts("Negative");}

      delta_t = KAPPA*KAPPA/(SIGMA*SIGMA*x);

      gsl_histogram_accumulate(hist, x, delta_t);

      t_begin += delta_t; //increase distance from the beginning
    }

    t_begin -= delta;

    /* remaining part of the time step is equal to the difference of the full
     * time step and of the part of the time step outside the interval.
     * Part outside the interval is t_begin */
    sum += x*(delta_t - t_begin);
    signal[j] = sum/delta; //assign effective height to the signal.
  }

  x0 = x;
}


#include <math.h>
#include <stdio.h>
//#include "gsl_headers.h"
#include <iostream>
//#include "laplaceEP.h"
//#include "matrix.h"
#include <time.h>

//#include <dai/alldai.h>
//#include <dai/bp.h>
// #include <map>
// #include <boost/shared_ptr.hpp>
// #include <string>
//
#include <gsl/gsl_sf_exp.h>
#include <gsl/gsl_sf_log.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_math.h>
#include "gsl/gsl_cdf.h"
#include "gsl/gsl_randist.h"

//Transformations
double fre_1(double x, double func, double mu, double w);
double f_1(double x, double func, double mu, double w);
// double f(double x, double w);

// General functions
double compute_vector_mean(int N, double missing, gsl_vector *v);
double compute_vector_var(int N, double missing, gsl_vector *v);
double compute_vector_max(int N, double missing, gsl_vector *v);
double compute_vector_min(int N, double missing, gsl_vector *v);
int factorial (int N);
int poissrnd(double lambda);
//gsl_matrix *double2gsl(double *Amat, int nRows, int nCols);
void matrix_multiply(gsl_matrix *A,gsl_matrix *B,gsl_matrix *C,double alpha,double beta,CBLAS_TRANSPOSE_t TransA,CBLAS_TRANSPOSE_t TransB);
double *column_to_row_major_order(double *A,int nRows,int nCols);
//double *row_to_column_major_order(double *A,int nRows,int nCols);
double det_get(gsl_matrix *Amat, int Arows, int Acols, int inPlace);
double lndet_get(gsl_matrix *Amat, int Arows, int Acols, int inPlace);
// gsl_matrix *inverse(gsl_matrix *Amat, int Asize);
void inverse(gsl_matrix *Amat, int Asize);
double trace(gsl_matrix *Amat, int Asize);
double logFun(double x);
double expFun(double x);
//Sampling functions
int mnrnd(double *p, int nK);
void mvnrnd(gsl_vector *X, gsl_matrix *Sigma,gsl_vector *Mu, int K, const gsl_rng *seed);
double truncnormrnd(double mu, double sigma, double xlo, double xhi);