Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ following, but feel free to add other methods::
* ``cython`` - a pure Cython-based wrapper
* ``c_numpy`` - a pure C (with Numpy API) wrapper
* ``c_auto`` - a hand-written vectorized C wrapper with an auto-generated Python wrapper from the vectorized C wrappers.
* ``c_ufunc`` - a pure C using the Numpy UFunc API wrapper
187 changes: 187 additions & 0 deletions c_ufunc/c_ufunc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
#include "Python.h"
#include "numpy/arrayobject.h"
#include "numpy/ufuncobject.h"

#include "numpy/npy_3kcompat.h"

#include "numpy/npy_math.h"

#include "erfa.h"

typedef npy_intp intp;

static void
increment_ufunc(intp ndim, char **args, intp *steps)
{
intp i;
for (i = 0; i < ndim; ++i) {
*(args[i]) += steps[i];
}
}

#define BEGIN_LOOP \
intp dN = *dimensions++; \
intp N; \
for (N = 0; N < dN; N++) { \

#define END_LOOP(x) \
increment_ufunc((x), args, steps); \
} \

/*
*****************************************************************************
** UFUNC LOOPS **
*****************************************************************************
*/

/*///////////////////////////////////////////////////////////////////////////
eraAtco13
*/

static void
eraAtco13_wrapper(char **args, intp *dimensions, intp *steps, void *extra)
{
int ret;

BEGIN_LOOP
ret = eraAtco13(
*(double *)args[0],
*(double *)args[1],
*(double *)args[2],
*(double *)args[3],
*(double *)args[4],
*(double *)args[5],
*(double *)args[6],
*(double *)args[7],
*(double *)args[8],
*(double *)args[9],
*(double *)args[10],
*(double *)args[11],
*(double *)args[12],
*(double *)args[13],
*(double *)args[14],
*(double *)args[15],
*(double *)args[16],
*(double *)args[17],
(double *)args[18],
(double *)args[19],
(double *)args[20],
(double *)args[21],
(double *)args[22],
(double *)args[23]);
if (ret > 0) {
PyErr_SetString(PyExc_ValueError, "dubious year");
return;
} else if (ret < 0) {
PyErr_SetString(PyExc_ValueError, "unacceptable date");
return;
}
END_LOOP(24)
}

static PyUFuncGenericFunction eraAtco13_functions[] = { eraAtco13_wrapper };
static void *eraAtco13_data[] = {NULL};
static char eraAtco13_types[] = {
NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE,
NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE,
NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE,
NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE };


static void
eraD2dtf_wrapper(char **args, intp *dimensions, intp *steps, void *extra)
{
int ret;
int ihmsf[4];

BEGIN_LOOP
ret = eraD2dtf(
(char *)args[0],
*(int *)args[1],
*(double *)args[2],
*(double *)args[3],
(int *)args[4],
(int *)args[5],
(int *)args[6],
ihmsf);

if (ret > 0) {
PyErr_SetString(PyExc_ValueError, "dubious year");
return;
} else if (ret < 0) {
PyErr_SetString(PyExc_ValueError, "unacceptable date");
return;
}

*(int *)args[7] = ihmsf[0];
*(int *)args[8] = ihmsf[1];
*(int *)args[9] = ihmsf[2];
*(int *)args[10] = ihmsf[3];
END_LOOP(11)
}

static PyUFuncGenericFunction eraD2dtf_functions[] = { eraD2dtf_wrapper };
static void *eraD2dtf_data[] = {NULL};
static char eraD2dtf_types[] = {
NPY_STRING, NPY_INT, NPY_DOUBLE, NPY_DOUBLE, NPY_INT, NPY_INT, NPY_INT,
NPY_INT, NPY_INT, NPY_INT, NPY_INT };


/*///////////////////////////////////////////////////////////////////////////
module level
*/

#if defined(NPY_PY3K)
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"c_ufunc",
NULL,
-1,
NULL,
NULL,
NULL,
NULL,
NULL
};
#endif

#if defined(NPY_PY3K)
#define RETVAL m
PyObject *PyInit_c_ufunc(void)
#else
#define RETVAL
PyMODINIT_FUNC
initc_ufunc(void)
#endif
{
PyObject *m;
PyObject *d;
PyObject *f;

#if defined(NPY_PY3K)
m = PyModule_Create(&moduledef);
#else
m = Py_InitModule("c_ufunc", NULL);
#endif
if (m == NULL)
return RETVAL;

import_array();
import_ufunc();

d = PyModule_GetDict(m);

f = PyUFunc_FromFuncAndData(
eraAtco13_functions, eraAtco13_data, eraAtco13_types, 1, 18, 6,
PyUFunc_None, "eraAtco13", "eraAtco13", 0);
PyDict_SetItemString(d, "atco13", f);
Py_DECREF(f);

f = PyUFunc_FromFuncAndData(
eraD2dtf_functions, eraD2dtf_data, eraD2dtf_types, 1, 4, 7,
PyUFunc_None, "eraD2dtf", "eraD2dtf", 0);
PyDict_SetItemString(d, "eraD2dtf", f);
Py_DECREF(f);

return RETVAL;
}
19 changes: 19 additions & 0 deletions c_ufunc/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from distutils.core import setup
from distutils.extension import Extension

import numpy as np

try:
numpy_include = np.get_include()
except AttributeError:
numpy_include = np.get_numpy_include()

setup(name='c_ufunc',
ext_modules=[
Extension(
'c_ufunc',
['c_ufunc.c'],
libraries=['erfa'],
include_dirs=[numpy_include]
)],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: I think this is missing the numpy include path?

)