diff --git a/benchmark/TensorAlgebraBenchmarks/TensorAlgebraBenchmarks.jl b/benchmark/TensorAlgebraBenchmarks/TensorAlgebraBenchmarks.jl index d7974b2..9334a52 100644 --- a/benchmark/TensorAlgebraBenchmarks/TensorAlgebraBenchmarks.jl +++ b/benchmark/TensorAlgebraBenchmarks/TensorAlgebraBenchmarks.jl @@ -49,8 +49,8 @@ H = TensorValue(1.:81...) SUITE["Tensor algebra"]["δδ_μ_2d"] = @benchmarkable δᵢₖδⱼₗ2D + δᵢₗδⱼₖ2D SUITE["Tensor algebra"]["δδ_λ_2d"] = @benchmarkable 1.0 * δᵢⱼδₖₗ2D -SUITE["Tensor algebra"]["Cofactor"] = @benchmarkable cof(A) -SUITE["Tensor algebra"]["Det(A)Inv(A')"] = @benchmarkable det(A)*inv(A') -SUITE["Tensor algebra"]["×ᵢ⁴"] = @benchmarkable ×ᵢ⁴(A) -SUITE["Tensor algebra"]["IIsym"] = @benchmarkable IIsym(A) -SUITE["Tensor algebra"]["push_forward_C_to_F"] = @benchmarkable push_forward_C_to_F(F,H) +SUITE["Tensor algebra"]["Cofactor"] = @benchmarkable cof($A) +SUITE["Tensor algebra"]["Det(A)Inv(A')"] = @benchmarkable det($A)*inv($A') +SUITE["Tensor algebra"]["×ᵢ⁴"] = @benchmarkable ×ᵢ⁴($A) +SUITE["Tensor algebra"]["IIsym"] = @benchmarkable IIsym($A) +SUITE["Tensor algebra"]["push_forward_C_to_F"] = @benchmarkable push_forward_C_to_F($F,$H) diff --git a/src/TensorAlgebra/Operations.jl b/src/TensorAlgebra/Operations.jl index 24a974b..0f36f22 100644 --- a/src/TensorAlgebra/Operations.jl +++ b/src/TensorAlgebra/Operations.jl @@ -10,12 +10,26 @@ function (*)(Ten1::TensorValue, Ten2::TensorValue) end -@inline @generated function (+)(A::TensorValue{D,D}, B::TensorValue{D,D}) where {D} - str = "" - for i in 1:D*D - str *= "A.data[$i] + B.data[$i], " - end - Meta.parse("TensorValue{D,D}($str)") +# The element type is explicit so that empty tensors (e.g. `TensorValue{0,3}`, +# built by Gridap for vertex grids) are also supported. +@inline @generated function (+)(A::TensorValue{D1,D2}, B::TensorValue{D1,D2}) where {D1,D2} + T = promote_type(eltype(A), eltype(B)) + data = [:(A.data[$i] + B.data[$i]) for i in 1:D1*D2] + :(TensorValue{D1,D2,$T}($(Expr(:tuple, data...)))) +end + + +@inline @generated function (-)(A::TensorValue{D1,D2}, B::TensorValue{D1,D2}) where {D1,D2} + T = promote_type(eltype(A), eltype(B)) + data = [:(A.data[$i] - B.data[$i]) for i in 1:D1*D2] + :(TensorValue{D1,D2,$T}($(Expr(:tuple, data...)))) +end + + +@inline @generated function (-)(A::TensorValue{D1,D2}) where {D1,D2} + T = eltype(A) + data = [:(-A.data[$i]) for i in 1:D1*D2] + :(TensorValue{D1,D2,$T}($(Expr(:tuple, data...)))) end diff --git a/src/TensorAlgebra/TensorAlgebra.jl b/src/TensorAlgebra/TensorAlgebra.jl index dfc7839..76abf9a 100644 --- a/src/TensorAlgebra/TensorAlgebra.jl +++ b/src/TensorAlgebra/TensorAlgebra.jl @@ -6,9 +6,11 @@ using StaticArrays using LinearAlgebra import Base: * import Base: + +import Base: - export (*) export (+) +export (-) export (⊗₁₂³) export (⊗₁₃²) export (⊗₁²³) diff --git a/test/TestTensorAlgebra/TensorAlgebraTests.jl b/test/TestTensorAlgebra/TensorAlgebraTests.jl index 8b34bad..d99e96d 100644 --- a/test/TestTensorAlgebra/TensorAlgebraTests.jl +++ b/test/TestTensorAlgebra/TensorAlgebraTests.jl @@ -107,6 +107,15 @@ end B = TensorValue(4.1, 5.2, 6.3, 7.4, 8.5, 9.6, 1.7, 2.8, 3.9) @test A + B == TensorValue(5.1, 7.2, 9.3, 11.4, 13.5, 15.6, 8.7, 10.8, 12.9) @test norm(A + B) ≈ 32.842807431765024 + @test B - A ≈ TensorValue(3.1, 3.2, 3.3, 3.4, 3.5, 3.6, -5.3, -5.2, -5.1) + @test -A == TensorValue(-1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0, -8.0, -9.0) + C = TensorValue{2,3}(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) + @test C + C == TensorValue{2,3}(2.0, 4.0, 6.0, 8.0, 10.0, 12.0) + @test TensorValue{2,2}(1, 2, 3, 4) + TensorValue{2,2}(0.5, 0.5, 0.5, 0.5) isa TensorValue{2,2,Float64} + E = TensorValue{0,3,Float64}(()) # empty tensor, built by Gridap for vertex grids + @test E + E == E + @test E - E == E + @test -E == E end