Skip to content
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

RFC: Refactoring to merge the code handling Adjoint and Transpose #33069

Closed
wants to merge 1 commit into from

Conversation

tkf
Copy link
Member

@tkf tkf commented Aug 25, 2019

I think the majority of code handling Adjoint and Transpose can be merged. The trick is to define a trait function

functor(::Type{<:Adjoint}) = adjoint
functor(::Type{<:Transpose}) = transpose

so that we can write code like this

function lmul!(adjA::AdjOrTrans{<:Any,<:UpperTriangular}, B::StridedVecOrMat)
A = adjA.parent
f = functor(adjA)
m, n = size(B, 1), size(B, 2)
if m != size(A, 1)
throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m"))
end
for j = 1:n
for i = m:-1:1
Bij = f(A.data[i,i]) * B[i,j]
for k = 1:i - 1
Bij += f(A.data[k,i]) * B[k,j]
end

Note that adjA can be a Adjoint or Transpose in above code. The function f is adjoint or transpose depending on the type of adjA.

I applied the idea to a few places so that you can see the impact of this change. You can already see that many lines can be removed.

What do you think? Does this refactoring makes sense?

true
```
"""
inplace(::typeof(adjoint)) = adjoint!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another alternative would be

functor!(::Type{<:Adjoint}) = adjoint!

@antoine-levitt
Copy link
Contributor

+1 on the refactor. The functor name is not great though. BLAS/LAPACK usually refer to this kind of thing as "op" in the doc and "trans" in the argnames, so maybe trans_op? Trans having the advantage that it's short for transform as well as transpose.

@tkf
Copy link
Member Author

tkf commented Aug 25, 2019

I find trans_op confusing (it says "trans" but can return adjoint?) but it's just an internal function so I don't mind changing the name if core devs say so.

@andreasnoack
Copy link
Member

I'm also in favor but I agree with @antoine-levitt about the name.

It looks like the change introduces some ambiguities.

@KristofferC
Copy link
Member

KristofferC commented Aug 26, 2019

Also, +1 for the refactor but functor and inplace sounds very generic when it does something quite specific to only two types. Something more direct and ugly like trans_or_adj would make the code clearer without having to look up the docstring of what seems to be a quite generic function.

@tkf
Copy link
Member Author

tkf commented Aug 26, 2019

OK so does

trans_or_adj(::Type{<:Adjoint}) = adjoint
trans_or_adj!(::Type{<:Adjoint}) = adjoint!

look fine for everyone?

It looks like the change introduces some ambiguities.

Can we do make ambiguity situation better? I suggest one simple solution in #33072. If there is no systematic solution I guess I'll do it the old way here...

@tkf
Copy link
Member Author

tkf commented Aug 26, 2019

Actually, I guess it probably should be something like

inplace_trans_or_adj(::Type{<:Adjoint}) = adjoint!

since otherwise

f! = trans_or_adj!(A)
f!(B)

might looke like we are mutating A as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
linear algebra Linear algebra
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants