-
Notifications
You must be signed in to change notification settings - Fork 174
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
Addition of diag, eye, and trace #170
Conversation
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 looks great!
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 @ivan-pi for these functions. It looks nice.
Some comments:
-
It would maybe good to move the functions in submodules. It avoids the compilation of alll functions when modifying only some of them.
-
I think it could be easily extended to ranks >2 with the same API quite easily using fypp. However, EDIT: I am NOT the target user for such functions.
-
I wrote the tests by hand.
src/tests/linalg/test_linalg.f90
Outdated
|
||
print *, eye(5) | ||
|
||
print *, all(eye(4) == diag([1,1,1,1])) |
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.
Could the check
function be used here?
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 will add more tests with calls to check
. This was just temporary for development purposes.
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.
Nice. For internal stdlib tests, I suggest providing custom message in each check
call so we can identify which failed, and also with warn=.true.
to allow multiple tests to fail in a single test program.
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.
and also with
warn=.true.
to allow multiple tests to fail in a single test program.
@milancurcic With warn = .true.
multiple tests can fail, but ctest
will report that all tests passed. It is ok when we develop it. But before merging into master, we should probably have warn=.false.
.
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're right, I forgot about that. We shouldn't do it then. It's important that ctest correctly reports failure.
I agree. I expect that in the future we will likely have several linear algebra submodules (array creation routines, solvers, matrix properties...).
I don't think a tensor version of I can try to make numpy.trace(a, offset=0, axis1=0, axis2=1, dtype=None, out=None) which calculates the trace of each two-dimensional slice returning an array. But since the name With
I applaud your effort. 👏 |
Good point. I didn't think so far. |
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 great, IMO good to go pending any requested changes.
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.
Pending the tests, it looks good to me. Thank you.
In the routine to extract the
Interestingly, if implicit none
real :: res(-5)
print *, size(res)
end which prints "0" for both the ifort and gfortan compilers without any warnings. So it looks like Fortran had my back covered 😎 . Edit: a related issue appeared in the Intel Fortran Forum: https://software.intel.com/en-us/forums/intel-fortran-compiler/topic/297666. Here is a quote from the Fortran standard pertaining to this issue in the context of allocatable arrays:
Explicit-shape arrays also follow the same behavior. (e.g. https://groups.google.com/forum/#!topic/comp.lang.fortran/xGwU2diHm60) |
Is there any interest to extend |
Not from my side. For what would you use such a matrix? |
It could be used as a mask to unpack values into a certain diagonal or more generally as a mask in other functions. The numpy diag also allows it, in MATLAB I think logical masks are binary arrays, so it probably also just works. |
If other languages support it, it is probably good to support it too. Up to you to decide. I don't think I would need such a logical function. |
I was planning to have a go at the logical kind version, but would like to clarify first if it would suffice to support only the default logical kind or all those supported by the compiler (for some odd reason?):
Any thoughts? If not, pending a review of the tests, I would merge this. |
I think we can merge this now. We are in experimental, so any such changes / modifications can always be done later. |
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.
LGTM. I only have a couple of minor comments.
src/tests/linalg/test_linalg.f90
Outdated
msg="all(diag(a) == pack(a,mask))", warn=warn) | ||
call check(all(diag(diag(a)) == merge(a,0_int16,mask)), & | ||
msg="all(diag(diag(a)) == merge(a,0_int16,mask)) failed.", warn=warn) | ||
a = unpack(int([1,2,3,4],int16),eye(n)==1,a) |
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 believe that this line could be removed.
src/tests/linalg/test_linalg.f90
Outdated
a = reshape([(i**2,i=1,n*(n-1))],[n,n-1]) | ||
ans = sum([1._dp,36._dp,121._dp]) | ||
|
||
call check(abs(trace(a) - ans) < epsilon(1.0_dp), & |
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.
When submitting tests for mean
and var
, it was mentioned that epsilon()
is too strict. Therefore, you should multiply it by e.g., 1000 (see here for the current implementation) to avoid any issues.
Co-Authored-By: Jeremie Vandenplas <jeremie.vandenplas@gmail.com>
Thanks @jvdp1, @milancurcic, and @certik for the review and approvals. I've squashed the commits and will merge after the tests are completed. |
See proposal in #169 . This is a draft pull request.
This is my first time using the fypp preprocessor, so I decided to only focus on rank-2 arrays to keep things simple and submit a pull request before my focus shifts away from stdlib. Hopefully the API will not need to change if we decide to generalize these to higher rank-matrices, otherwise the generalizations could be placed into a
stdlib_tensor
module in the future.I am still missing the tests, but thought it would be beneficial to get some feedback on the functions and documentation first.
@jvdp1 Did you use fypp to generate the tests for the statistical routines and then committed only the generated .f90 files?