/* ---------- statsimodule.c ----------------- */

#include <Python.h>
#include "stats.h"
/*
 * This is an extension implementing the 'stats'
 * module which is intended to be wrapped by a
 * python module; it provides a simple internal
 * interface.
 *
 * the 'find_variance' entry point accepts
 * a single parameter, which is expected to
 * be a read-only buffer of floats (at least one)
 */
static PyObject *
statsi_find_variance(PyObject *self, PyObject *args)
{
	double mean, var;
	char *data_ptr;
	int nbytes,n;

	/*
	 * expect a single parameter, which is a string
	 * or buffer, containing value in native order.
	 * The API call below gets us the address and len
	 * of the string, or fails.
	 */
    if (!PyArg_ParseTuple(args, "s#", &data_ptr, &nbytes))
        return NULL;
	/*
	 * check the len - it must be a multiple of sizeof(float)
	 */
	n = nbytes/sizeof(float);
	if( n <= 0 || n*sizeof(float) != nbytes ){
		PyErr_SetString( PyExc_ValueError,
				 "find_variance: bad length");
		return 0;
	}
		
	/*
	 * call the actual C routine with all the floats.
	 * Note: there is a risk here that the data will not
	 * be aligned on a suitable boundary for floats. This
	 * is not an issue on X86 hardware; also, the python
	 * wrapper can guarantee this, if needed, by using 
	 * array.array type instead of a string.
	 */
	var = find_variance( (float const*) data_ptr, n , & mean );
	/*
	 * return results
	 */
    return Py_BuildValue("dd", var, mean);
}
/*
 * table of module methods. If the module has multiple
 * Python-callable functions, they are all listed here.
 */
static PyMethodDef StatsiMethods[] = {
{"find_variance",  statsi_find_variance,
	METH_VARARGS,  ""},
    {NULL, NULL, 0, NULL}        /* Sentinel */
};
/*
 * The module initialization function
 */
PyMODINIT_FUNC
initstatsi(void)
{
    Py_InitModule("statsi", StatsiMethods);
}

