Re: [Numpy-discussion] f2py callback bug?

2009-11-25 Thread Pearu Peterson

Hi James,

To answer the second question, use:

   j = 1+numpy.array([2], numpy.int32)

The answer to the first question is that
the type of 1+numpy.array([2]) is
numpy.int64 but Fortran function expects
an array of type numpy.int32 and hence
the wrapper makes a copy of the input
array (which is also returned by the wrapper)
before passing it to Fortran.

Regards,
Pearu

James McEnerney wrote:
> Pearu,
> Thanks. a follow question.
> Using fortran
> 
>   subroutine calc(j)
> Cf2py intent(callback) pycalc
>   external pycalc
> Cf2py integer dimension(1), intent(in,out):: j
> 
>   integer j(1)
>   print *, 'in fortran before pycalc ', 'j=', j(1)
>   call pycalc(j)
>   print *, 'in fortran after pycalc ', ' j=', j(1)
>   end
> 
> in python
> 
> import foo,numpy
> def pycalc(j):
>
> print ' in pycalc ', 'j=', j
> j[:] = 20*j
> return
> 
> print foo.calc.__doc__
> j = 1+numpy.array([2])
> print foo.calc(j, pycalc)
> print j
> 
> the output is
> 
> calc - Function signature:
>   j = calc(j,pycalc,[pycalc_extra_args])
> Required arguments:
>   j : input rank-1 array('i') with bounds (1)
>   pycalc : call-back function
> Optional arguments:
>   pycalc_extra_args := () input tuple
> Return objects:
>   j : rank-1 array('i') with bounds (1)
> Call-back functions:
>   def pycalc(j): return j
>   Required arguments:
> j : input rank-1 array('i') with bounds (1)
>   Return objects:
> j : rank-1 array('i') with bounds (1)
> 
>  in fortran before pycalc j=   3
>  in pycalc  j= [3]
>  in fortran after pycalc  j=  60
> [60]
> [3]
> 
> Why is the return from foo.calc different from j?
> How do I make them the same?
> "return j" in pycalc doesn't change things.
> 
> Thanks again!
> 
> At 12:06 AM 11/25/2009, you wrote:
> 
> 
>> Pearu Peterson wrote:
>>
>> > Hmm, regarding `intent(in, out) j`, this should work. I'll check what
>> > is going on..
>>
>> The `intent(in, out) j` works when pycalc is defined as subroutine:
>>
>>call pycalc(i, j)
>>
>> instead of
>>
>>pyreturn = pycalc(i, j)
>>
>> Pearu
>> ___
>> NumPy-Discussion mailing list
>> NumPy-Discussion@scipy.org
>> http://*mail.scipy.org/mailman/listinfo/numpy-discussion
> 
> Jim McEnerney
> Lawrence Livermore National Laboratory
> 7000 East Ave.
> Livermore, Ca. 94550-9234
> 
> USA
> 
> 925-422-1963
> 
> 
> 
> 
> ___
> NumPy-Discussion mailing list
> NumPy-Discussion@scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] f2py callback bug?

2009-11-25 Thread James McEnerney


Pearu,
Thanks. a follow question. 
Using fortran
  subroutine calc(j)
Cf2py intent(callback) pycalc
  external pycalc
Cf2py integer dimension(1), intent(in,out):: j
  integer j(1)
  print *, 'in fortran before pycalc ',
'j=', j(1)
  call pycalc(j)
  print *, 'in fortran after pycalc ', '
j=', j(1)
  end
in python
import foo,numpy
def pycalc(j):
    
    print ' in pycalc ', 'j=', j
    j[:] = 20*j
    return 
print foo.calc.__doc__
j = 1+numpy.array([2])
print foo.calc(j, pycalc)
print j
the output is
calc - Function signature:
  j = calc(j,pycalc,[pycalc_extra_args])
Required arguments:
  j : input rank-1 array('i') with bounds (1)
  pycalc : call-back function
Optional arguments:
  pycalc_extra_args := () input tuple
Return objects:
  j : rank-1 array('i') with bounds (1)
Call-back functions:
  def pycalc(j): return j
  Required arguments:
    j : input rank-1 array('i') with bounds (1)
  Return objects:
    j : rank-1 array('i') with bounds (1)
 in fortran before pycalc
