sampled_gaussian.cpp.html mathcode2html   
 Source file:   sampled_gaussian.cpp
 Converted:   Tue Apr 17 2012 at 11:03:44
 This documentation file will not reflect any later changes in the source file.

$$\phantom{******** If you see this on the webpage then the browser could not locate *********}$$
$$\phantom{******** jsMath/easy/load.js or the variable root is set wrong in this file *********}$$
$$\newcommand{\vector}[1]{\left[\begin{array}{c} #1 \end{array}\right]}$$ $$\newenvironment{matrix}{\left[\begin{array}{cccccccccc}} {\end{array}\right]}$$ $$\newcommand{\A}{{\cal A}}$$ $$\newcommand{\W}{{\cal W}}$$

/* Copyright 2008-2011 Research Foundation State University of New York   */

/* This file is part of QUB Express.                                      */

/* QUB Express 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 3 of the License, or      */
/* (at your option) any later version.                                    */

/* QUB Express 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,     */
/* named LICENSE.txt, in the QUB Express program directory.  If not, see  */
/* <http://www.gnu.org/licenses/>.                                        */

#include <math.h>
#include <string.h>
#include <iostream>
#include "sampled_gaussian.h"

using namespace std;

#ifndef NULL
#define NULL 0
#endif

#ifdef _WIN32
#include <boost/math/special_functions/erf.hpp>
using boost::math::erf;
#endif

SampledGaussian::SampledGaussian()
  : A(NULL)
{
  setup(0.0, 1.0, 1e-3, 6.0, 256, false);
}

SampledGaussian::SampledGaussian(const SampledGaussian& other)
  : mean(other.mean), std(other.std), resolution(other.resolution), cutoff_std(other.cutoff_std),
    s2s2i(other.s2s2i), r2(other.r2), max_for_complete(other.max_for_complete), N(other.N),
    A(other.A ? new double[other.N] : NULL), A_out(other.A_out), y2i_m(other.y2i_m), y2i_b(other.y2i_b),
    use_log(other.use_log)
{
  if ( A )
    memcpy(A, other.A, N*sizeof(double));
}

SampledGaussian& SampledGaussian::operator=(const SampledGaussian& other)
{
  delete [] A;
  mean = other.mean;
  std = other.std;
  resolution = other.resolution;
  cutoff_std = other.cutoff_std;
  s2s2i = other.s2s2i;
  r2 = other.r2;
  max_for_complete = other.max_for_complete;
  N = other.N;
  A = other.A ? new double[other.N] : NULL;
  A_out = other.A_out;
  y2i_m = other.y2i_m;
  y2i_b = other.y2i_b;
  use_log = other.use_log;
  return *this;
}

void SampledGaussian::setup(double mean_, double std_, double resolution_,
			    double cutoff_std_, int max_for_complete_, bool sample, bool use_log_)
{
  delete [] A;
  A = NULL;
  
  mean = mean_;
  std = std_;
  resolution = resolution_;
  cutoff_std = cutoff_std_;
  max_for_complete = max_for_complete_;
  use_log = use_log_;
  
  s2s2i = 1.0 / (std * sqrt(2.0));
  r2 = resolution / 2.0;
  N = (int) (2 * std * cutoff_std / resolution + 0.5);
  if ( (! sample) || (N > max_for_complete) ) {
    //cerr << "non-sampled " << mean << " +/- " << std << " -> " << N << " at " << resolution << endl;
    N = 0;
  } else {
    make_A();
  }
}

void SampledGaussian::make_A()
{
  A = new double[N];
  double cdf_b = 0.0;
  double b = mean - std * cutoff_std;
  for (int i=0; i<N; ++i) {
    double a = b;
    double cdf_a = cdf_b ? cdf_b : erf((a - mean) * s2s2i);
    b += resolution;
    cdf_b = erf((b - mean) * s2s2i);
    A[i] = 0.5 * (cdf_b - cdf_a);
    if ( use_log )
      A[i] = log(A[i]);
  }
  A_out = G_area(mean+(cutoff_std+1)*std, mean+(cutoff_std+1)*std + resolution);
  y2i_m = N / (2 * std * cutoff_std);
  y2i_b = N/2.0 - mean * y2i_m;
}

SampledGaussian::~SampledGaussian()
{
  delete [] A;
}

double SampledGaussian::operator()(double x)
{
  return N ? G_sampled(x) : G_centered(x);
}

double SampledGaussian::G_area(double a, double b)
{
  if ( use_log )
    return log(0.5 * (erf((b - mean) * s2s2i) - erf((a - mean) * s2s2i)));
  else
    return 0.5 * (erf((b - mean) * s2s2i) - erf((a - mean) * s2s2i));
}

double SampledGaussian::G_centered(double x)
{
  return G_area(x - r2, x + r2);
}

double SampledGaussian::G_sampled(double x)
{
  int i = (int) (y2i_m * x + y2i_b);
  if ( (0 <= i) && (i < N) )
    return A[i];
  return A_out;
}