#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include #include #include "C_buildMomentsMatrix.h" #include void buildMomentsMatrix(double *M, int m[3], int n[3], double *Ym[3], double *Yn[3]) { int im[3], in[3]; int ndim = n[0] * n[1] * n[2]; for (im[0]=0; im[0] < m[0]; ++im[0]) { for (in[0]=0; in[0] < n[0]; ++in[0]) { double Y00 = Ym[0][im[0]] * Yn[0][in[0]]; for (im[1]=0; im[1] < m[1]; ++im[1]) { for (in[1]=0; in[1] < n[1]; ++in[1]) { double Y0011 = Y00 * Ym[1][im[1]] * Yn[1][in[1]]; int mm = (im[0] * m[1] + im[1]) * m[2]; for (im[2]=0; im[2] < m[2]; ++im[2], ++mm) { double Y00112 = Y0011 * Ym[2][im[2]]; int nn = (in[0] * n[1] + in[1]) * n[2]; int mn = mm * ndim + nn; for (in[2]=0; in[2] < n[2]; ++in[2], ++mn) { M[mn] += Y00112 * Yn[2][in[2]]; } } } } } } } /* ==== Set up the methods table ====================== */ static PyMethodDef _C_buildMomentsMatrixMethods[] = { {"vecfcn1", vecfcn1, METH_VARARGS}, {"vecsq", vecsq, METH_VARARGS}, {"rowx2", rowx2, METH_VARARGS}, {"rowx2_v2", rowx2_v2, METH_VARARGS}, {"matsq", matsq, METH_VARARGS}, {"contigmat", contigmat, METH_VARARGS}, {"intfcn1", intfcn1, METH_VARARGS}, {"add_event", add_event, METH_VARARGS}, {NULL, NULL} /* Sentinel - marks the end of this structure */ }; // Module definition // The arguments of this structure tell Python what to call your extension, // what it's methods are and where to look for it's method definitions static struct PyModuleDef C_buildMomentsMatrix_definition = { PyModuleDef_HEAD_INIT, "buildMomentsMatrix", "A Python module with accelerated matrix methods", -1, _C_buildMomentsMatrixMethods }; /* ==== Initialize the extension module (Python2 style) ====== */ //void init_C_buildMomentsMatrix() { // (void) Py_InitModule("_C_buildMomentsMatrix", _C_buildMomentsMatrixMethods); // import_array(); // Must be present for NumPy. Called first after above line. //} // Module initialization (Python3 style) // Python calls this function when importing your extension. It is important // that this function is named PyInit_[[your_module_name]] exactly, and matches // the name keyword argument in setup.py's setup() call. PyMODINIT_FUNC PyInit_C_buildMomentsMatrix(void) { Py_Initialize(); import_array(); // Must be present for NumPy. Called first after above line. return PyModule_Create(&C_buildMomentsMatrix_definition); } /* #### Vector Extensions ############################## */ /* ==== vector function - manipulate vector in place ====================== Multiply the input by 2 x dfac and put in output Interface: vecfcn1(vec1, vec2, str1, d1) vec1, vec2 are NumPy vectors, str1 is Python string, d1 is Python float (double) Returns integer 1 if successful */ static PyObject *vecfcn1(PyObject *self, PyObject *args) { PyArrayObject *vecin, *vecout; // The python objects to be extracted from the args double *cin, *cout; // The C vectors to be created to point to the // python vectors, cin and cout point to the row // of vecin and vecout, respectively int i,j,n; const char *str; double dfac; /* Parse tuples separately since args will differ between C fcns */ if (!PyArg_ParseTuple(args, "O!O!sd", &PyArray_Type, &vecin, &PyArray_Type, &vecout, &str, &dfac)) return NULL; if (NULL == vecin) return NULL; if (NULL == vecout) return NULL; // Print out input string printf("Input string: %s\n", str); /* Check that objects are 'double' type and vectors Not needed if python wrapper function checks before call to this routine */ if (not_doublevector(vecin)) return NULL; if (not_doublevector(vecout)) return NULL; /* Change contiguous arrays into C * arrays */ cin=pyvector_to_Carrayptrs(vecin); cout=pyvector_to_Carrayptrs(vecout); /* Get vector dimension. */ n=PyArray_DIM(vecin,0); /* Operate on the vectors */ for ( i=0; itype_num != NPY_DOUBLE || PyArray_NDIM(vec) != 1) { PyErr_SetString(PyExc_ValueError, "In not_doublevector: array must be of type Float and 1 dimensional (n)."); return 1; } return 0; } /* #### Matrix Extensions ############################## */ /* ==== Row x 2 function - manipulate matrix in place ====================== Multiply the 2nd row of the input by 2 and put in output interface: rowx2(mat1, mat2) mat1 and mat2 are NumPy matrices Returns integer 1 if successful */ static PyObject *rowx2(PyObject *self, PyObject *args) { PyArrayObject *matin, *matout; // The python objects to be extracted from the args double **cin, **cout; // The C matrices to be created to point to the // python matrices, cin and cout point to the rows // of matin and matout, respectively int i,j,n,m; /* Parse tuples separately since args will differ between C fcns */ if (!PyArg_ParseTuple(args, "O!O!", &PyArray_Type, &matin, &PyArray_Type, &matout)) return NULL; if (NULL == matin) return NULL; if (NULL == matout) return NULL; /* Check that objects are 'double' type and matrices Not needed if python wrapper function checks before call to this routine */ if (not_doublematrix(matin)) return NULL; if (not_doublematrix(matout)) return NULL; /* Change contiguous arrays into C ** arrays (Memory is Allocated!) */ cin=pymatrix_to_Carrayptrs(matin); cout=pymatrix_to_Carrayptrs(matout); /* Get matrix dimensions. */ n=PyArray_DIM(matin,0); m=PyArray_DIM(matin,1); /* Operate on the matrices */ for ( i=0; itype_num != NPY_DOUBLE || PyArray_NDIM(mat) != 2) { PyErr_SetString(PyExc_ValueError, "In not_doublematrix: array must be of type Float and 2 dimensional (n x m)."); return 1; } return 0; } /* #### Integer 2D Array Extensions ############################## */ /* ==== Integer function - manipulate integer 2D array in place ====================== Replace >=0 integer with 1 and < 0 integer with 0 and put in output interface: intfcn1(int1, afloat) int1 is a NumPy integer 2D array, afloat is a Python float Returns integer 1 if successful */ static PyObject *intfcn1(PyObject *self, PyObject *args) { PyArrayObject *intin, *intout; // The python objects to be extracted from the args int **cin, **cout; // The C integer 2D arrays to be created to point to the // python integer 2D arrays, cin and cout point to the rows // of intin and intout, respectively int i,j,n,m, dims[2]; double afloat; /* Parse tuples separately since args will differ between C fcns */ if (!PyArg_ParseTuple(args, "O!d", &PyArray_Type, &intin, &afloat)) return NULL; if (NULL == intin) return NULL; printf("In intfcn1, the input Python float = %e, a C double\n",afloat); /* Check that object input is int type and a 2D array Not needed if python wrapper function checks before call to this routine */ if (not_int2Darray(intin)) return NULL; /* Get the dimensions of the input */ n=dims[0]=PyArray_DIM(intin,0); m=dims[1]=PyArray_DIM(intin,1); /* Make a new int array of same dims */ intout=(PyArrayObject *) PyArray_NewLikeArray(intin, NPY_KEEPORDER, 0, 1); /* Change contiguous arrays into C ** arrays (Memory is Allocated!) */ cin=pyint2Darray_to_Carrayptrs(intin); cout=pyint2Darray_to_Carrayptrs(intout); /* Do the calculation. */ for ( i=0; i= 0) { cout[i][j]= 1; } else { cout[i][j]= 0; } } } printf("In intfcn1, the output array is,\n\n"); for ( i=0; itype_num != NPY_LONG || PyArray_NDIM(mat) != 2) { PyErr_SetString(PyExc_ValueError, "In not_int2Darray: array must be of type int and 2 dimensional (n x m)."); return 1; } return 0; } /* ==== Add one event to the M moments matrix ================================== */ /* eg. add_event(M, [YmomGJ, YmomEta, YmomPi0], [YmomGJ_, YmomEta_, YmomPi0_]) */ PyObject *add_event(PyObject *self, PyObject *args) { PyArrayObject *M; PyObject *Ymom, *Ymom_; double *Ym[3], *Yn[3]; int m[3], n[3], i; double *Mad; if (!PyArg_ParseTuple(args, "O!O!O!", &PyArray_Type, &M, &PyList_Type, &Ymom, &PyList_Type, &Ymom_)) return NULL; else if (M == 0 || Ymom == 0 || Ymom_ == 0) return NULL; else if (PyList_Size(Ymom) != 3 || PyList_Size(Ymom_) != 3) return NULL; else if (not_doublematrix(M)) return NULL; for (i=0; i<3; ++i) { m[i] = PyArray_DIM((PyArrayObject*)PyList_GetItem(Ymom, i), 0); n[i] = PyArray_DIM((PyArrayObject*)PyList_GetItem(Ymom_, i), 0); Ym[i] = PyArray_DATA((PyArrayObject*)PyList_GetItem(Ymom, i)); Yn[i] = PyArray_DATA((PyArrayObject*)PyList_GetItem(Ymom_, i)); } Mad = PyArray_DATA(M); Py_BEGIN_ALLOW_THREADS buildMomentsMatrix(Mad, m, n, Ym, Yn); Py_END_ALLOW_THREADS return Py_BuildValue("i", 0); }