j=   3
 in pycalc  j= [3]
 in fortran after pycalc 
j=  60
[60]
[3]
Why is the return from foo.calc different from j?
How do I make them the same?
"return j" in pycalc doesn't change things.
Thanks again!
At 12:06 AM 11/25/2009, you wrote:

Pearu Peterson wrote:
> Hmm, regarding `intent(in, out) j`, this should work. I'll check
what
> is going on..
The `intent(in, out) j` works when pycalc is defined as
subroutine:
   call pycalc(i, j)
instead of
   pyreturn = pycalc(i, j)
Pearu
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org

http://*mail.scipy.org/mailman/listinfo/numpy-discussion

Jim McEnerney
Lawrence Livermore National Laboratory
7000 East Ave.
Livermore, Ca. 94550-9234
USA
925-422-1963


___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] f2py callback bug?

2009-11-25 Thread Pearu Peterson


Pearu Peterson wrote:

> Hmm, regarding `intent(in, out) j`, this should work. I'll check what
> is going on..

The `intent(in, out) j` works when pycalc is defined as subroutine:

   call pycalc(i, j)

instead of

   pyreturn = pycalc(i, j)

Pearu
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] f2py callback bug?

2009-11-24 Thread Pearu Peterson
Hi,

It is not really a bug what you are seeing..

In pycalc when assigning

j = 20 * j

you create a new object `j` and the argument object `j`, that links
back to Fortran data, gets discarded.
So, you can change j inplace, for example:

   j[:] = 20*j

The first argument `i` is int object that in Python is immutable,
and hence cannot be changed inplace and the corresponding Fortran
scalar object cannot be changed in the callback (in fact, `i`
is a copy of the corresponding Fortran data value).

To change `i` in Python callback, define it as an array
(similar to `j`) and do inplace operations with it.

Regarding pyreturn and assuming Fortran 77:
you cannot return arrays or multiple object in Fortran functions.
Fortran functions may return only scalars. So, the pyreturn trick will 
never work. The solution is to change arguments in place as with `j`.

Hmm, regarding `intent(in, out) j`, this should work. I'll check what
is going on..

HTH,
Pearu


James McEnerney wrote:
>   While using the call-back feature of f2py I stumbled across what appears
> to be a bug and I'm asking the community to look into this.
> 
> Background: I'm in the middle of converting some legacy fortran to python.
> There is one routine that is particulary thorny that calls more easily
> convertible service routines and my intention is to convert the latter
> and use the callback feature of f2py to execute them within the fortran
> followed by a systematic conversion of what remains.  This seems to be
> doable from what I've read on callback. I have not seen an example
> of using callback where the python actually changes parameters that are
> returned to the fortran; this is a requirement for me. While setting up
> an example to illustrate this I came across a syntactically correct
> situation(this means it compiles & executes) but gives the wrong answer.
> Here's the code:
> In fortran, source foo.f
>   subroutine calc(i, j)
> Cf2py intent(callback) pycalc
>   external pycalc
> Cf2py integer intent(in,out,copy):: i
> Cf2py integer dimension(1), intent(in,out):: j
>   integer pyreturn
> 
>   integer i, j(1)
>   print *, 'in fortran before pycalc ','i=',i, ' j=', j(1)
>   pyreturn = pycalc(i, j)
>   print *, 'in fortran after pycalc ','i=', i, ' j=', j(1)
> 
>   end
>  
> Standard build: f2py -c -m foo foo.f
> 
> In python, execute
> import foo,numpy
> 
> def pycalc(i, j):
> print ' in pycalc ', 'i=',i, 'j=', j
> i=10*i
> j = 20*j
> return i, j
> 
> print foo.calc.__doc__
> i=2
> j = 1+numpy.array([i])
> print foo.calc(i,j, pycalc)
> 
> Here's the output:
> calc - Function signature:
>   i,j = calc(i,j,pycalc,[pycalc_extra_args])
> Required arguments:
>   i : input int
>   j : input rank-1 array('i') with bounds (1)
>   pycalc : call-back function
> Optional arguments:
>   pycalc_extra_args := () input tuple
> Return objects:
>   i : int
>   j : rank-1 array('i') with bounds (1)
> Call-back functions:
>   def pycalc(i,j): return pyreturn,i,j
>   Required arguments:
> i : input int
> j : input rank-1 array('i') with bounds (1)
>   Return objects:
> pyreturn : int
> i : int
> j : rank-1 array('i') with bounds (1)
> 
> 
>  in fortran before pycalc i= 2 j= 3
>  in pycalc  i= 2 j= [3]
>  in fortran after pycalc i= 60 j= 3
> (60, array([3]))
> 
> The bug:
> on return to the fortran why is i=60 & j=3?
> shouldn't it be i=10 & j=60
> 
> While that's what I expect, I might not be defining the
> interface properly; but this compiles & executes. If this
> is incorrect, what is?  In the fortran, pyreturn appears
> to be an address; how do I get the retuned values?
> 
> I'm running 
> Redhat Linux
> python version 2.5
> f2py version 2_3979
> numpy version 1.0.3.1
> Thanks
> 
> Jim McEnerney
> Lawrence Livermore National Laboratory
> 7000 East Ave.
> Livermore, Ca. 94550-9234
> 
> USA
> 
> 925-422-1963
> 
> 
> 
> 
> ___
> NumPy-Discussion mailing list
> NumPy-Discussion@scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion


