diff options
author | Pearu Peterson <pearu.peterson@gmail.com> | 2011-02-25 22:34:48 +0200 |
---|---|---|
committer | Pearu Peterson <pearu.peterson@gmail.com> | 2011-02-25 22:34:48 +0200 |
commit | cafd2df2336258b6a107d827f60b89d20a967653 (patch) | |
tree | 340e1aad654c7375e2ee213b0b251bd3dc483ffd /numpy/f2py | |
parent | c0e1c0000f27b55dfd5aa4b1674a8c1b6ac38c36 (diff) | |
download | numpy-cafd2df2336258b6a107d827f60b89d20a967653.tar.gz |
WIP: added assumed shape array support to Fortran functions.
Diffstat (limited to 'numpy/f2py')
-rwxr-xr-x | numpy/f2py/crackfortran.py | 20 | ||||
-rw-r--r-- | numpy/f2py/func2subr.py | 42 | ||||
-rw-r--r-- | numpy/f2py/tests/src/assumed_shape/foo_free.f90 | 34 | ||||
-rw-r--r-- | numpy/f2py/tests/test_assumed_shape.py | 25 |
4 files changed, 106 insertions, 15 deletions
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index 032901af9..43bcfa259 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -78,6 +78,7 @@ f2py_version = __version__.version B['entry'] --- dictionary {entryname:argslist,..} B['varnames'] --- list of variable names given in the order of reading the Fortran code, useful for derived types. + B['saved_interface'] --- a string of scanned routine signature, defines explicit interface *** Variable definition is a dictionary D = B['vars'][<variable name>] = {'typespec'[,'attrspec','kindselector','charselector','=','typename']} @@ -1707,6 +1708,8 @@ def analyzebody(block,args,tab=''): continue if onlyfuncs and b['name'] not in onlyfuncs: continue + b['saved_interface'] = crack2fortrangen(b, '\n'+' '*6, as_interface=True) + else: as_=args b=postcrack(b,as_,tab=tab+'\t') if b['block']=='interface' and not b['body']: @@ -2451,7 +2454,7 @@ def determineexprtype(expr,vars,rules={}): return t ###### -def crack2fortrangen(block,tab='\n'): +def crack2fortrangen(block,tab='\n', as_interface=False): global skipfuncs, onlyfuncs setmesstext(block) ret='' @@ -2462,7 +2465,7 @@ def crack2fortrangen(block,tab='\n'): continue if onlyfuncs and g['name'] not in onlyfuncs: continue - ret=ret+crack2fortrangen(g,tab) + ret=ret+crack2fortrangen(g,tab,as_interface=as_interface) return ret prefix='' name='' @@ -2503,9 +2506,9 @@ def crack2fortrangen(block,tab='\n'): #if 'prefix' in block: # prefix=block['prefix']+' ' body=crack2fortrangen(block['body'],tab+tabchar) - vars=vars2fortran(block,block['vars'],al,tab+tabchar) + vars=vars2fortran(block,block['vars'],al,tab+tabchar, as_interface=as_interface) mess='' - if 'from' in block: + if 'from' in block and not as_interface: mess='! in %s'%block['from'] if 'entry' in block: entry_stmts = '' @@ -2558,7 +2561,7 @@ def true_intent_list(var): ret.append(intent) return ret -def vars2fortran(block,vars,args,tab=''): +def vars2fortran(block,vars,args,tab='', as_interface=False): """ TODO: public sub @@ -2579,9 +2582,10 @@ def vars2fortran(block,vars,args,tab=''): errmess('vars2fortran: Confused?!: "%s" is not defined in vars.\n'%a) if 'varnames' in block: nout.extend(block['varnames']) - for a in vars.keys(): - if a not in nout: - nout.append(a) + if not as_interface: + for a in vars.keys(): + if a not in nout: + nout.append(a) for a in nout: if 'depend' in vars[a]: for d in vars[a]['depend']: diff --git a/numpy/f2py/func2subr.py b/numpy/f2py/func2subr.py index 7ce30bc70..6ef8da3cb 100644 --- a/numpy/f2py/func2subr.py +++ b/numpy/f2py/func2subr.py @@ -75,6 +75,23 @@ def var2fixfortran(vars,a,fa=None,f90mode=None): 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 = 'f2py_%s_d%s' % (a, i) + dv = dict(typespec='integer', intent=['hide']) + dv['='] = 'shape(%s, %s)' % (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] = '%s\n %s'%(ret[0],line) @@ -82,7 +99,7 @@ def createfuncwrapper(rout,signature=0): fortranname = getfortranname(rout) f90mode = ismoduleroutine(rout) newname = '%sf2pywrap'%(name) - vars = rout['vars'] + if newname not in vars: vars[newname] = vars[name] args = [newname]+rout['args'][1:] @@ -98,14 +115,15 @@ def createfuncwrapper(rout,signature=0): charselect = vars[name]['charselector'] if charselect.get('*','')=='(*)': charselect['*'] = '10' + sargs = ', '.join(args) if f90mode: - sargs = ', '.join(args) add('subroutine f2pywrap_%s_%s (%s)'%(rout['modulename'],name,sargs)) if not signature: add('use %s, only : %s'%(rout['modulename'],fortranname)) else: - add('subroutine f2pywrap%s (%s)'%(name,', '.join(args))) - add('external %s'%(fortranname)) + add('subroutine f2pywrap%s (%s)'%(name,sargs)) + if not need_interface: + add('external %s'%(fortranname)) #if not return_char_star: l = l + ', '+fortranname args = args[1:] @@ -125,11 +143,18 @@ def createfuncwrapper(rout,signature=0): add(l) + if need_interface: + 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('%s = .not.(.not.%s(%s))'%(newname,fortranname,', '.join(args))) + add('%s = .not.(.not.%s(%s))'%(newname,fortranname,sargs)) else: - add('%s = %s(%s)'%(newname,fortranname,', '.join(args))) + add('%s = %s(%s)'%(newname,fortranname,sargs)) if f90mode: add('end subroutine f2pywrap_%s_%s'%(rout['modulename'],name)) else: @@ -140,7 +165,8 @@ def createfuncwrapper(rout,signature=0): return ret[0] def assubr(rout): - if not isfunction_wrap(rout): return rout,'' + if not isfunction_wrap(rout): + return rout,'' fortranname = getfortranname(rout) name = rout['name'] outmess('\t\tCreating wrapper for Fortran function "%s"("%s")...\n'%(name,fortranname)) @@ -165,3 +191,5 @@ def assubr(rout): rout['args'] = [fname] + rout['args'] return rout,createfuncwrapper(rout) + + diff --git a/numpy/f2py/tests/src/assumed_shape/foo_free.f90 b/numpy/f2py/tests/src/assumed_shape/foo_free.f90 new file mode 100644 index 000000000..43c076f15 --- /dev/null +++ b/numpy/f2py/tests/src/assumed_shape/foo_free.f90 @@ -0,0 +1,34 @@ + +subroutine sum(x, res) + implicit none + real, intent(in) :: x(:) + real, intent(out) :: res + + integer :: i + + print *, "sum: size(x) = ", size(x) + + res = 0.0 + + do i = 1, size(x) + res = x(i) + enddo + +end subroutine sum + +function fsum(x) result (res) + implicit none + real, intent(in) :: x(:) + real :: res + + integer :: i + + print *, "fsum: size(x) = ", size(x) + + res = 0.0 + + do i = 1, size(x) + res = res + x(i) + enddo + +end function fsum diff --git a/numpy/f2py/tests/test_assumed_shape.py b/numpy/f2py/tests/test_assumed_shape.py new file mode 100644 index 000000000..5784c54f9 --- /dev/null +++ b/numpy/f2py/tests/test_assumed_shape.py @@ -0,0 +1,25 @@ +import os +import math + +from numpy.testing import * +from numpy import array + +import util + +def _path(*a): + return os.path.join(*((os.path.dirname(__file__),) + a)) + +class TestMixed(util.F2PyTest): + sources = [_path('src', 'assumed_shape', 'foo_free.f90')] + + @dec.slow + def test_all(self): + print self.module.__doc__ + r = self.module.fsum([1,2]) + assert r==3,`r` + #r = self.module.sum([1,2]) + #assert r==3,`r` + +if __name__ == "__main__": + import nose + nose.runmodule() |