From 73ec36f3d8d73b9636c9403954ec6a55b028efe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20M=C3=BCller-Widmann?= Date: Wed, 7 Oct 2026 09:35:53 +0200 Subject: [PATCH] Add cheap lu_instance/qr_instance for FixedSizeArrays Previously `lu_instance` and `qr_instance` fell back to a full factorization for `FixedSizeMatrix`. The new `FixedSizeArraysExt` factorizes an empty `similar(A, 0, 0)` instead, which matches the factorization types for all eltypes (including BigFloat) and pivot modes. Fixes #510 Co-Authored-By: Claude Opus 5.5 --- Project.toml | 6 +++++- ext/FixedSizeArraysExt.jl | 15 +++++++++++++++ test/fixedsizearrays.jl | 17 +++++++++++++++++ test/runtests.jl | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 ext/FixedSizeArraysExt.jl create mode 100644 test/fixedsizearrays.jl diff --git a/Project.toml b/Project.toml index 78f60758..2475ad87 100644 --- a/Project.toml +++ b/Project.toml @@ -15,6 +15,7 @@ CUDSS = "45b445bb-4962-46a0-9369-b4df9d0f772e" ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" +FixedSizeArrays = "3821ddf9-e5b5-40d5-8e25-6813ab96b5e2" GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" Metal = "dde4c033-4e86-420c-a63e-0dd931031962" ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" @@ -38,6 +39,7 @@ ArrayInterfaceReverseDiffExt = "ReverseDiff" ArrayInterfaceSparseArraysExt = "SparseArrays" ArrayInterfaceStaticArraysCoreExt = "StaticArraysCore" ArrayInterfaceTrackerExt = "Tracker" +FixedSizeArraysExt = "FixedSizeArrays" [compat] AMDGPU = "2" @@ -51,6 +53,7 @@ ChainRulesCore = "1" ChainRulesTestUtils = "1" ComponentArrays = "0.4.1 - 0" FillArrays = "1" +FixedSizeArrays = "1" GPUArraysCore = "0.1, 0.2" JLArrays = "0.3" LinearAlgebra = "1.10" @@ -70,6 +73,7 @@ ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" ChainRulesTestUtils = "cdddcdb0-9152-4a09-a978-84456f9df70a" ComponentArrays = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66" FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" +FixedSizeArrays = "3821ddf9-e5b5-40d5-8e25-6813ab96b5e2" GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" JLArrays = "27aeb0d3-9eb9-45fb-866b-73c2ecf80fcb" JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899" @@ -86,4 +90,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" [targets] -test = ["SafeTestsets", "Pkg", "Test", "Aqua", "Random", "SparseArrays", "SuiteSparse", "BandedMatrices", "BlockBandedMatrices", "GPUArraysCore", "JLArrays", "StaticArrays", "Tracker", "ReverseDiff", "ChainRules", "FillArrays", "ComponentArrays", "ChainRulesTestUtils"] +test = ["SafeTestsets", "Pkg", "Test", "Aqua", "Random", "SparseArrays", "SuiteSparse", "BandedMatrices", "BlockBandedMatrices", "GPUArraysCore", "JLArrays", "StaticArrays", "Tracker", "ReverseDiff", "ChainRules", "FillArrays", "FixedSizeArrays", "ComponentArrays", "ChainRulesTestUtils"] diff --git a/ext/FixedSizeArraysExt.jl b/ext/FixedSizeArraysExt.jl new file mode 100644 index 00000000..b0415326 --- /dev/null +++ b/ext/FixedSizeArraysExt.jl @@ -0,0 +1,15 @@ +module FixedSizeArraysExt + +using ArrayInterface: ArrayInterface +using FixedSizeArrays: FixedSizeMatrix +using LinearAlgebra: lu, qr + +# Factorizing an empty matrix is cheap and yields exactly the factorization type +# of `A` (pivot vector types differ across eltypes, e.g. for BigFloat). +ArrayInterface.lu_instance(A::FixedSizeMatrix) = lu(similar(A, 0, 0), check = false) + +function ArrayInterface.qr_instance(A::FixedSizeMatrix, pivot = ArrayInterface.DEFAULT_CHOLESKY_PIVOT) + return qr(similar(A, 0, 0), pivot) +end + +end diff --git a/test/fixedsizearrays.jl b/test/fixedsizearrays.jl new file mode 100644 index 00000000..c20bf737 --- /dev/null +++ b/test/fixedsizearrays.jl @@ -0,0 +1,17 @@ +using ArrayInterface, FixedSizeArrays, LinearAlgebra, Test + +@testset "$T" for T in (Float64, Float32, ComplexF64, Int, BigFloat) + F = FixedSizeMatrix{T}(T.(rand(1:5, 4, 4)) + 10I) + + luF = ArrayInterface.lu_instance(F) + @test luF isa typeof(lu(F, check = false)) + @test size(luF.factors) == (0, 0) + + qrF = ArrayInterface.qr_instance(F) + @test qrF isa typeof(qr(F)) + @test size(qrF.factors) == (0, 0) + + qrpF = ArrayInterface.qr_instance(F, ColumnNorm()) + @test qrpF isa typeof(qr(F, ColumnNorm())) + @test size(qrpF.factors) == (0, 0) +end diff --git a/test/runtests.jl b/test/runtests.jl index c312622a..0b563c62 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -17,6 +17,7 @@ end @time @safetestset "StaticArrays" begin include("staticarrays.jl") end @time @safetestset "ChainRules" begin include("chainrules.jl") end @time @safetestset "FillArrays" begin include("fillarrays.jl") end + @time @safetestset "FixedSizeArrays" begin include("fixedsizearrays.jl") end end if GROUP == "GPU"