Learn more  » Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

aaronreidsmith / numpy   python

Repository URL to install this package:

Version: 1.17.4 

/ f2py / src / fortranobject.c

#define FORTRANOBJECT_C
#include "fortranobject.h"

#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>
#include <string.h>

/*
  This file implements: FortranObject, array_from_pyobj, copy_ND_array

  Author: Pearu Peterson <pearu@cens.ioc.ee>
  $Revision: 1.52 $
  $Date: 2005/07/11 07:44:20 $
*/

int
F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj)
{
    if (obj==NULL) {
        fprintf(stderr, "Error loading %s\n", name);
        if (PyErr_Occurred()) {
            PyErr_Print();
            PyErr_Clear();
        }
        return -1;
    }
    return PyDict_SetItemString(dict, name, obj);
}

/************************* FortranObject *******************************/

typedef PyObject *(*fortranfunc)(PyObject *,PyObject *,PyObject *,void *);

PyObject *
PyFortranObject_New(FortranDataDef* defs, f2py_void_func init) {
    int i;
    PyFortranObject *fp = NULL;
    PyObject *v = NULL;
    if (init!=NULL)                           /* Initialize F90 module objects */
        (*(init))();
    if ((fp = PyObject_New(PyFortranObject, &PyFortran_Type))==NULL) return NULL;
    if ((fp->dict = PyDict_New())==NULL) return NULL;
    fp->len = 0;
    while (defs[fp->len].name != NULL) fp->len++;
    if (fp->len == 0) goto fail;
    fp->defs = defs;
    for (i=0;i<fp->len;i++)
        if (fp->defs[i].rank == -1) {                      /* Is Fortran routine */
            v = PyFortranObject_NewAsAttr(&(fp->defs[i]));
            if (v==NULL) return NULL;
            PyDict_SetItemString(fp->dict,fp->defs[i].name,v);
        } else
            if ((fp->defs[i].data)!=NULL) { /* Is Fortran variable or array (not allocatable) */
                if (fp->defs[i].type == NPY_STRING) {
                    int n = fp->defs[i].rank-1;
                    v = PyArray_New(&PyArray_Type, n, fp->defs[i].dims.d,
                                    NPY_STRING, NULL, fp->defs[i].data, fp->defs[i].dims.d[n],
                                    NPY_ARRAY_FARRAY, NULL);
                }
                else {
                    v = PyArray_New(&PyArray_Type, fp->defs[i].rank, fp->defs[i].dims.d,
                                    fp->defs[i].type, NULL, fp->defs[i].data, 0, NPY_ARRAY_FARRAY,
                                    NULL);
                }
                if (v==NULL) return NULL;
                PyDict_SetItemString(fp->dict,fp->defs[i].name,v);
            }
    Py_XDECREF(v);
    return (PyObject *)fp;
 fail:
    Py_XDECREF(v);
    return NULL;
}

PyObject *
PyFortranObject_NewAsAttr(FortranDataDef* defs) { /* used for calling F90 module routines */
    PyFortranObject *fp = NULL;
    fp = PyObject_New(PyFortranObject, &PyFortran_Type);
    if (fp == NULL) return NULL;
    if ((fp->dict = PyDict_New())==NULL) {
        PyObject_Del(fp);
        return NULL;
    }
    fp->len = 1;
    fp->defs = defs;
    return (PyObject *)fp;
}

/* Fortran methods */

static void
fortran_dealloc(PyFortranObject *fp) {
    Py_XDECREF(fp->dict);
    PyObject_Del(fp);
}


#if PY_VERSION_HEX >= 0x03000000
#else
static PyMethodDef fortran_methods[] = {
    {NULL,          NULL}           /* sentinel */
};
#endif


/* Returns number of bytes consumed from buf, or -1 on error. */
static Py_ssize_t
format_def(char *buf, Py_ssize_t size, FortranDataDef def)
{
    char *p = buf;
    int i, n;

    n = PyOS_snprintf(p, size, "array(%" NPY_INTP_FMT, def.dims.d[0]);
    if (n < 0 || n >= size) {
        return -1;
    }
    p += n;
    size -= n;

    for (i = 1; i < def.rank; i++) {
        n = PyOS_snprintf(p, size, ",%" NPY_INTP_FMT, def.dims.d[i]);
        if (n < 0 || n >= size) {
            return -1;
        }
        p += n;
        size -= n;
    }

    if (size <= 0) {
        return -1;
    }

    *p++ = ')';
    size--;

    if (def.data == NULL) {
        static const char notalloc[] = ", not allocated";
        if ((size_t) size < sizeof(notalloc)) {
            return -1;
        }
        memcpy(p, notalloc, sizeof(notalloc));
    }

    return p - buf;
}

