Repository: Theano/Theano

Issue:
bug with T.set_subtensor()
``` python
def rec_area(R):
    '''
    x_min, x_max, y_min, y_max
    '''
    return (R[:,1] - R[:,0]) * (R[:,3] - R[:,2])

def max_mat(M1, M2):
    return M1 * (M1 > M2) + M2 * (M2 >= M1)

def min_mat(M1, M2):
    return M1 * (M1 < M2) + M2 * ( M2 <= M1)

def jaccard_box_score(R1, R2):
    '''
    x_min, x_max, y_min, y_max
    '''
    intercept = max_mat(T.zeros((R1.shape[0],)), min_mat(R1[:,1], R2[:,1]) - max_mat(R1[:,0], R2[:,0])) * \
                max_mat(T.zeros((R1.shape[0],)), min_mat(R1[:,3], R2[:,3]) - max_mat(R1[:,2], R2[:,2]))
    A1 = rec_area(R1)
    A2 = rec_area(R2)
    denom = A1 + A2 - intercept

    X = intercept / denom
    Z = T.set_subtensor(X[T.eq(denom,0).nonzero()], -1)

    return Z

def testing(R1, R2):
    y = R1 / R2
    X = T.set_subtensor(y[T.eq(R2,0).nonzero()], -1)
    return X

if __name__ == '__main__':
    R1 = T.matrix()
    R2 = T.matrix()
    f = theano.function([R1, R2], jaccard_box_score(R1, R2)) 
    print f(np.asarray([[1,2,2,3],[0,0,0,0],[1,2,3,4]]), np.asarray([[2,3,2,3],[0,0,0,0],[2,0,3,0]])) # returns nan is not set to -1

   f = theano.function([R1, R2], testing(R1, R2)) # returns nan is set to -1
```

The `nan` or `inf` produced by `testing` when the denominator is 0 is set successfully to -1 with using `X = T.set_subtensor(y[T.eq(R2,0).nonzero()], -1)`, however doing exactly the same thing in `jaccard_box_score` with `T.set_subtensor(X[T.eq(denom,0).nonzero()], -1)`, the `nan` remains as nan. I wonder why.



Discussion:
This looks like an actual bug in `AdvancedIncSubtensor1`.
Running your example in DebugMode with check_finite turned off gives me the error message below, indicating that the Python code gave the expected value, but the C code did not.

The reason the second example works is that `denom` is a vector whereas `R2` is a matrix, so `T.eq(denom, 0).nonzero()` is a vector, whereas `T.eq(R2, 0).nonzero()` is a pair of vectors.
Indexing with 1 vector is implemented by `AdvancedIncSubtensor1`, but indexing with 2 vectors uses `AdvancedIncSubtensor`, which does not exhibit the problem.

```
BadThunkOutput: BadThunkOutput
  Apply   : AdvancedIncSubtensor1{no_inplace,set}(Elemwise{true_div,no_inplace}.0, TensorConstant{-1}, Subtensor{int64}.0)
  op      : <class 'theano.tensor.subtensor.AdvancedIncSubtensor1'>
  Outputs Type: TensorType(float64, vector)
  Outputs Shape: (3,)
  Outputs Strides: (8,)
  Inputs Type : [TensorType(float64, vector), TensorType(int8, scalar), TensorType(int64, vector)]
  Inputs Shape: [(3,), (), (1,)]
  Inputs Strides: [(8,), (), (8,)]
  Inputs values: [array([  0.,  nan,   0.]), array(-1, dtype=int8), array([1])]
  Bad Variable: AdvancedIncSubtensor1{no_inplace,set}.0
  thunk1  : perform
  thunk2  : c_code
           : shape, dtype, strides, min, max, n_inf, n_nan:
  Expected : (3,) float64 (8,) -1.0 0.0 0 0 
  Value    : (3,) float64 (8,) nan nan 0 1 
  expected    : [ 0. -1.  0.]
  value    : [  0.  nan   0.]
  Max Abs Diff:  nan
  Mean Abs Diff:  nan
  Median Abs Diff:  0.0
  Std Abs Diff:  nan
  Max Rel Diff:  nan
  Mean Rel Diff:  nan
  Median Rel Diff:  nan
  Std Rel Diff:  nan

  rtol, atol: 1e-06 1e-08

```


Resolving patch:
diff --git a/theano/gof/cutils.py b/theano/gof/cutils.py
--- a/theano/gof/cutils.py
+++ b/theano/gof/cutils.py
@@ -41,13 +41,16 @@ def compile_cutils_code():
     #endif
     """
 
-    floatadd = ("((%(type)s*)mit->dataptr)[0] = inc_or_set * "
-                "((%(type)s*)mit->dataptr)[0] + ((%(type)s*)it->dataptr)[0];")
+    floatadd = ("((%(type)s*)mit->dataptr)[0] = "
+                "(inc_or_set ? ((%(type)s*)mit->dataptr)[0] : 0)"
+                " + ((%(type)s*)it->dataptr)[0];")
     complexadd = """
-    ((%(type)s*)mit->dataptr)[0].real = inc_or_set *
-       ((%(type)s*)mit->dataptr)[0].real + ((%(type)s*)it->dataptr)[0].real;
-    ((%(type)s*)mit->dataptr)[0].imag = inc_or_set *
-       ((%(type)s*)mit->dataptr)[0].imag + ((%(type)s*)it->dataptr)[0].imag;
+    ((%(type)s*)mit->dataptr)[0].real =
+        (inc_or_set ? ((%(type)s*)mit->dataptr)[0].real : 0)
+        + ((%(type)s*)it->dataptr)[0].real;
+    ((%(type)s*)mit->dataptr)[0].imag =
+        (inc_or_set ? ((%(type)s*)mit->dataptr)[0].imag : 0)
+        + ((%(type)s*)it->dataptr)[0].imag;
     """
 
     fns = ''.join([inplace_map_template % {'type': t, 'typen': t.upper(),


Test patch: