diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index aa38419614b737..799fa53f0b00f2 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -1539,9 +1539,9 @@ julia> det(M) 2.0 ``` """ -function det(A::AbstractMatrix{T}) where T +function det(A::AbstractMatrix{T}) where {T} if istriu(A) || istril(A) - S = typeof((one(T)*zero(T) + zero(T))/one(T)) + S = promote_type(T, typeof((one(T)*zero(T) + zero(T))/one(T))) return convert(S, det(UpperTriangular(A))) end return det(lu(A; check = false)) diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index cd52d30da6c8d1..a9d6441cc29b4f 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -76,6 +76,35 @@ n = 5 # should be odd @test logabsdet(x)[1] ≈ logabsdet(X)[1] @test logabsdet(x)[2] ≈ logabsdet(X)[2] end + + @testset "det with nonstandard Number type" begin + struct MyDual{T<:Real} <: Real + val::T + eps::T + end + Base.:+(x::MyDual, y::MyDual) = MyDual(x.val + y.val, x.eps + y.eps) + Base.:*(x::MyDual, y::MyDual) = MyDual(x.val * y.val, x.eps * y.val + y.eps * x.val) + Base.:/(x::MyDual, y::MyDual) = x.val / y.val + Base.:(==)(x::MyDual, y::MyDual) = x.val == y.val && x.eps == y.eps + Base.zero(::MyDual{T}) where {T} = MyDual(zero(T), zero(T)) + Base.zero(::Type{MyDual{T}}) where {T} = MyDual(zero(T), zero(T)) + Base.one(::MyDual{T}) where {T} = MyDual(one(T), zero(T)) + Base.one(::Type{MyDual{T}}) where {T} = MyDual(one(T), zero(T)) + # the following line is required for BigFloat, IDK why it doesn't work via + # promote_rule like for all other types + Base.promote_type(::Type{MyDual{BigFloat}}, ::Type{BigFloat}) = MyDual{BigFloat} + Base.promote_rule(::Type{MyDual{T}}, ::Type{S}) where {T,S<:Real} = + MyDual{promote_type(T, S)} + Base.promote_rule(::Type{MyDual{T}}, ::Type{MyDual{S}}) where {T,S} = + MyDual{promote_type(T, S)} + Base.convert(::Type{MyDual{T}}, x::MyDual) where {T} = + MyDual(convert(T, x.val), convert(T, x.eps)) + if elty <: Real + @show elty + @show istriu(triu(MyDual.(A, zero(A)))) + @test det(triu(MyDual.(A, zero(A)))) isa MyDual + end + end end @testset "diag" begin