done
This commit is contained in:
329
lib/python3.11/site-packages/numpy/f2py/func2subr.py
Normal file
329
lib/python3.11/site-packages/numpy/f2py/func2subr.py
Normal file
@ -0,0 +1,329 @@
|
||||
"""
|
||||
|
||||
Rules for building C/API module with f2py2e.
|
||||
|
||||
Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
|
||||
Copyright 2011 -- present NumPy Developers.
|
||||
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.
|
||||
"""
|
||||
import copy
|
||||
|
||||
from ._isocbind import isoc_kindmap
|
||||
from .auxfuncs import (
|
||||
getfortranname,
|
||||
isexternal,
|
||||
isfunction,
|
||||
isfunction_wrap,
|
||||
isintent_in,
|
||||
isintent_out,
|
||||
islogicalfunction,
|
||||
ismoduleroutine,
|
||||
isscalar,
|
||||
issubroutine,
|
||||
issubroutine_wrap,
|
||||
outmess,
|
||||
show,
|
||||
)
|
||||
|
||||
|
||||
def var2fixfortran(vars, a, fa=None, f90mode=None):
|
||||
if fa is None:
|
||||
fa = a
|
||||
if a not in vars:
|
||||
show(vars)
|
||||
outmess(f'var2fixfortran: No definition for argument "{a}".\n')
|
||||
return ''
|
||||
if 'typespec' not in vars[a]:
|
||||
show(vars[a])
|
||||
outmess(f'var2fixfortran: No typespec for argument "{a}".\n')
|
||||
return ''
|
||||
vardef = vars[a]['typespec']
|
||||
if vardef == 'type' and 'typename' in vars[a]:
|
||||
vardef = f"{vardef}({vars[a]['typename']})"
|
||||
selector = {}
|
||||
lk = ''
|
||||
if 'kindselector' in vars[a]:
|
||||
selector = vars[a]['kindselector']
|
||||
lk = 'kind'
|
||||
elif 'charselector' in vars[a]:
|
||||
selector = vars[a]['charselector']
|
||||
lk = 'len'
|
||||
if '*' in selector:
|
||||
if f90mode:
|
||||
if selector['*'] in ['*', ':', '(*)']:
|
||||
vardef = f'{vardef}(len=*)'
|
||||
else:
|
||||
vardef = f"{vardef}({lk}={selector['*']})"
|
||||
elif selector['*'] in ['*', ':']:
|
||||
vardef = f"{vardef}*({selector['*']})"
|
||||
else:
|
||||
vardef = f"{vardef}*{selector['*']}"
|
||||
elif 'len' in selector:
|
||||
vardef = f"{vardef}(len={selector['len']}"
|
||||
if 'kind' in selector:
|
||||
vardef = f"{vardef},kind={selector['kind']})"
|
||||
else:
|
||||
vardef = f'{vardef})'
|
||||
elif 'kind' in selector:
|
||||
vardef = f"{vardef}(kind={selector['kind']})"
|
||||
|
||||
vardef = f'{vardef} {fa}'
|
||||
if 'dimension' in vars[a]:
|
||||
vardef = f"{vardef}({','.join(vars[a]['dimension'])})"
|
||||
return vardef
|
||||
|
||||
def useiso_c_binding(rout):
|
||||
useisoc = False
|
||||
for key, value in rout['vars'].items():
|
||||
kind_value = value.get('kindselector', {}).get('kind')
|
||||
if kind_value in isoc_kindmap:
|
||||
return True
|
||||
return useisoc
|
||||
|
||||
def createfuncwrapper(rout, signature=0):
|
||||
assert isfunction(rout)
|
||||
|
||||
extra_args = []
|
||||
vars = rout['vars']
|
||||
for a in rout['args']:
|
||||
v = rout['vars'][a]
|
||||
for i, d in enumerate(v.get('dimension', [])):
|
||||
if d == ':':
|
||||
dn = f'f2py_{a}_d{i}'
|
||||
dv = {'typespec': 'integer', 'intent': ['hide']}
|
||||
dv['='] = f'shape({a}, {i})'
|
||||
extra_args.append(dn)
|
||||
vars[dn] = dv
|
||||
v['dimension'][i] = dn
|
||||
rout['args'].extend(extra_args)
|
||||
need_interface = bool(extra_args)
|
||||
|
||||
ret = ['']
|
||||
|
||||
def add(line, ret=ret):
|
||||
ret[0] = f'{ret[0]}\n {line}'
|
||||
name = rout['name']
|
||||
fortranname = getfortranname(rout)
|
||||
f90mode = ismoduleroutine(rout)
|
||||
newname = f'{name}f2pywrap'
|
||||
|
||||
if newname not in vars:
|
||||
vars[newname] = vars[name]
|
||||
args = [newname] + rout['args'][1:]
|
||||
else:
|
||||
args = [newname] + rout['args']
|
||||
|
||||
l_tmpl = var2fixfortran(vars, name, '@@@NAME@@@', f90mode)
|
||||
if l_tmpl[:13] == 'character*(*)':
|
||||
if f90mode:
|
||||
l_tmpl = 'character(len=10)' + l_tmpl[13:]
|
||||
else:
|
||||
l_tmpl = 'character*10' + l_tmpl[13:]
|
||||
charselect = vars[name]['charselector']
|
||||
if charselect.get('*', '') == '(*)':
|
||||
charselect['*'] = '10'
|
||||
|
||||
l1 = l_tmpl.replace('@@@NAME@@@', newname)
|
||||
rl = None
|
||||
|
||||
useisoc = useiso_c_binding(rout)
|
||||
sargs = ', '.join(args)
|
||||
if f90mode:
|
||||
# gh-23598 fix warning
|
||||
# Essentially, this gets called again with modules where the name of the
|
||||
# function is added to the arguments, which is not required, and removed
|
||||
sargs = sargs.replace(f"{name}, ", '')
|
||||
args = [arg for arg in args if arg != name]
|
||||
rout['args'] = args
|
||||
add(f"subroutine f2pywrap_{rout['modulename']}_{name} ({sargs})")
|
||||
if not signature:
|
||||
add(f"use {rout['modulename']}, only : {fortranname}")
|
||||
if useisoc:
|
||||
add('use iso_c_binding')
|
||||
else:
|
||||
add(f'subroutine f2pywrap{name} ({sargs})')
|
||||
if useisoc:
|
||||
add('use iso_c_binding')
|
||||
if not need_interface:
|
||||
add(f'external {fortranname}')
|
||||
rl = l_tmpl.replace('@@@NAME@@@', '') + ' ' + fortranname
|
||||
|
||||
if need_interface:
|
||||
for line in rout['saved_interface'].split('\n'):
|
||||
if line.lstrip().startswith('use ') and '__user__' not in line:
|
||||
add(line)
|
||||
|
||||
args = args[1:]
|
||||
dumped_args = []
|
||||
for a in args:
|
||||
if isexternal(vars[a]):
|
||||
add(f'external {a}')
|
||||
dumped_args.append(a)
|
||||
for a in args:
|
||||
if a in dumped_args:
|
||||
continue
|
||||
if isscalar(vars[a]):
|
||||
add(var2fixfortran(vars, a, f90mode=f90mode))
|
||||
dumped_args.append(a)
|
||||
for a in args:
|
||||
if a in dumped_args:
|
||||
continue
|
||||
if isintent_in(vars[a]):
|
||||
add(var2fixfortran(vars, a, f90mode=f90mode))
|
||||
dumped_args.append(a)
|
||||
for a in args:
|
||||
if a in dumped_args:
|
||||
continue
|
||||
add(var2fixfortran(vars, a, f90mode=f90mode))
|
||||
|
||||
add(l1)
|
||||
if rl is not None:
|
||||
add(rl)
|
||||
|
||||
if need_interface:
|
||||
if f90mode:
|
||||
# f90 module already defines needed interface
|
||||
pass
|
||||
else:
|
||||
add('interface')
|
||||
add(rout['saved_interface'].lstrip())
|
||||
add('end interface')
|
||||
|
||||
sargs = ', '.join([a for a in args if a not in extra_args])
|
||||
|
||||
if not signature:
|
||||
if islogicalfunction(rout):
|
||||
add(f'{newname} = .not.(.not.{fortranname}({sargs}))')
|
||||
else:
|
||||
add(f'{newname} = {fortranname}({sargs})')
|
||||
if f90mode:
|
||||
add(f"end subroutine f2pywrap_{rout['modulename']}_{name}")
|
||||
else:
|
||||
add('end')
|
||||
return ret[0]
|
||||
|
||||
|
||||
def createsubrwrapper(rout, signature=0):
|
||||
assert issubroutine(rout)
|
||||
|
||||
extra_args = []
|
||||
vars = rout['vars']
|
||||
for a in rout['args']:
|
||||
v = rout['vars'][a]
|
||||
for i, d in enumerate(v.get('dimension', [])):
|
||||
if d == ':':
|
||||
dn = f'f2py_{a}_d{i}'
|
||||
dv = {'typespec': 'integer', 'intent': ['hide']}
|
||||
dv['='] = f'shape({a}, {i})'
|
||||
extra_args.append(dn)
|
||||
vars[dn] = dv
|
||||
v['dimension'][i] = dn
|
||||
rout['args'].extend(extra_args)
|
||||
need_interface = bool(extra_args)
|
||||
|
||||
ret = ['']
|
||||
|
||||
def add(line, ret=ret):
|
||||
ret[0] = f'{ret[0]}\n {line}'
|
||||
name = rout['name']
|
||||
fortranname = getfortranname(rout)
|
||||
f90mode = ismoduleroutine(rout)
|
||||
|
||||
args = rout['args']
|
||||
|
||||
useisoc = useiso_c_binding(rout)
|
||||
sargs = ', '.join(args)
|
||||
if f90mode:
|
||||
add(f"subroutine f2pywrap_{rout['modulename']}_{name} ({sargs})")
|
||||
if useisoc:
|
||||
add('use iso_c_binding')
|
||||
if not signature:
|
||||
add(f"use {rout['modulename']}, only : {fortranname}")
|
||||
else:
|
||||
add(f'subroutine f2pywrap{name} ({sargs})')
|
||||
if useisoc:
|
||||
add('use iso_c_binding')
|
||||
if not need_interface:
|
||||
add(f'external {fortranname}')
|
||||
|
||||
if need_interface:
|
||||
for line in rout['saved_interface'].split('\n'):
|
||||
if line.lstrip().startswith('use ') and '__user__' not in line:
|
||||
add(line)
|
||||
|
||||
dumped_args = []
|
||||
for a in args:
|
||||
if isexternal(vars[a]):
|
||||
add(f'external {a}')
|
||||
dumped_args.append(a)
|
||||
for a in args:
|
||||
if a in dumped_args:
|
||||
continue
|
||||
if isscalar(vars[a]):
|
||||
add(var2fixfortran(vars, a, f90mode=f90mode))
|
||||
dumped_args.append(a)
|
||||
for a in args:
|
||||
if a in dumped_args:
|
||||
continue
|
||||
add(var2fixfortran(vars, a, f90mode=f90mode))
|
||||
|
||||
if need_interface:
|
||||
if f90mode:
|
||||
# f90 module already defines needed interface
|
||||
pass
|
||||
else:
|
||||
add('interface')
|
||||
for line in rout['saved_interface'].split('\n'):
|
||||
if line.lstrip().startswith('use ') and '__user__' in line:
|
||||
continue
|
||||
add(line)
|
||||
add('end interface')
|
||||
|
||||
sargs = ', '.join([a for a in args if a not in extra_args])
|
||||
|
||||
if not signature:
|
||||
add(f'call {fortranname}({sargs})')
|
||||
if f90mode:
|
||||
add(f"end subroutine f2pywrap_{rout['modulename']}_{name}")
|
||||
else:
|
||||
add('end')
|
||||
return ret[0]
|
||||
|
||||
|
||||
def assubr(rout):
|
||||
if isfunction_wrap(rout):
|
||||
fortranname = getfortranname(rout)
|
||||
name = rout['name']
|
||||
outmess('\t\tCreating wrapper for Fortran function "%s"("%s")...\n' % (
|
||||
name, fortranname))
|
||||
rout = copy.copy(rout)
|
||||
fname = name
|
||||
rname = fname
|
||||
if 'result' in rout:
|
||||
rname = rout['result']
|
||||
rout['vars'][fname] = rout['vars'][rname]
|
||||
fvar = rout['vars'][fname]
|
||||
if not isintent_out(fvar):
|
||||
if 'intent' not in fvar:
|
||||
fvar['intent'] = []
|
||||
fvar['intent'].append('out')
|
||||
flag = 1
|
||||
for i in fvar['intent']:
|
||||
if i.startswith('out='):
|
||||
flag = 0
|
||||
break
|
||||
if flag:
|
||||
fvar['intent'].append(f'out={rname}')
|
||||
rout['args'][:] = [fname] + rout['args']
|
||||
return rout, createfuncwrapper(rout)
|
||||
if issubroutine_wrap(rout):
|
||||
fortranname = getfortranname(rout)
|
||||
name = rout['name']
|
||||
outmess('\t\tCreating wrapper for Fortran subroutine "%s"("%s")...\n'
|
||||
% (name, fortranname))
|
||||
rout = copy.copy(rout)
|
||||
return rout, createsubrwrapper(rout)
|
||||
return rout, ''
|
Reference in New Issue
Block a user