static PyObject *
fortran_doc(FortranDataDef def)
{
    char *buf, *p;
    PyObject *s = NULL;
    Py_ssize_t n, origsize, size = 100;

    if (def.doc != NULL) {
        size += strlen(def.doc);
    }
    origsize = size;
    buf = p = (char *)PyMem_Malloc(size);
    if (buf == NULL) {
        return PyErr_NoMemory();
    }

    if (def.rank == -1) {
        if (def.doc) {
            n = strlen(def.doc);
            if (n > size) {
                goto fail;
            }
            memcpy(p, def.doc, n);
            p += n;
            size -= n;
        }
        else {
            n = PyOS_snprintf(p, size, "%s - no docs available", def.name);
            if (n < 0 || n >= size) {
                goto fail;
            }
            p += n;
            size -= n;
        }
    }
    else {
        PyArray_Descr *d = PyArray_DescrFromType(def.type);
        n = PyOS_snprintf(p, size, "'%c'-", d->type);
        Py_DECREF(d);
        if (n < 0 || n >= size) {
            goto fail;
        }
        p += n;
        size -= n;

        if (def.data == NULL) {
            n = format_def(p, size, def) == -1;
            if (n < 0) {
                goto fail;
            }
            p += n;
            size -= n;
        }
        else if (def.rank > 0) {
            n = format_def(p, size, def);
            if (n < 0) {
                goto fail;
            }
            p += n;
            size -= n;
        }
        else {
            n = strlen("scalar");
            if (size < n) {
                goto fail;
            }
            memcpy(p, "scalar", n);
            p += n;
            size -= n;
        }
    }
    if (size <= 1) {
        goto fail;
    }
    *p++ = '\n';
    size--;

    /* p now points one beyond the last character of the string in buf */
#if PY_VERSION_HEX >= 0x03000000
    s = PyUnicode_FromStringAndSize(buf, p - buf);
#else
    s = PyString_FromStringAndSize(buf, p - buf);
#endif

    PyMem_Free(buf);
    return s;

 fail:
    fprintf(stderr, "fortranobject.c: fortran_doc: len(p)=%zd>%zd=size:"
                    " too long docstring required, increase size\n",
            p - buf, origsize);
    PyMem_Free(buf);
    return NULL;
}

static FortranDataDef *save_def; /* save pointer of an allocatable array */
static void set_data(char *d,npy_intp *f) {  /* callback from Fortran */
    if (*f)                                  /* In fortran f=allocated(d) */
        save_def->data = d;
    else
        save_def->data = NULL;
    /* printf("set_data: d=%p,f=%d\n",d,*f); */
}

static PyObject *
fortran_getattr(PyFortranObject *fp, char *name) {
    int i,j,k,flag;
    if (fp->dict != NULL) {
        PyObject *v = PyDict_GetItemString(fp->dict, name);
        if (v != NULL) {
            Py_INCREF(v);
            return v;
        }
    }
    for (i=0,j=1;i<fp->len && (j=strcmp(name,fp->defs[i].name));i++);
    if (j==0)
        if (fp->defs[i].rank!=-1) {                   /* F90 allocatable array */
            if (fp->defs[i].func==NULL) return NULL;
            for(k=0;k<fp->defs[i].rank;++k)
                fp->defs[i].dims.d[k]=-1;
            save_def = &fp->defs[i];
            (*(fp->defs[i].func))(&fp->defs[i].rank,fp->defs[i].dims.d,set_data,&flag);
            if (flag==2)
                k = fp->defs[i].rank + 1;
            else
                k = fp->defs[i].rank;
            if (fp->defs[i].data !=NULL) {              /* array is allocated */
                PyObject *v = PyArray_New(&PyArray_Type, k, fp->defs[i].dims.d,
                                          fp->defs[i].type, NULL, fp->defs[i].data, 0, NPY_ARRAY_FARRAY,
                                          NULL);
                if (v==NULL) return NULL;
                /* Py_INCREF(v); */
                return v;
            } else {                                    /* array is not allocated */
                Py_RETURN_NONE;
            }
        }
    if (strcmp(name,"__dict__")==0) {
        Py_INCREF(fp->dict);
        return fp->dict;
    }
    if (strcmp(name,"__doc__")==0) {
#if PY_VERSION_HEX >= 0x03000000
        PyObject *s = PyUnicode_FromString(""), *s2, *s3;
        for (i=0;i<fp->len;i++) {
            s2 = fortran_doc(fp->defs[i]);
            s3 = PyUnicode_Concat(s, s2);
            Py_DECREF(s2);
            Py_DECREF(s);
            s = s3;
        }
#else
        PyObject *s = PyString_FromString("");
        for (i=0;i<fp->len;i++)
            PyString_ConcatAndDel(&s,fortran_doc(fp->defs[i]));
#endif
        if (PyDict_SetItemString(fp->dict, name, s))
            return NULL;
        return s;
    }
    if ((strcmp(name,"_cpointer")==0) && (fp->len==1)) {
        PyObject *cobj = F2PyCapsule_FromVoidPtr((void *)(fp->defs[0].data),NULL);
        if (PyDict_SetItemString(fp->dict, name, cobj))
            return NULL;
        return cobj;
    }
#if PY_VERSION_HEX >= 0x03000000
    if (1) {
        PyObject *str, *ret;
        str = PyUnicode_FromString(name);
        ret = PyObject_GenericGetAttr((PyObject *)fp, str);
        Py_DECREF(str);
        return ret;
    }
#else
    return Py_FindMethod(fortran_methods, (PyObject *)fp, name);
#endif
}

static int
fortran_setattr(PyFortranObject *fp, char *name, PyObject *v) {
    int i,j,flag;
    PyArrayObject *arr = NULL;
    for (i=0,j=1;i<fp->len && (j=strcmp(name,fp->defs[i].name));i++);
    if (j==0) {
        if (fp->defs[i].rank==-1) {
            PyErr_SetString(PyExc_AttributeError,"over-writing fortran routine");
            return -1;
        }
        if (fp->defs[i].func!=NULL) { /* is allocatable array */
            npy_intp dims[F2PY_MAX_DIMS];
            int k;
            save_def = &fp->defs[i];
            if (v!=Py_None) {     /* set new value (reallocate if needed --
                                     see f2py generated code for more
                                     details ) */
Loading ...