New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add triangular indices functions #4601
Add triangular indices functions #4601
Conversation
…dices_from` Mirrors the implementation from numpy
Will need to update #4074 when merged |
@EPronovost thanks for implementing and submitting this. I have queued it for an initial review. |
FYI: CI errors are probably unrelated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good so far! Some exception testing and corner cases will still need to be addressed.
@EPronovost thanks again for submitting this and welcome to Numba! I have reviewed your submission and it looks really good so far. There are a few things that still need to be addressed and I left some comments inline for your consideration. If anything is unclear or confusing, please don't hesitate to ask. |
* Add explicit test for `n, m` arguments * Factored out test code for `triu_indices` * Fixed spacing for flake8
4f5159a
to
2993966
Compare
@EPronovost thanks for making these changes and addressing the comments from the review, I will look at them today. Just a word of warning, I saw that you have force pushed the branch, probably due to a git rebase or similar operation. We have had some bad experiences with GitHub loosing review comments and discussions because it can no longer assign them to the respective source lines so we generally discourage the use of rebase. Instead we generally tend to recommend merging |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is in great shape, probably just a few more tidbits to fix, getting close to being mergeable.
numba/targets/arraymath.py
Outdated
@register_jitable | ||
def _check_is_integer(v, name): | ||
if not isinstance(v, (int, types.Integer)): | ||
raise TypeError('{} must be an integer'.format(name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We generally tend to use TypingError
in these cases rather than TypeError
. This is to indicate that Numba failed during type inference.
|
||
def tril_indices_n_k_m(n, k=0, m=None): | ||
return np.tril_indices(n, k, m) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is one last corner case that you should address:
def tril_indices_n_k_m(n, k=0, m=None):
return np.tril_indices(n, k=k, m=m)
I.e. supplying the arguments as keyword arguments. I recently discovered that this might lead to slightly different path and should be checked to be safe.
numba/tests/test_np_functions.py
Outdated
|
||
with self.assertTypingError() as raises: | ||
cfunc(4, k=1.5) | ||
assert "k must be an integer" in str(raises.exception) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible, can you add some code to test the exceptions for m
and n
too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, please use self.assertIn()
, Numba employs unittest
style testing.
Use TypingError instead of TypeError to indicate that the error happened during TypeInference. Also. use unittest style testing with assertIn.
The ndim attribute is already available in the typing context. Removing an additional if-branch in the implementation is cleaner and will most likely accelerate the function a little, especially when called in a tight loop.
@EPronovost FYI: we would like to get this PR in to the next RC. I have tended to this PR and pushed some commits to your branch so that it has a chance of making it into the next release. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@esc thanks for the fixes, I've added some notes/comments for you.
numba/targets/arraymath.py
Outdated
@@ -614,6 +614,12 @@ def check_array(a): | |||
raise ValueError('zero-size array to reduction operation not possible') | |||
|
|||
|
|||
@register_jitable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this being compiled? the type is known at typing time?
numba/targets/arraymath.py
Outdated
# we require integer arguments, unlike numpy | ||
_check_is_integer(n, 'n') | ||
_check_is_integer(k, 'k') | ||
if m is not None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a numba.numpy_support.is_nonelike
case, None literal vs NoneType. Merge in master to get that function from it's new API home.
This ought to work:
from numba import njit
import numpy as np
@njit
def triu_indices_n(n, k=0, m=None):
return np.triu_indices(n, k, m)
print(triu_indices_n(2))
print(triu_indices_n.py_func(2))
something like (but with the import at the top of file) will likely sort it:
from numba.numpy_support import is_nonelike
if not is_nonelike(m):
_check_is_integer(m, 'm')
same argument applies to the tril
case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, the tests don't actually capture this case..
numba/tests/test_np_functions.py
Outdated
|
||
for dtype in [int, float, bool]: | ||
for n in range(10): | ||
for m in range(10): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
itertools.product
!?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
self.assertEqual(type(expected), type(got)) | ||
self.assertEqual(len(expected), len(got)) | ||
for e, g in zip(expected, got): | ||
np.testing.assert_array_equal(e, g) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd assume that the arrays returned would be int
type so self.assertPreciseEqual
perhaps could be used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this, and the strides turned out to be different:
FAIL: test_tril_indices_from (numba.tests.test_np_functions.TestNPFunctions)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/vhaenel/git/numba/numba/tests/test_np_functions.py", line 1288, in test_tril_indices_from
self._triangular_indices_from_tests_arr(tril_indices_from_arr)
File "/Users/vhaenel/git/numba/numba/tests/test_np_functions.py", line 1221, in _triangular_indices_from_tests_arr
self.assertPreciseEqual(e, g)
File "/Users/vhaenel/git/numba/numba/tests/support.py", line 270, in assertPreciseEqual
self.fail("when comparing %s and %s: %s" % (first, second, failure_msg))
AssertionError: when comparing [0 1] and [0 1]: Lists differ: [2.0] != [1.0]
First differing element 0:
2.0
1.0
- [2.0]
? ^
+ [1.0]
? ^
: different strides
numba/tests/test_np_functions.py
Outdated
def _triangular_indices_exceptions(self, pyfunc): | ||
cfunc = jit(nopython=True)(pyfunc) | ||
|
||
# Exceptions leak references |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be resolvable at typing time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed
numba/tests/test_np_functions.py
Outdated
|
||
for dtype in [int, float, bool]: | ||
for n in range(10): | ||
for m in range(10): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
itertools.product
!?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
numba/tests/test_np_functions.py
Outdated
for dtype in [int, float, bool]: | ||
for n in range(10): | ||
for m in range(10): | ||
arr = np.ones((n, m), dtype) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is just testing matrices that are full? given the alg, perhaps put in some zeros via a slice with step or similar?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean randomly or with structure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't think it matters, whatever is convenient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually, ignore this, am remembering a different function!
The type-checking does not need to be compiled. Also, this means potentially more flexibility.
* master: (54 commits) Add __init__.py files to ensure `numba/cext` directory is installed. Move get_extension_libs() into `numba/cext/__init__.py`. Fix doc build Add checks on the status of the dtor execution. Apply suggestions from code review Fix docs WRT new compiler pass infrastructure. Respond to review Update arraymath.py Fix numba#4589. Just pass NULL for b2d_func for constant dynamic sharedmem per block. No need for cfunc. Fix test Turn off verbose Fix missing int64_t on w32 Update numpysupported.rst Add checks Ensure include_path() returns an absolute path Turn on verbose to debug Add missing nrt.py file Add docs Add intrinsic that calls NRT_get_api() Fix py2 problem with Py_hash_t Rename to NRT_get_api, add method get_data, refactor test ...
When calling a function like: ``` @njit def func(a, b=None): # code ``` We also need to call it like: ``` func(1) ``` To make sure that we don't reject a plain None when b is a NoneType. In this case, this test was missing, but could be fixed by using `is_nonlike` to perform typechecking.
Instead of two nested for loops.
Need to test the type check for n and m too.
Canceled build, will update with new changes shortly. |
@stuartarchibald can you give it another quick look? I think it's almost ready for 'waiting on CI'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the fixes.
It seems the tests are failing for Python 2.7 because |
@esc please could you take a look at the Py2.7 issue, there might be something to help in |
As title.
Add
tril_indices
,tril_indices_from
,triu_indices
, andtriu_indices_from
Mirrors the implementation from numpy