@@ -229,3 +229,48 @@ mul!(similar(x)', x', A)
229
229
# corresponding 5-arg `mul!` methods. This may seem like a lot of methods to
230
230
# be implemented, but note that adding such methods is only necessary/recommended
231
231
# for performance.
232
+
233
+ # ## Computing a matrix representation
234
+
235
+ # In some cases, it might be necessary to compute a matrix representation of a `LinearMap`.
236
+ # This is essentially done via the
237
+ # `[LinearMaps._unsafe_mul!(::Matrix,::LinearMap,::Number)]`(@ref) method, for which a
238
+ # generic fallback exists: it applies the `LinearMap` successively to the standard unit
239
+ # vectors.
240
+
241
+ F = MyFillMap (5 , (100 ,100 ))
242
+ M = Matrix {eltype(F)} (undef, size (F))
243
+ @benchmark Matrix ($ F)
244
+ @benchmark LinearMaps. _unsafe_mul! ($ (Matrix {Int} (undef, (100 ,100 ))), $ (MyFillMap (5 , (100 ,100 ))), true )
245
+
246
+ # If a more performant implementation exists, it is recommended to overwrite this method,
247
+ # for instance (as before, size checks need not be included here since they are handled by
248
+ # the corresponding `LinearAlgebra.mul!` method):
249
+
250
+ LinearMaps. _unsafe_mul! (M:: AbstractMatrix , A:: MyFillMap , s:: Number ) = fill! (M, A. λ* s)
251
+ @benchmark Matrix ($ F)
252
+ @benchmark LinearMaps. _unsafe_mul! ($ (Matrix {Int} (undef, (100 ,100 ))), $ (MyFillMap (5 , (100 ,100 ))), true )
253
+
254
+ # As one can see, the above runtimes are dominated by the allocation of the output matrix,
255
+ # but still overwriting the multiplication kernel yields a speed-up of about factor 3 for
256
+ # the matrix filling part.
257
+
258
+ # ## Slicing
259
+
260
+ # As usual, generic fallbacks for `LinearMap` slicing exist and are handled by the following
261
+ # method hierarchy, where at least one of `I` and `J` has to be a `Colon`:
262
+ #
263
+ # Base.getindex(::LinearMap, I, J)
264
+ # -> LinearMaps._getindex(::LinearMap, I, J)
265
+ #
266
+ # The method `Base.getindex` checks the validity of the the requested indices and calls
267
+ # `LinearMaps._getindex`, which should be overloaded for custom `LinearMap`s subtypes.
268
+ # For instance:
269
+
270
+ @benchmark F[1 ,:]
271
+
272
+ LinearMaps. _getindex (A:: MyFillMap , :: Integer , J:: Base.Slice ) = fill (A. λ, axes (J))
273
+ @benchmark F[1 ,:]
274
+
275
+ # Note that in `Base.getindex` `Colon`s are converted to `Base.Slice` via
276
+ # `Base.to_indices`, thus the dispatch must be on `Base.Slice` rather than on `Colon`.
0 commit comments