Repository: numpy/numpy

Issue:
f2py - bug in calcualtion of array dimensions
I try to include a common f77 block from legacy code.  

some calculations in the conversion go wrong.

I have in my common block lines

```
      implicit real*8 (a-h,o-z)
      parameter ( nvar  = 3       )
      parameter ( jmz    = 1983 )

      common scmt(3*(jmz+1)), dbuf(nvar*(nvar+1) * (jmz+2))
```

resulting an a comlilation error

```
/tmp/tmpcpniavle/src.linux-x86_64-3.4/_keplermodule.c:1386:22: error: ânvarâ undeclared here (not in a function)
   {"dbuf",1,{{5955 * nvar + 5955}},NPY_DOUBLE},
```

it seems a bad line is generated and f2py does not resolve multiple occurrences (nvar) of the same parameter/variable in an expression?  at least inside sufficiently complex expressions?

If I define a parameter with nvar*(nvar+1) and use that new parameter, things work, but maybe if you get a chance to fix this fluke as well, that would be nice.  (or let me me know in what function for crackfortran even to look...)



Discussion:
@2sn would be good to comment on the relation between gh-5876 and this issue. I first thought that this was a duplicate issue, but it's slightly different right?

@Ralf This is basically independent from #5876 - this is why I submitted
them separately.

(the only relation being that they occurred compiling the same piece of
legacy code).

In contrast to #5876, I was not able to find where in crackfortran.py the
bug is located, would probably take me a few hours of debugging to even
find the routine. Likely the fix is more involved as well, and may require
proper debugging.

So

#5877 is about problems with array definitions that contain the same
variable twice in one expression - at least some cases.  This may or may
not be in common block, I have not tested that.

#5877 is about common blocks being continued in subsequent common
statements.  All compilers inc gcc 4.9.x seem to support this, f2py does
not (as stated in doc).  This submission provides a fix (doc needs to be
updated accordingly.)

On 17 May 2015 at 20:09, Ralf Gommers notifications@github.com wrote:

> @2sn https://github.com/2sn would be good to comment on the relation
> between gh-5876 https://github.com/numpy/numpy/issues/5876 and this
> issue. I first thought that this was a duplicate issue, but it's slightly
> different right?
> 
> ## 
> 
> Reply to this email directly or view it on GitHub
> https://github.com/numpy/numpy/issues/5877#issuecomment-102779469.

@pearu would be great if you could comment on this issue and the patch in gh-5876

To me, issues #5876 and #5877 are independent.

The patch in #5876 might fix the reported issue but I cannot tell immediately that it won't have any side effects to "normal" usage of common blocks. I would test it first.

To fix issue in #5877, I suggest the following patch

```
--- crackfortran.py.orig    2015-05-18 14:39:01.357203311 +0300
+++ crackfortran.py 2015-05-18 15:01:15.348972108 +0300
@@ -2197,9 +2197,10 @@
                         d = str(params[d])
                     for p in list(params.keys()):
                         m = re.match(r'(?P<before>.*?)\b'+p+r'\b(?P<after>.*)', d, re.I)
-                        if m:
+                        while m:
                             #outmess('analyzevars:replacing parameter %s in %s (dimension of %s) with %s\n'%(`p`,`d`,`n`,`params[p]`))
                             d = m.group('before')+str(params[p])+m.group('after')
+                            m = re.match(r'(?P<before>.*?)\b'+p+r'\b(?P<after>.*)', d, re.I)
                     if d==star:
                         dl = [star]
                     else:
```

This patch is against numpy 1.8.2 but it should be simple enough to apply it manually to newer versions. Sorry, this is what I can contribute in shortest amount of time..

Thanks @pearu!

@2sn would be useful to send the patch in gh-5876 as a pull request, then it's easier to test. If it passes all the `numpy.f2py` tests and doesn't break anything for Scipy then that covers a fair amount of regression testing. `scikits.bvp_solver` is the only other package I can think of right now which uses `f2py`.

@pearu thanks for the pointer where to look. I will try this fix in current
f2py and convert to pull request if it works

@ralf OK, will try to make a pull request for the fix (incl. update of doc
if I can find it - any hints?)

Also, is there a way to link a pull request to a current issue?

On 19 May 2015 at 05:44, Ralf Gommers notifications@github.com wrote:

> Thanks @pearu https://github.com/pearu!
> 
> @2sn https://github.com/2sn would be useful to send the patch in gh-5876
> https://github.com/numpy/numpy/issues/5876 as a pull request, then it's
> easier to test. If it passes all the numpy.f2py tests and doesn't break
> anything for Scipy then that covers a fair amount of regression testing.
> scikits.bvp_solver is the only other package I can think of right now
> which uses f2py.
> 
> ## 
> 
> Reply to this email directly or view it on GitHub
> https://github.com/numpy/numpy/issues/5877#issuecomment-103187912.

@2sn you can find the docs under `doc/source/f2py`.

Linking a PR to an issue is easy, just put `gh-xxxx` (with xxxx the issue number) in a comment.


Resolving patch:
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py
--- a/numpy/f2py/crackfortran.py
+++ b/numpy/f2py/crackfortran.py
@@ -2624,11 +2624,12 @@ def analyzevars(block):
                     if d in params:
                         d = str(params[d])
                     for p in list(params.keys()):
-                        m = re.match(
-                            r'(?P<before>.*?)\b' + p + r'\b(?P<after>.*)', d, re.I)
-                        if m:
+                        re_1 = re.compile(r'(?P<before>.*?)\b' + p + r'\b(?P<after>.*)', re.I)
+                        m = re_1.match(d)
+                        while m:
                             d = m.group('before') + \
                                 str(params[p]) + m.group('after')
+                            m = re_1.match(d)
                     if d == star:
                         dl = [star]
                     else:


Test patch: