Repository: numba/numba

Issue:
prange working with numpy?
<!--

Thanks for opening an issue! To help the Numba team handle your information
efficiently, please first ensure that there is no other issue present that
already describes the issue you have
(search at https://github.com/numba/numba/issues?&q=is%3Aissue).

For more general "how do I do X?" type questions, please speak to us in real
time on https://gitter.im/numba/numba or post to the Numba mailing list
https://groups.google.com/a/continuum.io/forum/#!forum/numba-users.

-->

## Reporting a bug

<!--

Before submitting a bug report please ensure that you can check off these boxes:

-->

- [x ] I am using the latest released version of Numba (most recent is visible in
 the change log (https://github.com/numba/numba/blob/master/CHANGE_LOG).
- [ x] I have included below a minimal working reproducer (if you are unsure how
 to write one see http://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports).

<!--

Please include details of the bug here, including, if applicable, what you
expected to happen!

-->


```python
from numba import njit, prange

@njit(parallel=True)
def f(arr):
    out = 0.0
    for i in prange(100):
        out += np.sum(arr[i:(i + 2)])
        # but following line is ok!
        out += 1


if __name__ == "__main__":
    import numpy as np
    arr = np.random.randn(10000)
    f(arr)

```

```
numba.core.errors.LoweringError: Failed in nopython mode pipeline (step: nopython mode backend)
Failed in nopython mode pipeline (step: nopython mode backend)
LLVM IR parsing error
<string>:499:18: error: invalid cast opcode for cast from 'i64' to 'double'
  %".408" = sext i64 %".406" to double
                 ^


File "test.py", line 6:
def f(arr):
    <source elided>
    out = 0.0
    for i in prange(100):
    ^

[1] During: lowering "id=1[LoopNest(index_variable = parfor_index.40, range = (0, $const10.1, 1))]{18: <ir.Block at test.py (6)>}Var(parfor_index.40, test.py:6)" at test.py (6)
```

```bash
>>> numba.__version__
'0.49.0dev0+995.gd0c7923c5'
```


Discussion:
bug confirmed
Issue debugged.  Working on fix.

Resolving patch:
diff --git a/numba/parfors/array_analysis.py b/numba/parfors/array_analysis.py
--- a/numba/parfors/array_analysis.py
+++ b/numba/parfors/array_analysis.py
@@ -89,22 +89,34 @@ def wrap_index(typingctx, idx, size):
     (idx < 0 ? idx + size : idx) because we may have situations
     where idx > size due to the way indices are calculated
     during slice/range analysis.
+
+    Both idx and size have to be Integer types.
+    size should be from the array size vars that array_analysis
+    adds and the bitwidth should match the platform maximum.
     """
-    unified_ty = typingctx.unify_types(idx, size)
-    # Mixing signed and unsigned ints will unify to double which is
-    # no good for indexing.  If the unified type is not an integer
-    # then just use int64 as the common index type.  This does have
-    # some overflow potential if the unsigned value is greater than
-    # 2**63.
-    if not isinstance(unified_ty, types.Integer):
-        unified_ty = types.int64
+    require(isinstance(idx, types.scalars.Integer))
+    require(isinstance(size, types.scalars.Integer))
+
+    # We need both idx and size to be platform size so that we can compare.
+    unified_ty = types.intp if size.signed else types.uintp
+    idx_unified = types.intp if idx.signed else types.uintp
 
     def codegen(context, builder, sig, args):
+        ll_idx_unified_ty = context.get_data_type(idx_unified)
         ll_unified_ty = context.get_data_type(unified_ty)
-        idx = builder.sext(args[0], ll_unified_ty)
-        size = builder.sext(args[1], ll_unified_ty)
+        if idx_unified.signed:
+            idx = builder.sext(args[0], ll_idx_unified_ty)
+        else:
+            idx = builder.zext(args[0], ll_idx_unified_ty)
+        if unified_ty.signed:
+            size = builder.sext(args[1], ll_unified_ty)
+        else:
+            size = builder.zext(args[1], ll_unified_ty)
         neg_size = builder.neg(size)
         zero = llvmlite.ir.Constant(ll_unified_ty, 0)
+        # If idx is unsigned then these signed comparisons will fail in those
+        # cases where the idx has the highest bit set, namely more than 2**63
+        # on 64-bit platforms.
         idx_negative = builder.icmp_signed("<", idx, zero)
         pos_oversize = builder.icmp_signed(">=", idx, size)
         neg_oversize = builder.icmp_signed("<=", idx, neg_size)


Test patch: