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

agriconnect / numpy   python

Repository URL to install this package:

/ f2py / capi_maps.py

#!/usr/bin/env python
"""

Copyright 1999,2000 Pearu Peterson all rights reserved,
Pearu Peterson <pearu@ioc.ee>
Permission to use, modify, and distribute this software is given under the
terms of the NumPy License.

NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
$Date: 2005/05/06 10:57:33 $
Pearu Peterson

"""
from __future__ import division, absolute_import, print_function

__version__ = "$Revision: 1.60 $"[10:-1]

from . import __version__
f2py_version = __version__.version

import copy
import re
import os
import sys
from .crackfortran import markoutercomma
from . import cb_rules

# The eviroment provided by auxfuncs.py is needed for some calls to eval.
# As the needed functions cannot be determined by static inspection of the
# code, it is safest to use import * pending a major refactoring of f2py.
from .auxfuncs import *

__all__ = [
    'getctype', 'getstrlength', 'getarrdims', 'getpydocsign',
    'getarrdocsign', 'getinit', 'sign2map', 'routsign2map', 'modsign2map',
    'cb_sign2map', 'cb_routsign2map', 'common_sign2map'
]


# Numarray and Numeric users should set this False
using_newcore = True

depargs = []
lcb_map = {}
lcb2_map = {}
# forced casting: mainly caused by the fact that Python or Numeric
#                 C/APIs do not support the corresponding C types.
c2py_map = {'double': 'float',
            'float': 'float',                          # forced casting
            'long_double': 'float',                    # forced casting
            'char': 'int',                             # forced casting
            'signed_char': 'int',                      # forced casting
            'unsigned_char': 'int',                    # forced casting
            'short': 'int',                            # forced casting
            'unsigned_short': 'int',                   # forced casting
            'int': 'int',                              # (forced casting)
            'long': 'int',
            'long_long': 'long',
            'unsigned': 'int',                         # forced casting
            'complex_float': 'complex',                # forced casting
            'complex_double': 'complex',
            'complex_long_double': 'complex',          # forced casting
            'string': 'string',
            }
c2capi_map = {'double': 'NPY_DOUBLE',
              'float': 'NPY_FLOAT',
              'long_double': 'NPY_DOUBLE',           # forced casting
              'char': 'NPY_STRING',
              'unsigned_char': 'NPY_UBYTE',
              'signed_char': 'NPY_BYTE',
              'short': 'NPY_SHORT',
              'unsigned_short': 'NPY_USHORT',
              'int': 'NPY_INT',
              'unsigned': 'NPY_UINT',
              'long': 'NPY_LONG',
              'long_long': 'NPY_LONG',                # forced casting
              'complex_float': 'NPY_CFLOAT',
              'complex_double': 'NPY_CDOUBLE',
              'complex_long_double': 'NPY_CDOUBLE',   # forced casting
              'string': 'NPY_STRING'}

# These new maps aren't used anyhere yet, but should be by default
#  unless building numeric or numarray extensions.
if using_newcore:
    c2capi_map = {'double': 'NPY_DOUBLE',
                  'float': 'NPY_FLOAT',
                  'long_double': 'NPY_LONGDOUBLE',
                  'char': 'NPY_BYTE',
                  'unsigned_char': 'NPY_UBYTE',
                  'signed_char': 'NPY_BYTE',
                  'short': 'NPY_SHORT',
                  'unsigned_short': 'NPY_USHORT',
                  'int': 'NPY_INT',
                  'unsigned': 'NPY_UINT',
                  'long': 'NPY_LONG',
                  'unsigned_long': 'NPY_ULONG',
                  'long_long': 'NPY_LONGLONG',
                  'unsigned_long_long': 'NPY_ULONGLONG',
                  'complex_float': 'NPY_CFLOAT',
                  'complex_double': 'NPY_CDOUBLE',
                  'complex_long_double': 'NPY_CDOUBLE',
                  'string':'NPY_STRING'

                  }
c2pycode_map = {'double': 'd',
                'float': 'f',
                'long_double': 'd',                       # forced casting
                'char': '1',
                'signed_char': '1',
                'unsigned_char': 'b',
                'short': 's',
                'unsigned_short': 'w',
                'int': 'i',
                'unsigned': 'u',
                'long': 'l',
                'long_long': 'L',
                'complex_float': 'F',
                'complex_double': 'D',
                'complex_long_double': 'D',               # forced casting
                'string': 'c'
                }
