6161 MatrixAlgebraKit.select_algorithm(f, A, (; kwargs...))
6262
6363Decide on an algorithm to use for implementing the function `f` on inputs of type `A`.
64+ This can be obtained both for values `A` or types `A`.
6465
6566If `alg` is an `AbstractAlgorithm` instance, it will be returned as-is.
6667
@@ -73,62 +74,62 @@ automatically with [`MatrixAlgebraKit.default_algorithm`](@ref) and
7374the keyword arguments in `kwargs` will be passed to the algorithm constructor.
7475Finally, the same behavior is obtained when the keyword arguments are
7576passed as the third positional argument in the form of a `NamedTuple`.
76- """
77- function select_algorithm end
77+ """ select_algorithm
7878
7979function select_algorithm(f:: F , A, alg:: Alg = nothing ; kwargs... ) where {F,Alg}
80- return _select_algorithm (f, A , alg; kwargs... )
80+ return select_algorithm (f, typeof(A) , alg; kwargs... )
8181end
82+ function select_algorithm(f:: F , :: Type{A} , alg:: Alg = nothing ; kwargs... ) where {F,A,Alg}
83+ if isnothing(alg)
84+ return default_algorithm(f, A; kwargs... )
85+ elseif alg isa Symbol
86+ return Algorithm{alg}(; kwargs... )
87+ elseif alg isa Type
88+ return alg(; kwargs... )
89+ elseif alg isa NamedTuple
90+ isempty(kwargs) ||
91+ throw(ArgumentError(" Additional keyword arguments are not allowed when algorithm parameters are specified." ))
92+ return default_algorithm(f, A; alg... )
93+ elseif alg isa AbstractAlgorithm
94+ isempty(kwargs) ||
95+ throw(ArgumentError(" Additional keyword arguments are not allowed when algorithm parameters are specified." ))
96+ return alg
97+ end
8298
83- function _select_algorithm(f:: F , A, alg:: Nothing ; kwargs... ) where {F}
84- return default_algorithm(f, A; kwargs... )
85- end
86- function _select_algorithm(f:: F , A, alg:: Symbol ; kwargs... ) where {F}
87- return Algorithm{alg}(; kwargs... )
88- end
89- function _select_algorithm(f:: F , A, :: Type{Alg} ; kwargs... ) where {F,Alg}
90- return Alg(; kwargs... )
91- end
92- function _select_algorithm(f:: F , A, alg:: NamedTuple ; kwargs... ) where {F}
93- isempty(kwargs) ||
94- throw(ArgumentError(" Additional keyword arguments are not allowed when algorithm parameters are specified." ))
95- return default_algorithm(f, A; alg... )
96- end
97- function _select_algorithm(f:: F , A, alg:: AbstractAlgorithm ; kwargs... ) where {F}
98- isempty(kwargs) ||
99- throw(ArgumentError(" Additional keyword arguments are not allowed when an algorithm is specified." ))
100- return alg
101- end
102- function _select_algorithm(f:: F , A, alg; kwargs... ) where {F}
103- return throw(ArgumentError(" Unknown alg $alg " ))
99+ throw(ArgumentError(" Unknown alg $alg " ))
104100end
105101
102+
106103@doc """
107104 MatrixAlgebraKit.default_algorithm(f, A; kwargs...)
105+ MatrixAlgebraKit.default_algorithm(f, ::Type{TA}; kwargs...) where {TA}
108106
109107Select the default algorithm for a given factorization function `f` and input `A`.
110108In general, this is called by [`select_algorithm`](@ref) if no algorithm is specified
111109explicitly.
112- """
113- function default_algorithm end
110+ New types should prefer to register their default algorithms in the type domain.
111+ """ default_algorithm
112+ default_algorithm(f:: F , A; kwargs... ) where {F} = default_algorithm(f, typeof(A); kwargs... )
113+ # avoid infinite recursion:
114+ function default_algorithm(f:: F , :: Type{T} ; kwargs... ) where {F,T}
115+ throw(MethodError(default_algorithm, (f, T)))
116+ end
114117
115118@doc """
116119 copy_input(f, A)
117120
118121Preprocess the input `A` for a given function, such that it may be handled correctly later.
119122This may include a copy whenever the implementation would destroy the original matrix,
120123or a change of element type to something that is supported.
121- """
122- function copy_input end
124+ """ copy_input
123125
124126@doc """
125127 initialize_output(f, A, alg)
126128
127129Whenever possible, allocate the destination for applying a given algorithm in-place.
128130If this is not possible, for example when the output size is not known a priori or immutable,
129131this function may return `nothing`.
130- """
131- function initialize_output end
132+ """ initialize_output
132133
133134# Utility macros
134135# --------------
@@ -176,25 +177,35 @@ macro functiondef(f)
176177 f isa Symbol || throw(ArgumentError(" Unsupported usage of `@functiondef`" ))
177178 f! = Symbol(f, :! )
178179
179- return esc(quote
180- # out of place to inplace
181- $ f(A; kwargs... ) = $ f!(copy_input($ f, A); kwargs... )
182- $ f(A, alg:: AbstractAlgorithm ) = $ f!(copy_input($ f, A), alg)
183-
184- # fill in arguments
185- function $ f!(A; alg= nothing , kwargs... )
186- return $ f!(A, select_algorithm($ f!, A, alg; kwargs... ))
187- end
188- function $ f!(A, out; alg= nothing , kwargs... )
189- return $ f!(A, out, select_algorithm($ f!, A, alg; kwargs... ))
190- end
191- function $ f!(A, alg:: AbstractAlgorithm )
192- return $ f!(A, initialize_output($ f!, A, alg), alg)
193- end
194-
195- # copy documentation to both functions
196- Core. @__doc__ $ f, $ f!
197- end )
180+ ex = quote
181+ # out of place to inplace
182+ $ f(A; kwargs... ) = $ f!(copy_input($ f, A); kwargs... )
183+ $ f(A, alg:: AbstractAlgorithm ) = $ f!(copy_input($ f, A), alg)
184+
185+ # fill in arguments
186+ function $ f!(A; alg= nothing , kwargs... )
187+ return $ f!(A, select_algorithm($ f!, A, alg; kwargs... ))
188+ end
189+ function $ f!(A, out; alg= nothing , kwargs... )
190+ return $ f!(A, out, select_algorithm($ f!, A, alg; kwargs... ))
191+ end
192+ function $ f!(A, alg:: AbstractAlgorithm )
193+ return $ f!(A, initialize_output($ f!, A, alg), alg)
194+ end
195+
196+ # define fallbacks for algorithm selection
197+ @inline function select_algorithm(:: typeof ($ f), :: Type{A} , alg:: Alg ;
198+ kwargs... ) where {Alg,A}
199+ return select_algorithm($ f!, A, alg; kwargs... )
200+ end
201+ @inline function default_algorithm(:: typeof ($ f), :: Type{A} ; kwargs... ) where {A}
202+ return default_algorithm($ f!, A; kwargs... )
203+ end
204+
205+ # copy documentation to both functions
206+ Core. @__doc__ $ f, $ f!
207+ end
208+ return esc(ex)
198209end
199210
200211"""
0 commit comments