/*  
    This code is written by <albanese@fbk.it>.
    (C) 2008 Fondazione Bruno Kessler - Via Santa Croce 77, 38100 Trento, ITALY.
    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 3 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, see <http://www.gnu.org/licenses/>.
*/


#include <Python.h>
#include <numpy/arrayobject.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <complex.h>
#include <gsl/gsl_sf_gamma.h>
#include <gsl/gsl_statistics_double.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_cdf.h>


static PyObject *gslpy_gamma(PyObject *self, PyObject *args, PyObject *keywds)
{
  double x, y;

  /* Parse Tuple*/
  static char *kwlist[] = {"x", NULL};
  if (!PyArg_ParseTupleAndKeywords(args, keywds, "d", kwlist, &x))
    return NULL;
  
  y = gsl_sf_gamma (x);

  return Py_BuildValue("d", y);
}


static PyObject *gslpy_fact(PyObject *self, PyObject *args, PyObject *keywds)
{
  int x;
  double y;

  /* Parse Tuple*/
  static char *kwlist[] = {"x", NULL};
  if (!PyArg_ParseTupleAndKeywords(args, keywds, "i", kwlist, &x))
    return NULL;
  
  y = gsl_sf_fact (x);

  return Py_BuildValue("d", y);
}


static PyObject *gslpy_quantile(PyObject *self, PyObject *args, PyObject *keywds)
{
  /* Inputs */
  PyObject *x = NULL; PyObject *xa = NULL;
  double f;  

  npy_intp n;
  double *xa_v, y;

  /* Parse Tuple*/
  static char *kwlist[] = {"x", "f", NULL};
  if (!PyArg_ParseTupleAndKeywords(args, keywds, "Od", kwlist, &x, &f))
    return NULL;
  
  xa = PyArray_FROM_OTF(x, NPY_DOUBLE, NPY_IN_ARRAY);
  if (xa == NULL) return NULL;
   
  xa_v = (double *) PyArray_DATA(xa);
  n = PyArray_DIM(xa, 0);

  y = gsl_stats_quantile_from_sorted_data (xa_v, 1, (size_t) n, f);

  Py_DECREF(xa);

  return Py_BuildValue("d", y);
}


static PyObject *gslpy_cdf_gaussian_P(PyObject *self, PyObject *args, PyObject *keywds)
{
  /* Inputs */
  double x;
  double sigma;  
  double y;

  /* Parse Tuple*/
  static char *kwlist[] = {"x", "sigma", NULL};
  if (!PyArg_ParseTupleAndKeywords(args, keywds, "dd", kwlist, &x, &sigma))
    return NULL;
   
  y = gsl_cdf_gaussian_P(x, sigma);

  return Py_BuildValue("d", y);
}



/* Doc strings: */
static char gslpy_gamma_doc[] = 
  "Gamma Function.\n\n"
  "Input\n\n"
  "  * *x* - [float] data\n\n"
  "Output\n\n"
  "  * *gx* - [float] gamma(x)"
  ;
  
static char gslpy_fact_doc[]  =
  "Factorial x!.\n"
  "The factorial is related to the gamma function by x! = gamma(x+1)\n\n"
  "Input\n\n"
  "  * *x* - [int] data\n\n"
  "Output\n\n"
  "  * *fx* - [float] factorial x!"
  ;

static char gslpy_quantile_doc[]  =
  "Quantile value of sorted data.\n"
  "The elements of the array must be in ascending numerical order.\n"
  "The quantile is determined by the f, a fraction between 0 and 1.\n"
  "The quantile is found by interpolation, using the formula:\n"
  "quantile = (1 - delta) x_i + delta x_{i+1}\n"
  "where i is floor((n - 1)f) and delta is (n-1)f - i.\n\n"
  "Input\n\n"
  "  * *x* - [1D numpy array float] sorted data\n"
  "  * *f* - [float] fraction between 0 and 1\n\n"
  "Output\n\n"
  "  * *q* - [float] quantile"
  ;

static char gslpy_cdf_gaussian_P_doc[] = 
  "Cumulative Distribution Functions (CDF) P(x)\n"
  "for the Gaussian distribution.\n\n"
  "Input\n\n"
  "  * *x* - [float] data\n\n"
  "  * *sigma* - [float] standard deviation \n\n"
  "Output\n\n"
  "  * *p* - [float]"
  ;


static char module_doc[]   = "GSL Functions";


/* Method table */
static PyMethodDef gslpy_methods[] = {
  {"gamma",
   (PyCFunction)gslpy_gamma,
   METH_VARARGS | METH_KEYWORDS,
   gslpy_gamma_doc},
  {"fact",
   (PyCFunction)gslpy_fact,
   METH_VARARGS | METH_KEYWORDS,
   gslpy_fact_doc},
  {"quantile",
   (PyCFunction)gslpy_quantile,
   METH_VARARGS | METH_KEYWORDS,
   gslpy_quantile_doc},
  {"cdf_gaussian_P",
   (PyCFunction)gslpy_cdf_gaussian_P,
   METH_VARARGS | METH_KEYWORDS,
   gslpy_cdf_gaussian_P_doc},
  {NULL, NULL, 0, NULL}
};


/* Init */
void initgslpy()
{
  Py_InitModule3("gslpy", gslpy_methods, module_doc);
  import_array();
}