if using_newcore:
    c2pycode_map = {'double': 'd',
                    'float': 'f',
                    'long_double': 'g',
                    'char': 'b',
                    'unsigned_char': 'B',
                    'signed_char': 'b',
                    'short': 'h',
                    'unsigned_short': 'H',
                    'int': 'i',
                    'unsigned': 'I',
                    'long': 'l',
                    'unsigned_long': 'L',
                    'long_long': 'q',
                    'unsigned_long_long': 'Q',
                    'complex_float': 'F',
                    'complex_double': 'D',
                    'complex_long_double': 'G',
                    'string': 'S'}
c2buildvalue_map = {'double': 'd',
                    'float': 'f',
                    'char': 'b',
                    'signed_char': 'b',
                    'short': 'h',
                    'int': 'i',
                    'long': 'l',
                    'long_long': 'L',
                    'complex_float': 'N',
                    'complex_double': 'N',
                    'complex_long_double': 'N',
                    'string': 'z'}

if sys.version_info[0] >= 3:
    # Bytes, not Unicode strings
    c2buildvalue_map['string'] = 'y'

if using_newcore:
    # c2buildvalue_map=???
    pass

f2cmap_all = {'real': {'': 'float', '4': 'float', '8': 'double',
                       '12': 'long_double', '16': 'long_double'},
              'integer': {'': 'int', '1': 'signed_char', '2': 'short',
                          '4': 'int', '8': 'long_long',
                          '-1': 'unsigned_char', '-2': 'unsigned_short',
                          '-4': 'unsigned', '-8': 'unsigned_long_long'},
              'complex': {'': 'complex_float', '8': 'complex_float',
                          '16': 'complex_double', '24': 'complex_long_double',
                          '32': 'complex_long_double'},
              'complexkind': {'': 'complex_float', '4': 'complex_float',
                              '8': 'complex_double', '12': 'complex_long_double',
                              '16': 'complex_long_double'},
              'logical': {'': 'int', '1': 'char', '2': 'short', '4': 'int',
                          '8': 'long_long'},
              'double complex': {'': 'complex_double'},
              'double precision': {'': 'double'},
              'byte': {'': 'char'},
              'character': {'': 'string'}
              }

if os.path.isfile('.f2py_f2cmap'):
    # User defined additions to f2cmap_all.
    # .f2py_f2cmap must contain a dictionary of dictionaries, only.  For
    # example, {'real':{'low':'float'}} means that Fortran 'real(low)' is
    # interpreted as C 'float'.  This feature is useful for F90/95 users if
    # they use PARAMETERSs in type specifications.
    try:
        outmess('Reading .f2py_f2cmap ...\n')
        f = open('.f2py_f2cmap', 'r')
        d = eval(f.read(), {}, {})
        f.close()
        for k, d1 in list(d.items()):
            for k1 in list(d1.keys()):
                d1[k1.lower()] = d1[k1]
            d[k.lower()] = d[k]
        for k in list(d.keys()):
            if k not in f2cmap_all:
                f2cmap_all[k] = {}
            for k1 in list(d[k].keys()):
                if d[k][k1] in c2py_map:
                    if k1 in f2cmap_all[k]:
                        outmess(
                            "\tWarning: redefinition of {'%s':{'%s':'%s'->'%s'}}\n" % (k, k1, f2cmap_all[k][k1], d[k][k1]))
                    f2cmap_all[k][k1] = d[k][k1]
                    outmess('\tMapping "%s(kind=%s)" to "%s"\n' %
                            (k, k1, d[k][k1]))
                else:
                    errmess("\tIgnoring map {'%s':{'%s':'%s'}}: '%s' must be in %s\n" % (
                        k, k1, d[k][k1], d[k][k1], list(c2py_map.keys())))
        outmess('Successfully applied user defined changes from .f2py_f2cmap\n')
    except Exception as msg:
        errmess(
            'Failed to apply user defined changes from .f2py_f2cmap: %s. Skipping.\n' % (msg))

cformat_map = {'double': '%g',
               'float': '%g',
               'long_double': '%Lg',
               'char': '%d',
               'signed_char': '%d',
               'unsigned_char': '%hhu',
               'short': '%hd',
               'unsigned_short': '%hu',
               'int': '%d',
               'unsigned': '%u',
               'long': '%ld',
               'unsigned_long': '%lu',
               'long_long': '%ld',
               'complex_float': '(%g,%g)',
               'complex_double': '(%g,%g)',
               'complex_long_double': '(%Lg,%Lg)',
               'string': '%s',
               }

# Auxiliary functions


def getctype(var):
    """
    Determines C type
    """
    ctype = 'void'
    if isfunction(var):
        if 'result' in var:
            a = var['result']
        else:
            a = var['name']
        if a in var['vars']:
            return getctype(var['vars'][a])
        else:
            errmess('getctype: function %s has no return value?!\n' % a)
    elif issubroutine(var):
        return ctype
    elif 'typespec' in var and var['typespec'].lower() in f2cmap_all:
        typespec = var['typespec'].lower()
        f2cmap = f2cmap_all[typespec]
        ctype = f2cmap['']  # default type
        if 'kindselector' in var:
            if '*' in var['kindselector']:
                try:
                    ctype = f2cmap[var['kindselector']['*']]
                except KeyError:
                    errmess('getctype: "%s %s %s" not supported.\n' %
                            (var['typespec'], '*', var['kindselector']['*']))
            elif 'kind' in var['kindselector']:
                if typespec + 'kind' in f2cmap_all:
                    f2cmap = f2cmap_all[typespec + 'kind']
                try:
                    ctype = f2cmap[var['kindselector']['kind']]
                except KeyError:
                    if typespec in f2cmap_all:
                        f2cmap = f2cmap_all[typespec]
                    try:
                        ctype = f2cmap[str(var['kindselector']['kind'])]
                    except KeyError:
                        errmess('getctype: "%s(kind=%s)" is mapped to C "%s" (to override define dict(%s = dict(%s="<C typespec>")) in %s/.f2py_f2cmap file).\n'
                                % (typespec, var['kindselector']['kind'], ctype,
                                   typespec, var['kindselector']['kind'], os.getcwd()))

    else:
        if not isexternal(var):
            errmess(
                'getctype: No C-type found in "%s", assuming void.\n' % var)
    return ctype


def getstrlength(var):
    if isstringfunction(var):
        if 'result' in var:
            a = var['result']
        else:
            a = var['name']
        if a in var['vars']:
            return getstrlength(var['vars'][a])
        else:
            errmess('getstrlength: function %s has no return value?!\n' % a)
    if not isstring(var):
        errmess(
            'getstrlength: expected a signature of a string but got: %s\n' % (repr(var)))
    len = '1'
    if 'charselector' in var:
        a = var['charselector']
        if '*' in a:
            len = a['*']
        elif 'len' in a:
            len = a['len']
    if re.match(r'\(\s*([*]|[:])\s*\)', len) or re.match(r'([*]|[:])', len):
        if isintent_hide(var):
            errmess('getstrlength:intent(hide): expected a string with defined length but got: %s\n' % (
                repr(var)))
        len = '-1'
    return len


def getarrdims(a, var, verbose=0):
    global depargs
    ret = {}
    if isstring(var) and not isarray(var):
        ret['dims'] = getstrlength(var)
        ret['size'] = ret['dims']
        ret['rank'] = '1'
    elif isscalar(var):
        ret['size'] = '1'
        ret['rank'] = '0'
        ret['dims'] = ''
    elif isarray(var):
        dim = copy.copy(var['dimension'])
        ret['size'] = '*'.join(dim)
        try:
            ret['size'] = repr(eval(ret['size']))
        except Exception:
            pass
        ret['dims'] = ','.join(dim)
        ret['rank'] = repr(len(dim))
        ret['rank*[-1]'] = repr(len(dim) * [-1])[1:-1]
        for i in range(len(dim)):  # solve dim for dependencies
            v = []
            if dim[i] in depargs:
                v = [dim[i]]
            else:
                for va in depargs:
                    if re.match(r'.*?\b%s\b.*' % va, dim[i]):
                        v.append(va)
            for va in v:
                if depargs.index(va) > depargs.index(a):
Loading ...