Skip to content

BUG: f2py incorrectly translates dimension declarations. #17654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 28, 2020

Conversation

ianthomas23
Copy link
Contributor

In fortran functions passed to f2py, calculations that occur in the dimensions of array declarations are interpreted as floats. Valid
fortran requires integers. Problem only occurs with fortran functions not subroutines as only for the former does f2py generate fortran wrapper code that fails to compile.

Relevant code is in numpy.f2py.crackfortran.getlincoef(), which calculates and returns the coefficients to getarrlen() for writing to the fortran wrapper code.

To convert floats to ints I have opted for try..except blocks which are common in crackfortran.py rather than explicit is_int() checks and conversion using int().

Fixes gh-8062.

In fortran functions passed to f2py, calculations that occur in the
dimensions of array declarations are interpreted as floats.  Valid
fortran requires integers.  Problem only occurs with fortran functions
not subroutines as only for the former does f2py generate fortran
wrapper code that fails to compile.

Relevant code is in numpy.f2py.crackfortran.getlincoef(), which
calculates and returns the coefficients to getarrlen() for writing to
the fortran wrapper code.

Fixes numpygh-8062.
@melissawm
Copy link
Member

Hello, @ianthomas23 ! Thanks for this. Note that this only happens if the expression inside the dimension declaration is actually simplified by f2py (which is not the case for a non-linear expression like a(0:n*n/2)). Fix seems OK to me, I don't know if there's a more elegant solution here than the try/except blocks :)

I think the Shippable failure is unrelated - don't understand what happened there.

@mattip
Copy link
Member

mattip commented Oct 28, 2020

s390x failure not connected to this PR

@mattip mattip merged commit 3cd6c57 into numpy:master Oct 28, 2020
@mattip
Copy link
Member

mattip commented Oct 28, 2020

Thanks @ianthomas23

Comment on lines +2162 to +2167
except:
pass
try:
b = int(b)
except:
pass
Copy link
Member

@eric-wieser eric-wieser Oct 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bare except is an antipattern, as this means that f2py now not only swallows Ctrl+C but give different compilation results depending on whether it was pressed. This should be except ValueError or at least except Exception?

Would you mind making a follow-up PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, that was my oversight. I can do a follow up if @ianthomas23 prefers.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reasons I don't understand, LGTM caught this, but decided to give a CI tick anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jhelie, I think we might have discussed this before - have we forgotten a config option, or is this working as intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eric-wieser, @melissawm: My apologies, I will submit a follow-up PR to change except to except ValueError. I'll wait until gh-17662 is accepted to avoid having to rebase.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need to rebase on that PR, since the lines aren't next to each other - github will sort out the merge automatically I'd expect

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Say, aren't both try / except clauses redundant here?
The original values of a and b are created by myeval(), which raises an exception if the return type is not a float or int:

def myeval(e, g=None, l=None):
r = eval(e, g, l)
if type(r) in [type(0), type(0.0)]:
return r
raise ValueError('r=%r' % (r))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch

code = """
function test(n, a)
integer, intent(in) :: n
real(8), intent(out) :: a(0:2*n/2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What shape should a(0:n/2*2) give when n is odd?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. Fortran uses integer maths is array declarations, so that shape here, in Python syntax, is (1+2*(n//2),)

I have submitted a new PR (gh-17687) to fix the original problem and it includes a test of this example.

Copy link
Member

@eric-wieser eric-wieser Nov 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does -(-n)/2*2 give in fortran? (edited) The python integer division is not the same as the integer division used in most languages.

ianthomas23 added a commit to ianthomas23/numpy that referenced this pull request Nov 1, 2020
Corrections to PR numpygh-17654 following post-merge review.  Fix now only
casts floats to integers if they are definitely integers.  Also,
division that occurs in fortran array declarations is evaluated in an
integer context, so f2py.crackfortran.myeval does the same, converting
single to double slashes.

Fixed numpygh-8062.
ianthomas23 added a commit to ianthomas23/numpy that referenced this pull request Nov 5, 2020
charris added a commit that referenced this pull request Nov 5, 2020
REV: Revert gh-17654 - f2py incorrectly translates dimension declarations.
@ianthomas23 ianthomas23 deleted the 8062_f2py_dimension_eval branch July 8, 2021 18:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

f2py incorrectly translate dimension declaration
5 participants