Repository: scipy/scipy

Issue:
weave.blitz produces different code for equal numpy ranges
When blitz is used to inline numpy expressions the outcome depends on the formating of the ranges, even if they are the same. For example a different result is produced for u[0:x] and u[:x] however the result should be the same.

See also:
http://stackoverflow.com/questions/16230848/blitz-code-produces-different-output

```
import numpy as np
from scipy.weave import blitz

def test_blitz_bug(N=4):
    ReI = 1.2
    ux_blitz_buggy, ux_blitz_not_buggy, ux_np = np.zeros((N, N)), np.zeros((N, N)), np.zeros((N, N))
    uxold = np.random.randn(N, N)
    ux_np[0:,1:-1] = uxold[0:,1:-1] + ReI* (uxold[0:,2:] - 2*uxold[0:,1:-1] + uxold[0:,0:-2])
    expr_buggy = 'ux_blitz_buggy[0:,1:-1] = uxold[0:,1:-1] + ReI* (uxold[0:,2:] - 2*uxold[0:,1:-1] + uxold[0:,0:-2])'
    expr_not_buggy = 'ux_blitz_not_buggy[:,1:-1] = uxold[:,1:-1] + ReI* (uxold[:,2:] - 2*uxold[:,1:-1] + uxold[:,0:-2])'
    blitz(expr_buggy)
    blitz(expr_not_buggy)
    assert not np.allclose(ux_blitz_buggy, ux_np)
    assert np.allclose(ux_blitz_not_buggy, ux_np)

if __name__ == '__main__':
    test_blitz_bug()
```



Discussion:
I've been testing this (I'm the one who answered that SO question) and I think the actual issue is that _assignment inside a blitz expression to a slice of the form `i:` fails_. A simplified test case is available [here](https://gist.github.com/Jorge-C/5473175). Notice that the issue lies in the left hand side (the right hand side is the same for both expressions).

Assignment to `:i` works fine:

``` Python
import numpy as np
from scipy.weave import blitz
import numpy.testing as npt


def test_no_bug():
    """Assignment to arr[:i] does not fail inside blitz expression."""
    N = 4
    expr_buggy = 'arr_blitz_buggy[:{0}] = arr[:{0}]'
    expr_not_buggy = 'arr_blitz_not_buggy[0:{0}] = arr[:{0}]'
    np.random.seed(7)
    arr = np.random.randn(N)
    for lim in [1, 2]:
        arr_blitz_buggy, arr_blitz_not_buggy, arr_np = np.zeros(N), np.zeros(N), np.zeros(N)
        blitz(expr_buggy.format(lim))
        blitz(expr_not_buggy.format(lim))
        arr_np[:lim] = arr[:lim]
        npt.assert_allclose(arr_blitz_buggy, arr_np)
        npt.assert_allclose(arr_blitz_not_buggy, arr_np)
```

Running it in scipy '0.13.0.dev-639ef30' gives a bunch of deprecation warnings, though.


Resolving patch:
diff --git a/scipy/weave/blitz_spec.py b/scipy/weave/blitz_spec.py
--- a/scipy/weave/blitz_spec.py
+++ b/scipy/weave/blitz_spec.py
@@ -20,7 +20,7 @@
 // declare them.
 
 int _beg = blitz::fromStart;
-int _end = blitz::toEnd;
+const int _end = blitz::toEnd;
 blitz::Range _all = blitz::Range::all();
 
 template<class T, int N>


Test patch:
diff --git a/scipy/weave/tests/test_blitz_tools.py b/scipy/weave/tests/test_blitz_tools.py
--- a/scipy/weave/tests/test_blitz_tools.py
+++ b/scipy/weave/tests/test_blitz_tools.py
@@ -6,9 +6,9 @@
 from numpy import float32, float64, complex64, complex128, \
      zeros, random, array, sum, abs, allclose
 
-from numpy.testing import TestCase, dec, assert_equal, assert_
+from numpy.testing import TestCase, dec, assert_equal, assert_, assert_allclose
 
-from scipy.weave import blitz_tools
+from scipy.weave import blitz_tools, blitz
 from scipy.weave.ast_tools import harvest_variables
 from weave_test_utils import empty_temp_dir, cleanup_temp_dir, remove_whitespace
 
@@ -181,6 +181,22 @@ def test_5point_avg_2d_complex_double(self):
                                   "+ b[1:-1,2:] + b[1:-1,:-2]) / 5."
         self.generic_2d(expr,complex128)
 
+@dec.slow
+def test_blitz_bug():
+    """Assignment to arr[i:] used to fail inside blitz expressions."""
+    N = 4
+    expr_buggy = 'arr_blitz_buggy[{0}:] = arr[{0}:]'
+    expr_not_buggy = 'arr_blitz_not_buggy[{0}:{1}] = arr[{0}:]'
+    random.seed(7)
+    arr = random.randn(N)
+    sh = arr.shape[0]
+    for lim in [0, 1, 2]:
+        arr_blitz_buggy, arr_blitz_not_buggy, arr_np = zeros(N), zeros(N), zeros(N)
+        blitz(expr_buggy.format(lim))
+        blitz(expr_not_buggy.format(lim, 'sh'))
+        arr_np[lim:] = arr[lim:]
+        assert_allclose(arr_blitz_buggy, arr_np)
+        assert_allclose(arr_blitz_not_buggy, arr_np)
 
 if __name__ == "__main__":
     import nose