1
#define FORTRANOBJECT_C
2
#include "fortranobject.h"
8
This file implements: FortranObject, array_from_pyobj, copy_ND_array
10
Author: Pearu Peterson <pearu@cens.ioc.ee>
12
$Date: 2005/07/11 07:44:20 $
16
F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj)
19
fprintf(stderr, "Error loading %s\n", name);
20
if (PyErr_Occurred()) {
26
return PyDict_SetItemString(dict, name, obj);
29
/************************* FortranObject *******************************/
31
typedef PyObject *(*fortranfunc)(PyObject *,PyObject *,PyObject *,void *);
34
PyFortranObject_New(FortranDataDef* defs, f2py_void_func init) {
36
PyFortranObject *fp = NULL;
38
if (init!=NULL) /* Initialize F90 module objects */
40
if ((fp = PyObject_New(PyFortranObject, &PyFortran_Type))==NULL) return NULL;
41
if ((fp->dict = PyDict_New())==NULL) return NULL;
43
while (defs[fp->len].name != NULL) fp->len++;
44
if (fp->len == 0) goto fail;
46
for (i=0;i<fp->len;i++)
47
if (fp->defs[i].rank == -1) { /* Is Fortran routine */
48
v = PyFortranObject_NewAsAttr(&(fp->defs[i]));
49
if (v==NULL) return NULL;
50
PyDict_SetItemString(fp->dict,fp->defs[i].name,v);
52
if ((fp->defs[i].data)!=NULL) { /* Is Fortran variable or array (not allocatable) */
53
if (fp->defs[i].type == PyArray_STRING) {
54
int n = fp->defs[i].rank-1;
55
v = PyArray_New(&PyArray_Type, n, fp->defs[i].dims.d,
56
PyArray_STRING, NULL, fp->defs[i].data, fp->defs[i].dims.d[n],
60
v = PyArray_New(&PyArray_Type, fp->defs[i].rank, fp->defs[i].dims.d,
61
fp->defs[i].type, NULL, fp->defs[i].data, 0, FARRAY_FLAGS,
64
if (v==NULL) return NULL;
65
PyDict_SetItemString(fp->dict,fp->defs[i].name,v);
68
return (PyObject *)fp;
75
PyFortranObject_NewAsAttr(FortranDataDef* defs) { /* used for calling F90 module routines */
76
PyFortranObject *fp = NULL;
77
fp = PyObject_New(PyFortranObject, &PyFortran_Type);
78
if (fp == NULL) return NULL;
79
if ((fp->dict = PyDict_New())==NULL) return NULL;
82
return (PyObject *)fp;
88
fortran_dealloc(PyFortranObject *fp) {
94
static PyMethodDef fortran_methods[] = {
95
{NULL, NULL} /* sentinel */
100
fortran_doc (FortranDataDef def) {
106
size += strlen(def.doc);
107
p = (char*)malloc (size);
108
if (sprintf(p,"%s - ",def.name)==0) goto fail;
111
if (sprintf(p,"%sno docs available",p)==0)
114
if (sprintf(p,"%s%s",p,def.doc)==0)
118
PyArray_Descr *d = PyArray_DescrFromType(def.type);
119
if (sprintf(p,"%s'%c'-",p,d->type)==0) goto fail;
120
if (def.data==NULL) {
121
if (sprintf(p,"%sarray(%" INTP_FMT,p,def.dims.d[0])==0) goto fail;
122
for(i=1;i<def.rank;++i)
123
if (sprintf(p,"%s,%" INTP_FMT,p,def.dims.d[i])==0) goto fail;
124
if (sprintf(p,"%s), not allocated",p)==0) goto fail;
127
if (sprintf(p,"%sarray(%"INTP_FMT,p,def.dims.d[0])==0) goto fail;
128
for(i=1;i<def.rank;i++)
129
if (sprintf(p,"%s,%" INTP_FMT,p,def.dims.d[i])==0) goto fail;
130
if (sprintf(p,"%s)",p)==0) goto fail;
132
if (sprintf(p,"%sscalar",p)==0) goto fail;
136
if (sprintf(p,"%s\n",p)==0) goto fail;
137
if (strlen(p)>size) {
138
fprintf(stderr,"fortranobject.c:fortran_doc:len(p)=%zd>%d(size): too long doc string required, increase size\n",strlen(p),size);
141
s = PyString_FromString(p);
147
static FortranDataDef *save_def; /* save pointer of an allocatable array */
148
static void set_data(char *d,intp *f) { /* callback from Fortran */
149
if (*f) /* In fortran f=allocated(d) */
152
save_def->data = NULL;
153
/* printf("set_data: d=%p,f=%d\n",d,*f); */
157
fortran_getattr(PyFortranObject *fp, char *name) {
159
if (fp->dict != NULL) {
160
PyObject *v = PyDict_GetItemString(fp->dict, name);
166
for (i=0,j=1;i<fp->len && (j=strcmp(name,fp->defs[i].name));i++);
168
if (fp->defs[i].rank!=-1) { /* F90 allocatable array */
169
if (fp->defs[i].func==NULL) return NULL;
170
for(k=0;k<fp->defs[i].rank;++k)
171
fp->defs[i].dims.d[k]=-1;
172
save_def = &fp->defs[i];
173
(*(fp->defs[i].func))(&fp->defs[i].rank,fp->defs[i].dims.d,set_data,&flag);
175
k = fp->defs[i].rank + 1;
177
k = fp->defs[i].rank;
178
if (fp->defs[i].data !=NULL) { /* array is allocated */
179
PyObject *v = PyArray_New(&PyArray_Type, k, fp->defs[i].dims.d,
180
fp->defs[i].type, NULL, fp->defs[i].data, 0, FARRAY_FLAGS,
182
if (v==NULL) return NULL;
185
} else { /* array is not allocated */
190
if (strcmp(name,"__dict__")==0) {
194
if (strcmp(name,"__doc__")==0) {
195
PyObject *s = PyString_FromString("");
196
for (i=0;i<fp->len;i++)
197
PyString_ConcatAndDel(&s,fortran_doc(fp->defs[i]));
198
if (PyDict_SetItemString(fp->dict, name, s))
202
if ((strcmp(name,"_cpointer")==0) && (fp->len==1)) {
203
PyObject *cobj = PyCObject_FromVoidPtr((void *)(fp->defs[0].data),NULL);
204
if (PyDict_SetItemString(fp->dict, name, cobj))
208
return Py_FindMethod(fortran_methods, (PyObject *)fp, name);
212
fortran_setattr(PyFortranObject *fp, char *name, PyObject *v) {
214
PyArrayObject *arr = NULL;
215
for (i=0,j=1;i<fp->len && (j=strcmp(name,fp->defs[i].name));i++);
217
if (fp->defs[i].rank==-1) {
218
PyErr_SetString(PyExc_AttributeError,"over-writing fortran routine");
221
if (fp->defs[i].func!=NULL) { /* is allocatable array */
222
intp dims[F2PY_MAX_DIMS];
224
save_def = &fp->defs[i];
225
if (v!=Py_None) { /* set new value (reallocate if needed --
226
see f2py generated code for more
228
for(k=0;k<fp->defs[i].rank;k++) dims[k]=-1;
229
if ((arr = array_from_pyobj(fp->defs[i].type,dims,fp->defs[i].rank,F2PY_INTENT_IN,v))==NULL)
231
(*(fp->defs[i].func))(&fp->defs[i].rank,arr->dimensions,set_data,&flag);
232
} else { /* deallocate */
233
for(k=0;k<fp->defs[i].rank;k++) dims[k]=0;
234
(*(fp->defs[i].func))(&fp->defs[i].rank,dims,set_data,&flag);
235
for(k=0;k<fp->defs[i].rank;k++) dims[k]=-1;
237
memcpy(fp->defs[i].dims.d,dims,fp->defs[i].rank*sizeof(intp));
238
} else { /* not allocatable array */
239
if ((arr = array_from_pyobj(fp->defs[i].type,fp->defs[i].dims.d,fp->defs[i].rank,F2PY_INTENT_IN,v))==NULL)
242
if (fp->defs[i].data!=NULL) { /* copy Python object to Fortran array */
243
intp s = PyArray_MultiplyList(fp->defs[i].dims.d,arr->nd);
245
s = PyArray_MultiplyList(arr->dimensions,arr->nd);
247
(memcpy(fp->defs[i].data,arr->data,s*PyArray_ITEMSIZE(arr)))==NULL) {
248
if ((PyObject*)arr!=v) {
253
if ((PyObject*)arr!=v) {
256
} else return (fp->defs[i].func==NULL?-1:0);
257
return 0; /* succesful */
259
if (fp->dict == NULL) {
260
fp->dict = PyDict_New();
261
if (fp->dict == NULL)
265
int rv = PyDict_DelItemString(fp->dict, name);
267
PyErr_SetString(PyExc_AttributeError,"delete non-existing fortran attribute");
271
return PyDict_SetItemString(fp->dict, name, v);
275
fortran_call(PyFortranObject *fp, PyObject *arg, PyObject *kw) {
277
/* printf("fortran call
278
name=%s,func=%p,data=%p,%p\n",fp->defs[i].name,
279
fp->defs[i].func,fp->defs[i].data,&fp->defs[i].data); */
280
if (fp->defs[i].rank==-1) {/* is Fortran routine */
281
if ((fp->defs[i].func==NULL)) {
282
PyErr_Format(PyExc_RuntimeError, "no function to call");
285
else if (fp->defs[i].data==NULL)
287
return (*((fortranfunc)(fp->defs[i].func)))((PyObject *)fp,arg,kw,NULL);
289
return (*((fortranfunc)(fp->defs[i].func)))((PyObject *)fp,arg,kw,
290
(void *)fp->defs[i].data);
292
PyErr_Format(PyExc_TypeError, "this fortran object is not callable");
297
PyTypeObject PyFortran_Type = {
298
PyObject_HEAD_INIT(0)
300
"fortran", /*tp_name*/
301
sizeof(PyFortranObject), /*tp_basicsize*/
304
(destructor)fortran_dealloc, /*tp_dealloc*/
306
(getattrfunc)fortran_getattr, /*tp_getattr*/
307
(setattrfunc)fortran_setattr, /*tp_setattr*/
311
0, /*tp_as_sequence*/
314
(ternaryfunc)fortran_call, /*tp_call*/
317
/************************* f2py_report_atexit *******************************/
319
#ifdef F2PY_REPORT_ATEXIT
320
static int passed_time = 0;
321
static int passed_counter = 0;
322
static int passed_call_time = 0;
323
static struct timeb start_time;
324
static struct timeb stop_time;
325
static struct timeb start_call_time;
326
static struct timeb stop_call_time;
327
static int cb_passed_time = 0;
328
static int cb_passed_counter = 0;
329
static int cb_passed_call_time = 0;
330
static struct timeb cb_start_time;
331
static struct timeb cb_stop_time;
332
static struct timeb cb_start_call_time;
333
static struct timeb cb_stop_call_time;
335
extern void f2py_start_clock(void) { ftime(&start_time); }
337
void f2py_start_call_clock(void) {
339
ftime(&start_call_time);
342
void f2py_stop_clock(void) {
344
passed_time += 1000*(stop_time.time - start_time.time);
345
passed_time += stop_time.millitm - start_time.millitm;
348
void f2py_stop_call_clock(void) {
349
ftime(&stop_call_time);
350
passed_call_time += 1000*(stop_call_time.time - start_call_time.time);
351
passed_call_time += stop_call_time.millitm - start_call_time.millitm;
356
extern void f2py_cb_start_clock(void) { ftime(&cb_start_time); }
358
void f2py_cb_start_call_clock(void) {
359
f2py_cb_stop_clock();
360
ftime(&cb_start_call_time);
363
void f2py_cb_stop_clock(void) {
364
ftime(&cb_stop_time);
365
cb_passed_time += 1000*(cb_stop_time.time - cb_start_time.time);
366
cb_passed_time += cb_stop_time.millitm - cb_start_time.millitm;
369
void f2py_cb_stop_call_clock(void) {
370
ftime(&cb_stop_call_time);
371
cb_passed_call_time += 1000*(cb_stop_call_time.time - cb_start_call_time.time);
372
cb_passed_call_time += cb_stop_call_time.millitm - cb_start_call_time.millitm;
373
cb_passed_counter += 1;
374
f2py_cb_start_clock();
377
static int f2py_report_on_exit_been_here = 0;
379
void f2py_report_on_exit(int exit_flag,void *name) {
380
if (f2py_report_on_exit_been_here) {
381
fprintf(stderr," %s\n",(char*)name);
384
f2py_report_on_exit_been_here = 1;
385
fprintf(stderr," /-----------------------\\\n");
386
fprintf(stderr," < F2PY performance report >\n");
387
fprintf(stderr," \\-----------------------/\n");
388
fprintf(stderr,"Overall time spent in ...\n");
389
fprintf(stderr,"(a) wrapped (Fortran/C) functions : %8d msec\n",
391
fprintf(stderr,"(b) f2py interface, %6d calls : %8d msec\n",
392
passed_counter,passed_time);
393
fprintf(stderr,"(c) call-back (Python) functions : %8d msec\n",
394
cb_passed_call_time);
395
fprintf(stderr,"(d) f2py call-back interface, %6d calls : %8d msec\n",
396
cb_passed_counter,cb_passed_time);
398
fprintf(stderr,"(e) wrapped (Fortran/C) functions (acctual) : %8d msec\n\n",
399
passed_call_time-cb_passed_call_time-cb_passed_time);
400
fprintf(stderr,"Use -DF2PY_REPORT_ATEXIT_DISABLE to disable this message.\n");
401
fprintf(stderr,"Exit status: %d\n",exit_flag);
402
fprintf(stderr,"Modules : %s\n",(char*)name);
406
/********************** report on array copy ****************************/
408
#ifdef F2PY_REPORT_ON_ARRAY_COPY
409
static void f2py_report_on_array_copy(PyArrayObject* arr) {
410
const long arr_size = PyArray_Size((PyObject *)arr);
411
if (arr_size>F2PY_REPORT_ON_ARRAY_COPY) {
412
fprintf(stderr,"copied an array: size=%ld, elsize=%d\n",
413
arr_size, PyArray_ITEMSIZE(arr));
416
static void f2py_report_on_array_copy_fromany(void) {
417
fprintf(stderr,"created an array from object\n");
420
#define F2PY_REPORT_ON_ARRAY_COPY_FROMARR f2py_report_on_array_copy((PyArrayObject *)arr)
421
#define F2PY_REPORT_ON_ARRAY_COPY_FROMANY f2py_report_on_array_copy_fromany()
423
#define F2PY_REPORT_ON_ARRAY_COPY_FROMARR
424
#define F2PY_REPORT_ON_ARRAY_COPY_FROMANY
428
/************************* array_from_obj *******************************/
431
* File: array_from_pyobj.c
435
* Provides array_from_pyobj function that returns a contigious array
436
* object with the given dimensions and required storage order, either
437
* in row-major (C) or column-major (Fortran) order. The function
438
* array_from_pyobj is very flexible about its Python object argument
439
* that can be any number, list, tuple, or array.
441
* array_from_pyobj is used in f2py generated Python extension
444
* Author: Pearu Peterson <pearu@cens.ioc.ee>
445
* Created: 13-16 January 2002
446
* $Id: fortranobject.c,v 1.52 2005/07/11 07:44:20 pearu Exp $
450
count_nonpos(const int rank,
454
if (dims[i] <= 0) ++r;
460
static int check_and_fix_dimensions(const PyArrayObject* arr,
464
#ifdef DEBUG_COPY_ND_ARRAY
465
void dump_dims(int rank, intp* dims) {
468
for(i=0;i<rank;++i) {
469
printf("%3" INTP_FMT, dims[i]);
473
void dump_attrs(const PyArrayObject* arr) {
475
intp size = PyArray_Size((PyObject *)arr);
476
printf("\trank = %d, flags = %d, size = %" INTP_FMT "\n",
477
rank,arr->flags,size);
478
printf("\tstrides = ");
479
dump_dims(rank,arr->strides);
480
printf("\tdimensions = ");
481
dump_dims(rank,arr->dimensions);
485
#define SWAPTYPE(a,b,t) {t c; c = (a); (a) = (b); (b) = c; }
487
static int swap_arrays(PyArrayObject* arr1, PyArrayObject* arr2) {
488
SWAPTYPE(arr1->data,arr2->data,char*);
489
SWAPTYPE(arr1->nd,arr2->nd,int);
490
SWAPTYPE(arr1->dimensions,arr2->dimensions,intp*);
491
SWAPTYPE(arr1->strides,arr2->strides,intp*);
492
SWAPTYPE(arr1->base,arr2->base,PyObject*);
493
SWAPTYPE(arr1->descr,arr2->descr,PyArray_Descr*);
494
SWAPTYPE(arr1->flags,arr2->flags,int);
495
/* SWAPTYPE(arr1->weakreflist,arr2->weakreflist,PyObject*); */
499
#define ARRAY_ISCOMPATIBLE(arr,type_num) \
500
( (PyArray_ISINTEGER(arr) && PyTypeNum_ISINTEGER(type_num)) \
501
||(PyArray_ISFLOAT(arr) && PyTypeNum_ISFLOAT(type_num)) \
502
||(PyArray_ISCOMPLEX(arr) && PyTypeNum_ISCOMPLEX(type_num)) \
506
PyArrayObject* array_from_pyobj(const int type_num,
511
/* Note about reference counting
512
-----------------------------
513
If the caller returns the array to Python, it must be done with
514
Py_BuildValue("N",arr).
515
Otherwise, if obj!=arr then the caller must call Py_DECREF(arr).
517
Note on intent(cache,out,..)
518
---------------------
519
Don't expect correct data when returning intent(cache) array.
523
PyArrayObject *arr = NULL;
524
PyArray_Descr *descr = PyArray_DescrFromType(type_num);
526
if ((intent & F2PY_INTENT_HIDE)
527
|| ((intent & F2PY_INTENT_CACHE) && (obj==Py_None))
528
|| ((intent & F2PY_OPTIONAL) && (obj==Py_None))
530
/* intent(cache), optional, intent(hide) */
531
if (count_nonpos(rank,dims)) {
533
sprintf(mess,"failed to create intent(cache|hide)|optional array"
534
"-- must have defined dimensions but got (");
536
sprintf(mess+strlen(mess),"%" INTP_FMT ",",dims[i]);
537
sprintf(mess+strlen(mess),")");
538
PyErr_SetString(PyExc_ValueError,mess);
541
arr = (PyArrayObject *)
542
PyArray_New(&PyArray_Type, rank, dims, type_num,
544
!(intent&F2PY_INTENT_C),
546
if (arr==NULL) return NULL;
547
if (!(intent & F2PY_INTENT_CACHE))
548
PyArray_FILLWBYTE(arr, 0);
552
if (PyArray_Check(obj)) {
553
arr = (PyArrayObject *)obj;
555
if (intent & F2PY_INTENT_CACHE) {
557
if (PyArray_ISONESEGMENT(obj)
558
&& PyArray_ITEMSIZE((PyArrayObject *)obj)>=descr->elsize) {
559
if (check_and_fix_dimensions((PyArrayObject *)obj,rank,dims))
560
return NULL; /*XXX: set exception */
561
if (intent & F2PY_INTENT_OUT)
563
return (PyArrayObject *)obj;
565
sprintf(mess,"failed to initialize intent(cache) array");
566
if (!PyArray_ISONESEGMENT(obj))
567
sprintf(mess+strlen(mess)," -- input must be in one segment");
568
if (PyArray_ITEMSIZE(arr)<descr->elsize)
569
sprintf(mess+strlen(mess)," -- expected at least elsize=%d but got %d",
570
descr->elsize,PyArray_ITEMSIZE(arr)
572
PyErr_SetString(PyExc_ValueError,mess);
576
/* here we have always intent(in) or intent(inout) or intent(inplace) */
578
if (check_and_fix_dimensions(arr,rank,dims))
579
return NULL; /*XXX: set exception */
581
if ((! (intent & F2PY_INTENT_COPY))
582
&& PyArray_ITEMSIZE(arr)==descr->elsize
583
&& ARRAY_ISCOMPATIBLE(arr,type_num)
585
if ((intent & F2PY_INTENT_C)?PyArray_ISCARRAY(arr):PyArray_ISFARRAY(arr)) {
586
if ((intent & F2PY_INTENT_OUT)) {
589
/* Returning input array */
594
if (intent & F2PY_INTENT_INOUT) {
595
sprintf(mess,"failed to initialize intent(inout) array");
596
if ((intent & F2PY_INTENT_C) && !PyArray_ISCARRAY(arr))
597
sprintf(mess+strlen(mess)," -- input not contiguous");
598
if (!(intent & F2PY_INTENT_C) && !PyArray_ISFARRAY(arr))
599
sprintf(mess+strlen(mess)," -- input not fortran contiguous");
600
if (PyArray_ITEMSIZE(arr)!=descr->elsize)
601
sprintf(mess+strlen(mess)," -- expected elsize=%d but got %d",
603
PyArray_ITEMSIZE(arr)
605
if (!(ARRAY_ISCOMPATIBLE(arr,type_num)))
606
sprintf(mess+strlen(mess)," -- input '%c' not compatible to '%c'",
607
arr->descr->type,descr->type);
608
PyErr_SetString(PyExc_ValueError,mess);
612
/* here we have always intent(in) or intent(inplace) */
615
PyArrayObject *retarr = (PyArrayObject *) \
616
PyArray_New(&PyArray_Type, arr->nd, arr->dimensions, type_num,
618
!(intent&F2PY_INTENT_C),
622
F2PY_REPORT_ON_ARRAY_COPY_FROMARR;
623
if (PyArray_CopyInto(retarr, arr)) {
627
if (intent & F2PY_INTENT_INPLACE) {
628
if (swap_arrays(arr,retarr))
629
return NULL; /* XXX: set exception */
631
if (intent & F2PY_INTENT_OUT)
640
if ((intent & F2PY_INTENT_INOUT)
641
|| (intent & F2PY_INTENT_INPLACE)
642
|| (intent & F2PY_INTENT_CACHE)) {
643
sprintf(mess,"failed to initialize intent(inout|inplace|cache) array"
644
" -- input must be array but got %s",
645
PyString_AsString(PyObject_Str(PyObject_Type(obj)))
647
PyErr_SetString(PyExc_TypeError,mess);
652
F2PY_REPORT_ON_ARRAY_COPY_FROMANY;
653
arr = (PyArrayObject *) \
654
PyArray_FromAny(obj,PyArray_DescrFromType(type_num), 0,0,
655
((intent & F2PY_INTENT_C)?CARRAY_FLAGS:FARRAY_FLAGS) \
659
if (check_and_fix_dimensions(arr,rank,dims))
660
return NULL; /*XXX: set exception */
666
/*****************************************/
667
/* Helper functions for array_from_pyobj */
668
/*****************************************/
671
int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,intp *dims) {
673
This function fills in blanks (that are -1\'s) in dims list using
674
the dimensions from arr. It also checks that non-blank dims will
675
match with the corresponding values in arr dimensions.
677
const intp arr_size = (arr->nd)?PyArray_Size((PyObject *)arr):1;
678
#ifdef DEBUG_COPY_ND_ARRAY
680
printf("check_and_fix_dimensions:init: dims=");
681
dump_dims(rank,dims);
683
if (rank > arr->nd) { /* [1,2] -> [[1],[2]]; 1 -> [[1]] */
687
/* Fill dims where -1 or 0; check dimensions; calc new_size; */
688
for(i=0;i<arr->nd;++i) {
690
if (dims[i]!=arr->dimensions[i]) {
691
fprintf(stderr,"%d-th dimension must be fixed to %" INTP_FMT
692
" but got %" INTP_FMT "\n",
693
i,dims[i], arr->dimensions[i]);
696
if (!dims[i]) dims[i] = 1;
698
dims[i] = arr->dimensions[i] ? arr->dimensions[i] : 1;
702
for(i=arr->nd;i<rank;++i)
704
fprintf(stderr,"%d-th dimension must be %" INTP_FMT
705
" but got 0 (not defined).\n",
708
} else if (free_axe<0)
713
dims[free_axe] = arr_size/new_size;
714
new_size *= dims[free_axe];
716
if (new_size != arr_size) {
717
fprintf(stderr,"confused: new_size=%" INTP_FMT
718
", arr_size=%" INTP_FMT " (maybe too many free"
719
" indices)\n", new_size,arr_size);
722
} else if (rank==arr->nd) {
725
for (i=0; i<rank; ++i) {
726
d = arr->dimensions[i];
728
if (d > 1 && d!=dims[i]) {
729
fprintf(stderr,"%d-th dimension must be fixed to %" INTP_FMT
730
" but got %" INTP_FMT "\n",
734
if (!dims[i]) dims[i] = 1;
737
} else { /* [[1,2]] -> [[1],[2]] */
742
for (i=0,effrank=0;i<arr->nd;++i)
743
if (arr->dimensions[i]>1) ++effrank;
746
fprintf(stderr,"too many axes: %d (effrank=%d), expected rank=%d\n",
747
arr->nd,effrank,rank);
751
for (i=0,j=0;i<rank;++i) {
752
while (j<arr->nd && arr->dimensions[j]<2) ++j;
753
if (j>=arr->nd) d = 1;
754
else d = arr->dimensions[j++];
756
if (d>1 && d!=dims[i]) {
757
fprintf(stderr,"%d-th dimension must be fixed to %" INTP_FMT
758
" but got %" INTP_FMT " (real index=%d)\n",
762
if (!dims[i]) dims[i] = 1;
767
for (i=rank;i<arr->nd;++i) { /* [[1,2],[3,4]] -> [1,2,3,4] */
768
while (j<arr->nd && arr->dimensions[j]<2) ++j;
769
if (j>=arr->nd) d = 1;
770
else d = arr->dimensions[j++];
773
for (i=0,size=1;i<rank;++i) size *= dims[i];
774
if (size != arr_size) {
775
fprintf(stderr,"confused: size=%" INTP_FMT ", arr_size=%" INTP_FMT
776
", rank=%d, effrank=%d, arr.nd=%d, dims=[",
777
size,arr_size,rank,effrank,arr->nd);
778
for (i=0;i<rank;++i) fprintf(stderr," %" INTP_FMT,dims[i]);
779
fprintf(stderr," ], arr.dims=[");
780
for (i=0;i<arr->nd;++i) fprintf(stderr," %" INTP_FMT,arr->dimensions[i]);
781
fprintf(stderr," ]\n");
785
#ifdef DEBUG_COPY_ND_ARRAY
786
printf("check_and_fix_dimensions:end: dims=");
787
dump_dims(rank,dims);
792
/* End of file: array_from_pyobj.c */
794
/************************* copy_ND_array *******************************/
797
int copy_ND_array(const PyArrayObject *arr, PyArrayObject *out)
799
F2PY_REPORT_ON_ARRAY_COPY_FROMARR;
800
return PyArray_CopyInto(out, (PyArrayObject *)arr);
806
/************************* EOF fortranobject.c *******************************/