Skip to content

Commit 79ac5f1

Browse files
authored
Merge pull request #262 from TsurHerman/pull-request/fb369658
More consistent treatment of unsigned types in det and inv
2 parents d4a4d4f + 77151c0 commit 79ac5f1

File tree

3 files changed

+30
-50
lines changed

3 files changed

+30
-50
lines changed

src/det.jl

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,26 @@
1-
@inline det(A::StaticMatrix) = _det(Size(A), A)
2-
@inline logdet(A::StaticMatrix) = _logdet(Size(A), A)
1+
@inline function det(A::StaticMatrix)
2+
T = eltype(A)
3+
S = typeof((one(T)*zero(T) + zero(T))/one(T))
4+
_det(Size(A),A,S)
5+
end
36

4-
@inline _det(::Size{(1,1)}, A::StaticMatrix) = @inbounds return A[1]
7+
@inline logdet(A::StaticMatrix) = log(det(A))
58

6-
@inline function _det(::Size{(2,2)}, A::StaticMatrix)
7-
@inbounds return A[1]*A[4] - A[3]*A[2]
8-
end
9+
@inline _det(::Size{(1,1)}, A::StaticMatrix,S::Type) = @inbounds return convert(S,A[1])
910

10-
@inline function _det(::Size{(2,2)}, A::StaticMatrix{<:Any, <:Any, <:Unsigned})
11-
@inbounds return Signed(A[1]*A[4]) - Signed(A[3]*A[2])
11+
@inline function _det(::Size{(2,2)}, A::StaticMatrix, S::Type)
12+
A = similar_type(A,S)(A)
13+
@inbounds return A[1]*A[4] - A[3]*A[2]
1214
end
1315

14-
@inline function _det(::Size{(3,3)}, A::StaticMatrix)
16+
@inline function _det(::Size{(3,3)}, A::StaticMatrix, S::Type)
17+
A = similar_type(A,S)(A)
1518
@inbounds x0 = SVector(A[1], A[2], A[3])
1619
@inbounds x1 = SVector(A[4], A[5], A[6])
1720
@inbounds x2 = SVector(A[7], A[8], A[9])
1821
return vecdot(x0, cross(x1, x2))
1922
end
2023

21-
@inline function _det(::Size{(3,3)}, A::StaticMatrix{<:Any, <:Any, <:Unsigned})
22-
@inbounds x0 = SVector(Signed(A[1]), Signed(A[2]), Signed(A[3]))
23-
@inbounds x1 = SVector(Signed(A[4]), Signed(A[5]), Signed(A[6]))
24-
@inbounds x2 = SVector(Signed(A[7]), Signed(A[8]), Signed(A[9]))
25-
return vecdot(x0, cross(x1, x2))
24+
@inline function _det(::Size, A::StaticMatrix,::Type)
25+
return det(Matrix(A))
2626
end
27-
28-
@inline _logdet(S::Union{Size{(1,1)},Size{(2,2)},Size{(3,3)}}, A::StaticMatrix) = log(_det(S, A))
29-
30-
for (symb, f) in [(:_det, :det), (:_logdet, :logdet)]
31-
eval(quote
32-
@generated function $symb{S}(::Size{S}, A::StaticMatrix)
33-
if S[1] != S[2]
34-
throw(DimensionMismatch("matrix is not square"))
35-
end
36-
return quote # Implementation from Base
37-
@_inline_meta
38-
T = eltype(A)
39-
T2 = typeof((one(T)*zero(T) + zero(T))/one(T))
40-
if istriu(A) || istril(A)
41-
return convert(T2, $($f)(UpperTriangular(A))) # Is this a Julia bug that a convert is not type stable??
42-
end
43-
AA = convert(Array{T2}, A)
44-
return $($f)(lufact(AA))
45-
end
46-
end
47-
end)
48-
end
49-

src/inv.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ end
1616
S = typeof((one(T)*zero(T) + zero(T))/one(T))
1717
newtype = similar_type(A, S)
1818

19-
@inbounds x0 = SVector(A[1], A[2], A[3])
20-
@inbounds x1 = SVector(A[4], A[5], A[6])
21-
@inbounds x2 = SVector(A[7], A[8], A[9])
19+
@inbounds x0 = SVector{3,S}(A[1], A[2], A[3])
20+
@inbounds x1 = SVector{3,S}(A[4], A[5], A[6])
21+
@inbounds x2 = SVector{3,S}(A[7], A[8], A[9])
2222

2323
y0 = cross(x1,x2)
2424
d = vecdot(x0, y0)

test/det.jl

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
@testset "Determinant" begin
2-
@test det(@SMatrix [1]) === 1
3-
@test logdet(@SMatrix [1]) === 0.0
4-
@test det(@SMatrix [0 1; 1 0]) === -1
2+
@test det(@SMatrix [1]) == 1
3+
@test logdet(@SMatrix [1]) == 0.0
4+
@test det(@SMatrix [0 1; 1 0]) == -1
55
@test logdet(@SMatrix Complex{Float64}[0 1; 1 0]) == log(det(@SMatrix Complex{Float64}[0 1; 1 0]))
6-
7-
@test det(@SMatrix [0 1 0; 1 0 0; 0 0 1]) === -1
6+
7+
@test det(@SMatrix [0 1 0; 1 0 0; 0 0 1]) == -1
88
m = randn(Float64, 4,4)
99
@test det(SMatrix{4,4}(m)) det(m)
1010
#triu/tril
11-
@test det(@SMatrix [1 2; 0 3]) === 3
12-
@test det(@SMatrix [1 2 3 4; 0 5 6 7; 0 0 8 9; 0 0 0 10]) === 400.0
11+
@test det(@SMatrix [1 2; 0 3]) == 3
12+
@test det(@SMatrix [1 2 3 4; 0 5 6 7; 0 0 8 9; 0 0 0 10]) == 400.0
1313
@test logdet(@SMatrix [1 2 3 4; 0 5 6 7; 0 0 8 9; 0 0 0 10]) log(400.0)
1414
@test @inferred(det(ones(SMatrix{10,10,Complex{Float64}}))) == 0
1515

16-
# Unsigned specializations
17-
@test det(@SMatrix [0x00 0x01; 0x01 0x00])::Int8 == -1
18-
@test det(@SMatrix [0x00 0x01 0x00; 0x01 0x00 0x00; 0x00 0x00 0x01])::Int8 == -1
16+
# Unsigned specializations , compare to Base
17+
M = @SMatrix [1 2 3 4; 200 5 6 7; 0 0 8 9; 0 0 0 10]
18+
for sz in (2,3,4), typ in (UInt8,UInt16,UInt32,UInt64)
19+
Mtag = SMatrix{sz,sz,typ}(M[1:sz,1:sz])
20+
@test det(Mtag) == det(Array(Mtag))
21+
end
1922

2023
@test_throws DimensionMismatch det(@SMatrix [0; 1])
2124
end

0 commit comments

Comments
 (0)