Repository: nv-legate/cunumeric

Issue:
random.randint() multiple errors
Calls result in errors when minimal input is provided (no error if dtype is provided).
```
>>> import numpy as np
>>> import cunumeric as cn
>>> np.random.randint(1000)
293
>>> cn.random.randint(1000)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/coverage.py", line 106, in wrapper
    return func(*args, **kwargs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/random/random.py", line 113, in randint
    return nprandom.randint(low=low, high=high, size=size, dtype=dtype)
  File "mtrand.pyx", line 764, in numpy.random.mtrand.RandomState.randint
TypeError: Unsupported dtype dtype('float64') for randint
>>> cn.random.randint(1000,dtype=np.int32)
172
```
Calls result in errors when size is provided in array form (or if ND) (this happens regardless whether or not dtype is provided):
```
>>> cn.random.randint(1000,size=10)
array([317, 787, 968, 969,  10, 508, 778, 387, 976, 166])
>>> np.random.randint(1000,size=[10])
array([ 79, 325, 406, 740, 810, 830, 551, 640, 596, 857])
>>> cn.random.randint(1000,size=[10])
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/coverage.py", line 106, in wrapper
    return func(*args, **kwargs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/random/random.py", line 125, in randint
    result = ndarray(size, dtype=dtype)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/coverage.py", line 106, in wrapper
    return func(*args, **kwargs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/array.py", line 190, in __init__
    self._thunk = runtime.create_empty_thunk(shape, dtype, inputs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/runtime.py", line 499, in create_empty_thunk
    self.is_eager_shape(computed_shape)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/runtime.py", line 528, in is_eager_shape
    return volume <= self.max_eager_volume
TypeError: '<=' not supported between instances of 'list' and 'int'
>>> np.random.randint(1000,size=[10,10])
array([[ 33, 401, 305, 230, 610, 912, 661,  89, 245,  35],
       [639, 985, 902, 324, 270, 145, 121, 947, 817, 175],
       [458, 623, 160, 994, 263, 824, 304,  94, 492, 552],
       [907, 607,  16, 761, 323, 479, 122, 954, 749, 254],
       [146, 627, 161, 855, 573, 794, 731, 192, 988, 999],
       [628, 582, 815, 592, 765,  69, 416, 445, 339, 756],
       [504, 332, 910, 478,  14, 686,  77, 527, 186, 545],
       [353, 432,  38,  32, 229, 129, 248, 992, 292,  49],
       [380, 835, 754, 874, 136, 167, 497, 984, 951, 353],
       [164, 512, 899, 515, 405, 929, 268, 491, 542, 664]])
>>> cn.random.randint(1000,size=[10,10])
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/coverage.py", line 106, in wrapper
    return func(*args, **kwargs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/random/random.py", line 125, in randint
    result = ndarray(size, dtype=dtype)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/coverage.py", line 106, in wrapper
    return func(*args, **kwargs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/array.py", line 190, in __init__
    self._thunk = runtime.create_empty_thunk(shape, dtype, inputs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/runtime.py", line 499, in create_empty_thunk
    self.is_eager_shape(computed_shape)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/runtime.py", line 528, in is_eager_shape
    return volume <= self.max_eager_volume
TypeError: '<=' not supported between instances of 'list' and 'int'
```



Discussion:
Regarding the second problem, there is no errors if size is provided as a tuple, but doesn't work if it's an array or a list:
```
>>> a = (2,2)
>>> b = [2,2]
>>> c = np.array([2,2])
>>> np.random.randint(1000,size=a)
array([[878, 295],
       [411, 598]])
>>> cn.random.randint(1000,size=a)
array([[232, 465],
       [407,  29]])
>>> np.random.randint(1000,size=b)
array([[667, 548],
       [590, 713]])
>>> cn.random.randint(1000,size=b)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/coverage.py", line 106, in wrapper
    return func(*args, **kwargs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/random/random.py", line 125, in randint
    result = ndarray(size, dtype=dtype)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/coverage.py", line 106, in wrapper
    return func(*args, **kwargs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/array.py", line 190, in __init__
    self._thunk = runtime.create_empty_thunk(shape, dtype, inputs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/runtime.py", line 499, in create_empty_thunk
    self.is_eager_shape(computed_shape)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/runtime.py", line 528, in is_eager_shape
    return volume <= self.max_eager_volume
TypeError: '<=' not supported between instances of 'list' and 'int'
>>> np.random.randint(1000,size=c)
array([[976, 707],
       [363,  62]])
>>> cn.random.randint(1000,size=c)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/coverage.py", line 106, in wrapper
    return func(*args, **kwargs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/random/random.py", line 125, in randint
    result = ndarray(size, dtype=dtype)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/coverage.py", line 106, in wrapper
    return func(*args, **kwargs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/array.py", line 190, in __init__
    self._thunk = runtime.create_empty_thunk(shape, dtype, inputs)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/runtime.py", line 499, in create_empty_thunk
    self.is_eager_shape(computed_shape)
  File "/rkarimi_l/Work/cunumeric/cunumeric/cunumeric/runtime.py", line 518, in is_eager_shape
    if volume == 0:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
```

Resolving patch:
diff --git a/cunumeric/random/random.py b/cunumeric/random/random.py
--- a/cunumeric/random/random.py
+++ b/cunumeric/random/random.py
@@ -14,7 +14,7 @@
 #
 from __future__ import annotations
 
-from typing import TYPE_CHECKING, Any, Union
+from typing import TYPE_CHECKING, Any, Sequence, Union
 
 import numpy as np
 import numpy.random as nprandom
@@ -68,10 +68,10 @@ def rand(*shapeargs: int) -> Union[float, ndarray]:
 
 
 def randint(
-    low: Union[int, ndarray],
-    high: Union[int, ndarray, None] = None,
-    size: Union[int, tuple[int], None] = None,
-    dtype: Union[np.dtype[Any], None] = None,
+    low: Union[int, Sequence[int]],
+    high: Union[int, Sequence[int], None] = None,
+    size: Union[int, Sequence[int], None] = None,
+    dtype: Union[np.dtype[Any], type, None] = int,
 ) -> Union[int, ndarray, npt.NDArray[Any]]:
     """
     Return random integers from `low` (inclusive) to `high` (exclusive).
@@ -109,8 +109,14 @@ def randint(
     Multiple GPUs, Multiple CPUs
     """
 
+    if not isinstance(low, int):
+        raise NotImplementedError("'low' must be an integer")
+    if high is not None and not isinstance(high, int):
+        raise NotImplementedError("'high' must be an integer or None")
+
     if size is None:
         return nprandom.randint(low=low, high=high, size=size, dtype=dtype)
+
     if dtype is not None:
         dtype = np.dtype(dtype)
     else:
@@ -120,7 +126,7 @@ def randint(
         raise TypeError(
             "cunumeric.random.randint must be given an integer dtype"
         )
-    if not isinstance(size, tuple):
+    if isinstance(size, int):
         size = (size,)
     result = ndarray(size, dtype=dtype)
     if high is None:


Test patch: