Attachment 'C_arraytest.c'
Download 1 /* A file to test imorting C modules for handling arrays to Python */
2
3 #include "Python.h"
4 #include "arrayobject.h"
5 #include "C_arraytest.h"
6 #include <math.h>
7
8 /* #### Globals #################################### */
9
10 /* ==== Set up the methods table ====================== */
11 static PyMethodDef _C_arraytestMethods[] = {
12 {"vecfcn1", vecfcn1, METH_VARARGS},
13 {"vecsq", vecsq, METH_VARARGS},
14 {"rowx2", rowx2, METH_VARARGS},
15 {"rowx2_v2", rowx2_v2, METH_VARARGS},
16 {"matsq", matsq, METH_VARARGS},
17 {"contigmat", contigmat, METH_VARARGS},
18 {"intfcn1", intfcn1, METH_VARARGS},
19 {NULL, NULL} /* Sentinel - marks the end of this structure */
20 };
21
22 /* ==== Initialize the C_test functions ====================== */
23 // Module name must be _C_arraytest in compile and linked
24 void init_C_arraytest() {
25 (void) Py_InitModule("_C_arraytest", _C_arraytestMethods);
26 import_array(); // Must be present for NumPy. Called first after above line.
27 }
28
29 /* #### Vector Extensions ############################## */
30
31 /* ==== vector function - manipulate vector in place ======================
32 Multiply the input by 2 x dfac and put in output
33 Interface: vecfcn1(vec1, vec2, str1, d1)
34 vec1, vec2 are NumPy vectors,
35 str1 is Python string, d1 is Python float (double)
36 Returns integer 1 if successful */
37 static PyObject *vecfcn1(PyObject *self, PyObject *args)
38 {
39 PyArrayObject *vecin, *vecout; // The python objects to be extracted from the args
40 double *cin, *cout; // The C vectors to be created to point to the
41 // python vectors, cin and cout point to the row
42 // of vecin and vecout, respectively
43 int i,j,n;
44 const char *str;
45 double dfac;
46
47 /* Parse tuples separately since args will differ between C fcns */
48 if (!PyArg_ParseTuple(args, "O!O!sd", &PyArray_Type, &vecin,
49 &PyArray_Type, &vecout, &str, &dfac)) return NULL;
50 if (NULL == vecin) return NULL;
51 if (NULL == vecout) return NULL;
52
53 // Print out input string
54 printf("Input string: %s\n", str);
55
56 /* Check that objects are 'double' type and vectors
57 Not needed if python wrapper function checks before call to this routine */
58 if (not_doublevector(vecin)) return NULL;
59 if (not_doublevector(vecout)) return NULL;
60
61 /* Change contiguous arrays into C * arrays */
62 cin=pyvector_to_Carrayptrs(vecin);
63 cout=pyvector_to_Carrayptrs(vecout);
64
65 /* Get vector dimension. */
66 n=vecin->dimensions[0];
67
68 /* Operate on the vectors */
69 for ( i=0; i<n; i++) {
70 cout[i]=2.0*dfac*cin[i];
71 }
72
73 return Py_BuildValue("i", 1);
74 }
75
76 /* ==== Square vector components & multiply by a float =========================
77 Returns a NEW NumPy vector array
78 interface: vecsq(vec1, x1)
79 vec1 is NumPy vector, x1 is Python float (double)
80 returns a NumPy vector */
81 static PyObject *vecsq(PyObject *self, PyObject *args) {
82 PyArrayObject *vecin, *vecout;
83 double *cin, *cout, dfactor; // The C vectors to be created to point to the
84 // python vectors, cin and cout point to the row
85 // of vecin and vecout, respectively
86 int i,j,n,m, dims[2];
87
88 /* Parse tuples separately since args will differ between C fcns */
89 if (!PyArg_ParseTuple(args, "O!d",
90 &PyArray_Type, &vecin, &dfactor)) return NULL;
91 if (NULL == vecin) return NULL;
92
93 /* Check that object input is 'double' type and a vector
94 Not needed if python wrapper function checks before call to this routine */
95 if (not_doublevector(vecin)) return NULL;
96
97 /* Get the dimension of the input */
98 n=dims[0]=vecin->dimensions[0];
99
100 /* Make a new double vector of same dimension */
101 vecout=(PyArrayObject *) PyArray_FromDims(1,dims,NPY_DOUBLE);
102
103 /* Change contiguous arrays into C *arrays */
104 cin=pyvector_to_Carrayptrs(vecin);
105 cout=pyvector_to_Carrayptrs(vecout);
106
107 /* Do the calculation. */
108 for ( i=0; i<n; i++) {
109 cout[i]= dfactor*cin[i]*cin[i];
110 }
111
112 return PyArray_Return(vecout);
113 }
114
115 /* #### Vector Utility functions ######################### */
116
117 /* ==== Make a Python Array Obj. from a PyObject, ================
118 generates a double vector w/ contiguous memory which may be a new allocation if
119 the original was not a double type or contiguous
120 !! Must DECREF the object returned from this routine unless it is returned to the
121 caller of this routines caller using return PyArray_Return(obj) or
122 PyArray_BuildValue with the "N" construct !!!
123 */
124 PyArrayObject *pyvector(PyObject *objin) {
125 return (PyArrayObject *) PyArray_ContiguousFromObject(objin,
126 NPY_DOUBLE, 1,1);
127 }
128 /* ==== Create 1D Carray from PyArray ======================
129 Assumes PyArray is contiguous in memory. */
130 double *pyvector_to_Carrayptrs(PyArrayObject *arrayin) {
131 int i,n;
132
133 n=arrayin->dimensions[0];
134 return (double *) arrayin->data; /* pointer to arrayin data as double */
135 }
136 /* ==== Check that PyArrayObject is a double (Float) type and a vector ==============
137 return 1 if an error and raise exception */
138 int not_doublevector(PyArrayObject *vec) {
139 if (vec->descr->type_num != NPY_DOUBLE || vec->nd != 1) {
140 PyErr_SetString(PyExc_ValueError,
141 "In not_doublevector: array must be of type Float and 1 dimensional (n).");
142 return 1; }
143 return 0;
144 }
145
146 /* #### Matrix Extensions ############################## */
147
148 /* ==== Row x 2 function - manipulate matrix in place ======================
149 Multiply the 2nd row of the input by 2 and put in output
150 interface: rowx2(mat1, mat2)
151 mat1 and mat2 are NumPy matrices
152 Returns integer 1 if successful */
153 static PyObject *rowx2(PyObject *self, PyObject *args)
154 {
155 PyArrayObject *matin, *matout; // The python objects to be extracted from the args
156 double **cin, **cout; // The C matrices to be created to point to the
157 // python matrices, cin and cout point to the rows
158 // of matin and matout, respectively
159 int i,j,n,m;
160
161 /* Parse tuples separately since args will differ between C fcns */
162 if (!PyArg_ParseTuple(args, "O!O!", &PyArray_Type, &matin,
163 &PyArray_Type, &matout)) return NULL;
164 if (NULL == matin) return NULL;
165 if (NULL == matout) return NULL;
166
167 /* Check that objects are 'double' type and matrices
168 Not needed if python wrapper function checks before call to this routine */
169 if (not_doublematrix(matin)) return NULL;
170 if (not_doublematrix(matout)) return NULL;
171
172 /* Change contiguous arrays into C ** arrays (Memory is Allocated!) */
173 cin=pymatrix_to_Carrayptrs(matin);
174 cout=pymatrix_to_Carrayptrs(matout);
175
176 /* Get matrix dimensions. */
177 n=matin->dimensions[0];
178 m=matin->dimensions[1];
179
180 /* Operate on the matrices */
181 for ( i=0; i<n; i++) {
182 for ( j=0; j<m; j++) {
183 if (i==1) cout[i][j]=2.0*cin[i][j];
184 } }
185
186 /* Free memory, close file and return */
187 free_Carrayptrs(cin);
188 free_Carrayptrs(cout);
189 return Py_BuildValue("i", 1);
190 }
191 /* ==== Row x 2 function- Version 2. - manipulate matrix in place ======================
192 Multiply the 2nd row of the input by 2 and put in output
193 interface: rowx2(mat1, mat2)
194 mat1 and mat2 are NumPy matrices
195 Returns integer 1 if successful
196 Uses the utility function pymatrix to make NumPy C objects from PyObjects
197 */
198 static PyObject *rowx2_v2(PyObject *self, PyObject *args)
199 {
200 PyObject *Pymatin, *Pymatout; // The python objects to be extracted from the args
201 PyArrayObject *matin, *matout; // The python array objects to be extracted from python objects
202 double **cin, **cout; // The C matrices to be created to point to the
203 // python matrices, cin and cout point to the rows
204 // of matin and matout, respectively
205 int i,j,n,m;
206
207 /* Parse tuples separately since args will differ between C fcns */
208 if (!PyArg_ParseTuple(args, "OO", &Pymatin, &Pymatout)) return NULL;
209 if (NULL == Pymatin) return NULL;
210 if (NULL == Pymatout) return NULL;
211
212 /* Convert Python Objects to Python Array Objects */
213 matin= pymatrix(Pymatin);
214 matout= pymatrix(Pymatout);
215
216 /* Check that objects are 'double' type and matrices
217 Not needed if python wrapper function checks before call to this routine */
218 if (not_doublematrix(matin)) return NULL;
219 if (not_doublematrix(matout)) return NULL;
220
221 /* Change contiguous arrays into C ** arrays (Memory is Allocated!) */
222 cin=pymatrix_to_Carrayptrs(matin);
223 cout=pymatrix_to_Carrayptrs(matout);
224
225 /* Get matrix dimensions. */
226 n=matin->dimensions[0];
227 m=matin->dimensions[1];
228
229 /* Operate on the matrices */
230 for ( i=0; i<n; i++) {
231 for ( j=0; j<m; j++) {
232 if (i==1) cout[i][j]=2.0*cin[i][j];
233 } }
234
235 /* Free memory, close file and return */
236 free_Carrayptrs(cin);
237 free_Carrayptrs(cout);
238 return Py_BuildValue("i", 1);
239 }
240 /* ==== Square matrix components function & multiply by int and float =========
241 Returns a NEW NumPy array
242 interface: matsq(mat1, i1, d1)
243 mat1 is NumPy matrix, i1 is Python integer, d1 is Python float (double)
244 returns a NumPy matrix */
245 static PyObject *matsq(PyObject *self, PyObject *args)
246 {
247 PyArrayObject *matin, *matout;
248 double **cin, **cout, dfactor;
249 int i,j,n,m, dims[2], ifactor;
250
251 /* Parse tuples separately since args will differ between C fcns */
252 if (!PyArg_ParseTuple(args, "O!id",
253 &PyArray_Type, &matin, &ifactor, &dfactor)) return NULL;
254 if (NULL == matin) return NULL;
255
256 /* Check that object input is 'double' type and a matrix
257 Not needed if python wrapper function checks before call to this routine */
258 if (not_doublematrix(matin)) return NULL;
259
260 /* Get the dimensions of the input */
261 n=dims[0]=matin->dimensions[0];
262 m=dims[1]=matin->dimensions[1];
263
264 /* Make a new double matrix of same dims */
265 matout=(PyArrayObject *) PyArray_FromDims(2,dims,NPY_DOUBLE);
266
267 /* Change contiguous arrays into C ** arrays (Memory is Allocated!) */
268 cin=pymatrix_to_Carrayptrs(matin);
269 cout=pymatrix_to_Carrayptrs(matout);
270
271 /* Do the calculation. */
272 for ( i=0; i<n; i++) {
273 for ( j=0; j<m; j++) {
274 cout[i][j]= ifactor*dfactor*cin[i][j]*cin[i][j];
275 } }
276
277 /* Free memory, close file and return */
278 free_Carrayptrs(cin);
279 free_Carrayptrs(cout);
280 return PyArray_Return(matout);
281 }
282
283 /* ==== Operate on Matrix components as contiguous memory =========================
284 Shows how to access the array data as a contiguous block of memory. Used, for example,
285 in matrix classes implemented as contiquous memory rather than as n arrays of
286 pointers to the data "rows"
287
288 Returns a NEW NumPy array
289 interface: contigmat(mat1, x1)
290 mat1 is NumPy matrix, x1 is Python float (double)
291 returns a NumPy matrix */
292 static PyObject *contigmat(PyObject *self, PyObject *args)
293 {
294 PyArrayObject *matin, *matout;
295 double *cin, *cout, x1; // Pointers to the contiguous data in the matrices to
296 // be used by C (e.g. passed to a program that uses
297 // matrix classes implemented as contiquous memory rather
298 // than as n arrays of pointers to the data "rows"
299 int i,j,n,m, dims[2], ncomps; // ncomps=n*m=total number of matrix components in mat1
300
301 /* Parse tuples separately since args will differ between C fcns */
302 if (!PyArg_ParseTuple(args, "O!d",
303 &PyArray_Type, &matin, &x1)) return NULL;
304 if (NULL == matin) return NULL;
305
306 /* Check that object input is 'double' type and a matrix
307 Not needed if python wrapper function checks before call to this routine */
308 if (not_doublematrix(matin)) return NULL;
309
310 /* Get the dimensions of the input */
311 n=dims[0]=matin->dimensions[0];
312 m=dims[1]=matin->dimensions[1];
313 ncomps=n*m;
314
315 /* Make a new double matrix of same dims */
316 matout=(PyArrayObject *) PyArray_FromDims(2,dims,NPY_DOUBLE);
317
318 /* Change contiguous arrays into C * arrays pointers to PyArrayObject data */
319 cin=pyvector_to_Carrayptrs(matin);
320 cout=pyvector_to_Carrayptrs(matout);
321
322 /* Do the calculation. */
323 printf("In contigmat, cout (as contiguous memory) =\n");
324 for ( i=0; i<ncomps; i++) {
325 cout[i]= cin[i]-x1;
326 printf("%e ",cout[i]);
327 }
328 printf("\n");
329
330 return PyArray_Return(matout);
331 }
332
333 /* #### Matrix Utility functions ######################### */
334
335 /* ==== Make a Python Array Obj. from a PyObject, ================
336 generates a double matrix w/ contiguous memory which may be a new allocation if
337 the original was not a double type or contiguous
338 !! Must DECREF the object returned from this routine unless it is returned to the
339 caller of this routines caller using return PyArray_Return(obj) or
340 PyArray_BuildValue with the "N" construct !!!
341 */
342 PyArrayObject *pymatrix(PyObject *objin) {
343 return (PyArrayObject *) PyArray_ContiguousFromObject(objin,
344 NPY_DOUBLE, 2,2);
345 }
346 /* ==== Create Carray from PyArray ======================
347 Assumes PyArray is contiguous in memory.
348 Memory is allocated! */
349 double **pymatrix_to_Carrayptrs(PyArrayObject *arrayin) {
350 double **c, *a;
351 int i,n,m;
352
353 n=arrayin->dimensions[0];
354 m=arrayin->dimensions[1];
355 c=ptrvector(n);
356 a=(double *) arrayin->data; /* pointer to arrayin data as double */
357 for ( i=0; i<n; i++) {
358 c[i]=a+i*m; }
359 return c;
360 }
361 /* ==== Allocate a double *vector (vec of pointers) ======================
362 Memory is Allocated! See void free_Carray(double ** ) */
363 double **ptrvector(long n) {
364 double **v;
365 v=(double **)malloc((size_t) (n*sizeof(double)));
366 if (!v) {
367 printf("In **ptrvector. Allocation of memory for double array failed.");
368 exit(0); }
369 return v;
370 }
371 /* ==== Free a double *vector (vec of pointers) ========================== */
372 void free_Carrayptrs(double **v) {
373 free((char*) v);
374 }
375 /* ==== Check that PyArrayObject is a double (Float) type and a matrix ==============
376 return 1 if an error and raise exception */
377 int not_doublematrix(PyArrayObject *mat) {
378 if (mat->descr->type_num != NPY_DOUBLE || mat->nd != 2) {
379 PyErr_SetString(PyExc_ValueError,
380 "In not_doublematrix: array must be of type Float and 2 dimensional (n x m).");
381 return 1; }
382 return 0;
383 }
384
385 /* #### Integer 2D Array Extensions ############################## */
386
387 /* ==== Integer function - manipulate integer 2D array in place ======================
388 Replace >=0 integer with 1 and < 0 integer with 0 and put in output
389 interface: intfcn1(int1, afloat)
390 int1 is a NumPy integer 2D array, afloat is a Python float
391 Returns integer 1 if successful */
392 static PyObject *intfcn1(PyObject *self, PyObject *args)
393 {
394 PyArrayObject *intin, *intout; // The python objects to be extracted from the args
395 int **cin, **cout; // The C integer 2D arrays to be created to point to the
396 // python integer 2D arrays, cin and cout point to the rows
397 // of intin and intout, respectively
398 int i,j,n,m, dims[2];
399 double afloat;
400
401 /* Parse tuples separately since args will differ between C fcns */
402 if (!PyArg_ParseTuple(args, "O!d",
403 &PyArray_Type, &intin, &afloat)) return NULL;
404 if (NULL == intin) return NULL;
405
406 printf("In intfcn1, the input Python float = %e, a C double\n",afloat);
407
408 /* Check that object input is int type and a 2D array
409 Not needed if python wrapper function checks before call to this routine */
410 if (not_int2Darray(intin)) return NULL;
411
412 /* Get the dimensions of the input */
413 n=dims[0]=intin->dimensions[0];
414 m=dims[1]=intin->dimensions[1];
415
416 /* Make a new int array of same dims */
417 intout=(PyArrayObject *) PyArray_FromDims(2,dims,NPY_LONG);
418
419 /* Change contiguous arrays into C ** arrays (Memory is Allocated!) */
420 cin=pyint2Darray_to_Carrayptrs(intin);
421 cout=pyint2Darray_to_Carrayptrs(intout);
422
423 /* Do the calculation. */
424 for ( i=0; i<n; i++) {
425 for ( j=0; j<m; j++) {
426 if (cin[i][j] >= 0) {
427 cout[i][j]= 1; }
428 else {
429 cout[i][j]= 0; }
430 } }
431
432 printf("In intfcn1, the output array is,\n\n");
433
434 for ( i=0; i<n; i++) {
435 for ( j=0; j<m; j++) {
436 printf("%d ",cout[i][j]);
437 }
438 printf("\n");
439 }
440 printf("\n");
441
442 /* Free memory, close file and return */
443 free_Cint2Darrayptrs(cin);
444 free_Cint2Darrayptrs(cout);
445 return PyArray_Return(intout);
446 }
447 /* #### Integer Array Utility functions ######################### */
448
449 /* ==== Make a Python int Array Obj. from a PyObject, ================
450 generates a 2D integer array w/ contiguous memory which may be a new allocation if
451 the original was not an integer type or contiguous
452 !! Must DECREF the object returned from this routine unless it is returned to the
453 caller of this routines caller using return PyArray_Return(obj) or
454 PyArray_BuildValue with the "N" construct !!!
455 */
456 PyArrayObject *pyint2Darray(PyObject *objin) {
457 return (PyArrayObject *) PyArray_ContiguousFromObject(objin,
458 NPY_LONG, 2,2);
459 }
460 /* ==== Create integer 2D Carray from PyArray ======================
461 Assumes PyArray is contiguous in memory.
462 Memory is allocated! */
463 int **pyint2Darray_to_Carrayptrs(PyArrayObject *arrayin) {
464 int **c, *a;
465 int i,n,m;
466
467 n=arrayin->dimensions[0];
468 m=arrayin->dimensions[1];
469 c=ptrintvector(n);
470 a=(int *) arrayin->data; /* pointer to arrayin data as int */
471 for ( i=0; i<n; i++) {
472 c[i]=a+i*m; }
473 return c;
474 }
475 /* ==== Allocate a a *int (vec of pointers) ======================
476 Memory is Allocated! See void free_Carray(int ** ) */
477 int **ptrintvector(long n) {
478 int **v;
479 v=(int **)malloc((size_t) (n*sizeof(int)));
480 if (!v) {
481 printf("In **ptrintvector. Allocation of memory for int array failed.");
482 exit(0); }
483 return v;
484 }
485 /* ==== Free an int *vector (vec of pointers) ========================== */
486 void free_Cint2Darrayptrs(int **v) {
487 free((char*) v);
488 }
489 /* ==== Check that PyArrayObject is an int (integer) type and a 2D array ==============
490 return 1 if an error and raise exception
491 Note: Use NY_LONG for NumPy integer array, not NP_INT */
492 int not_int2Darray(PyArrayObject *mat) {
493 if (mat->descr->type_num != NPY_LONG || mat->nd != 2) {
494 PyErr_SetString(PyExc_ValueError,
495 "In not_int2Darray: array must be of type int and 2 dimensional (n x m).");
496 return 1; }
497 return 0;
498 }
499
500
501
502
503
504
505
506 // EOF
507
508
509
510
New Attachment
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.- [get | view] (2006-12-13 18:39:14, 18.1 KB) [[attachment:C_arraytest.c]]
- [get | view] (2006-12-13 16:13:44, 18.1 KB) [[attachment:C_arraytest.c_v2]]
- [get | view] (2006-12-13 18:39:03, 1.4 KB) [[attachment:C_arraytest.h]]
- [get | view] (2006-12-13 16:13:23, 1.4 KB) [[attachment:C_arraytest.h_v2]]
- [get | view] (2006-12-13 16:14:10, 316.1 KB) [[attachment:Cext_v2.tar.gz]]