`diagmat()`, `diagvec()`, and `.diag()` support
This MR implements support for diagonal matrices and diagonals. Unlike CPU-based Armadillo, the implementation is not based on the idea of a "Proxy" that can be used as an iterator, but instead uses handcrafted kernels to extract or manipulate diagonals. The diagview
class is adapted from Armadillo, building on @zoq's preliminary adaptation.
Functionality overview:
-
.diag()
operators added toMat
andsubview
; these returndiagview
s. - Support added to
Mat
to handlediagview
s; these typically extract the diagonal from the argument with theextract_diag
kernel, and then perform the requested operation. - Handling added for all
diagview
operations (element access, inplace operations,fill()
,clamp()
,zeros()
,ones()
,randu()
,randn()
). When possible custom kernels are used, but sometimes the convenient implementation for now is to extract the diagonal, perform the operation, and set the diagonal. - Added
diagmat()
anddiagvec()
functions that match Armadillo's API. - When
diagmat(A) * B
(or similar) is detected, special matrix multiplication handling via themul_colwise
,mul_rowwise
,mul_colwise_trans
, andmul_rowwise_trans
kernels is used. I think this actually might detect more complicated expressions than Armadillo, liketrans(diagmat(3 * A)) * 4 * trans(B)
or similar, but I have not checked for sure---I just glanced through the Armadillo code. - Tests for everything I could think of were added in
diag.cpp
.
Like so many things, it ended up being more code than I originally anticipated...
I'll let the MR sit for a couple days in case anyone has any comments and to give myself a chance to review it.