[Numpy-discussion] f2py callback bug?

2009-11-24 Thread James McEnerney


While using the call-back feature of
f2py I stumbled across what appears
to be a bug and I'm asking the community to look into this.
Background: I'm in the middle of converting some legacy fortran to
python.
There is one routine that is particulary thorny that calls more
easily
convertible service routines and my intention is to convert the
latter
and use the callback feature of f2py to execute them within the
fortran
followed by a systematic conversion of what remains.  This seems to
be 
doable from what I've read on callback. I have not seen an example
of using callback where the python actually changes parameters that
are
returned to the fortran; this is a requirement for me. While setting
up
an example to illustrate this I came across a syntactically correct 
situation(this means it compiles & executes) but gives the wrong
answer.
Here's the code:
In fortran, source foo.f
  subroutine calc(i, j)
Cf2py intent(callback) pycalc
  external pycalc
Cf2py integer intent(in,out,copy):: i
Cf2py integer dimension(1), intent(in,out):: j
  integer pyreturn
  integer i, j(1)
  print *, 'in fortran before pycalc
','i=',i, ' j=', j(1)
  pyreturn = pycalc(i, j)
  print *, 'in fortran after pycalc ','i=',
i, ' j=', j(1)
  end
  
Standard build: f2py -c -m foo foo.f
In python, execute
import foo,numpy
def pycalc(i, j):
    print ' in pycalc ', 'i=',i, 'j=', j
    i=10*i
    j = 20*j
    return i, j
print foo.calc.__doc__
i=2
j = 1+numpy.array([i])
print foo.calc(i,j, pycalc)
Here's the output:
calc - Function signature:
  i,j = calc(i,j,pycalc,[pycalc_extra_args])
Required arguments:
  i : input int
  j : input rank-1 array('i') with bounds (1)
  pycalc : call-back function
Optional arguments:
  pycalc_extra_args := () input tuple
Return objects:
  i : int
  j : rank-1 array('i') with bounds (1)
Call-back functions:
  def pycalc(i,j): return pyreturn,i,j
  Required arguments:
    i : input int
    j : input rank-1 array('i') with bounds (1)
  Return objects:
    pyreturn : int
    i : int
    j : rank-1 array('i') with bounds (1)

 in fortran before pycalc i= 2 j= 3
 in pycalc  i= 2 j= [3]
 in fortran after pycalc i= 60 j= 3
(60, array([3]))
The bug: 
on return to the fortran why is i=60 & j=3?
shouldn't it be i=10 & j=60
While that's what I expect, I might not be defining the
interface properly; but this compiles & executes. If this
is incorrect, what is?  In the fortran, pyreturn appears
to be an address; how do I get the retuned values?
I'm running  
Redhat Linux
python version 2.5
f2py version 2_3979
numpy version 1.0.3.1
Thanks

Jim McEnerney
Lawrence Livermore National Laboratory
7000 East Ave.
Livermore, Ca. 94550-9234
USA
925-422-1963


___
NumPy-Discussion mailing list
NumPy-Discussion@scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion