diff --git a/NEWS.md b/NEWS.md index c2e60b4bc0745..d70fcae04fb64 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,6 +14,11 @@ Language changes * New builtins `getglobal(::Module, ::Symbol[, order])` and `setglobal!(::Module, ::Symbol, x[, order])` for reading from and writing to globals. `getglobal` should now be preferred for accessing globals over `getfield`. ([#44137]) +* A few basic operators have been generalized to more naturally support vector space structures: + `+(x) = x`, unary minus falls back to scalar multiplication with -1, `-(x) = Int8(-1)*x`, + binary minus falls back to addition `-(x, y) = x + (-y)`, and, at the most generic level, + left- and right-division fall back to multiplication with the inverse from left and right, + respectively, as stated in the docstring. ([#44564]) Compiler/Runtime improvements ----------------------------- diff --git a/base/operators.jl b/base/operators.jl index 92c016d00bf03..43cbbb55d8266 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -512,8 +512,10 @@ julia> identity("Well, what did you expect?") """ identity(@nospecialize x) = x -+(x::Number) = x -*(x::Number) = x ++(x) = x +-(x) = Int8(-1)*x +-(x, y) = x + (-y) +*(x) = x (&)(x::Integer) = x (|)(x::Integer) = x xor(x::Integer) = x @@ -613,7 +615,9 @@ julia> inv(A) * x -7.0 ``` """ -\(x,y) = adjoint(adjoint(y)/adjoint(x)) +\(x, y) = inv(x) * y + +/(x, y) = x * inv(y) # Core <<, >>, and >>> take either Int or UInt as second arg. Signed shift # counts can shift in either direction, and are translated here to unsigned diff --git a/stdlib/Dates/docs/src/index.md b/stdlib/Dates/docs/src/index.md index 4975f175bbf16..4a7456b72a801 100644 --- a/stdlib/Dates/docs/src/index.md +++ b/stdlib/Dates/docs/src/index.md @@ -206,7 +206,8 @@ ERROR: MethodError: no method matching *(::Date, ::Date) [...] julia> dt / dt2 -ERROR: MethodError: no method matching /(::Date, ::Date) +ERROR: MethodError: no method matching inv(::Date) +[...] julia> dt - dt2 4411 days diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index b6a4548833eac..8d6e7cca53f21 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -318,6 +318,8 @@ pinv(v::TransposeAbsVec, tol::Real = 0) = pinv(conj(v.parent)).parent ## left-division \ \(u::AdjOrTransAbsVec, v::AdjOrTransAbsVec) = pinv(u) * v +\(u::AdjointAbsVec, y::Number) = adjoint(conj(y) / u.parent) +\(u::TransposeAbsVec, y::Number) = transpose(y / u.parent) ## right-division / diff --git a/stdlib/LinearAlgebra/test/bidiag.jl b/stdlib/LinearAlgebra/test/bidiag.jl index 59bc1a5cb13ec..adaae98250ee4 100644 --- a/stdlib/LinearAlgebra/test/bidiag.jl +++ b/stdlib/LinearAlgebra/test/bidiag.jl @@ -315,7 +315,7 @@ Random.seed!(1) typediv=T.uplo == 'U' ? UpperTriangular : Matrix, typediv2=T.uplo == 'U' ? UpperTriangular : Matrix) TM = Matrix(T) - @test (T*x)::typemul ≈ TM*x #broken=eltype(x) <: Furlong + @test (T*x)::typemul ≈ TM*x #broken=eltype(x) <: Furlong @test (x*T)::typemul ≈ x*TM #broken=eltype(x) <: Furlong @test (x\T)::typediv ≈ x\TM #broken=eltype(T) <: Furlong @test (T/x)::typediv ≈ TM/x #broken=eltype(T) <: Furlong @@ -325,20 +325,24 @@ Random.seed!(1) end return nothing end - A = randn(n,n) - d = randn(n) - dl = randn(n-1) - t = T - for t in (T, #=Furlong.(T)=#), (A, d, dl) in ((A, d, dl), #=(Furlong.(A), Furlong.(d), Furlong.(dl))=#) + if relty <: Integer + A = convert(Matrix{elty}, rand(1:10, n, n)) + if (elty <: Complex) + A += im*convert(Matrix{elty}, rand(1:10, n, n)) + end + else + A = rand(elty, n, n) + end + for t in (T, #=Furlong.(T)=#), (A, dv, ev) in ((A, dv, ev), #=(Furlong.(A), Furlong.(dv), Furlong.(ev))=#) _bidiagdivmultest(t, 5, Bidiagonal, Bidiagonal) _bidiagdivmultest(t, 5I, Bidiagonal, Bidiagonal, t.uplo == 'U' ? UpperTriangular : LowerTriangular) - _bidiagdivmultest(t, Diagonal(d), Bidiagonal, Bidiagonal, t.uplo == 'U' ? UpperTriangular : LowerTriangular) + _bidiagdivmultest(t, Diagonal(dv), Bidiagonal, Bidiagonal, t.uplo == 'U' ? UpperTriangular : LowerTriangular) _bidiagdivmultest(t, UpperTriangular(A)) _bidiagdivmultest(t, UnitUpperTriangular(A)) _bidiagdivmultest(t, LowerTriangular(A), t.uplo == 'L' ? LowerTriangular : Matrix, t.uplo == 'L' ? LowerTriangular : Matrix, t.uplo == 'L' ? LowerTriangular : Matrix) _bidiagdivmultest(t, UnitLowerTriangular(A), t.uplo == 'L' ? LowerTriangular : Matrix, t.uplo == 'L' ? LowerTriangular : Matrix, t.uplo == 'L' ? LowerTriangular : Matrix) - _bidiagdivmultest(t, Bidiagonal(d, dl, :U), Matrix, Matrix, Matrix) - _bidiagdivmultest(t, Bidiagonal(d, dl, :L), Matrix, Matrix, Matrix) + _bidiagdivmultest(t, Bidiagonal(dv, ev, :U), Matrix, Matrix, Matrix) + _bidiagdivmultest(t, Bidiagonal(dv, ev, :L), Matrix, Matrix, Matrix) end end end diff --git a/stdlib/LinearAlgebra/test/dense.jl b/stdlib/LinearAlgebra/test/dense.jl index 9bdc732d1f67a..a7b31dcc50611 100644 --- a/stdlib/LinearAlgebra/test/dense.jl +++ b/stdlib/LinearAlgebra/test/dense.jl @@ -25,7 +25,7 @@ Random.seed!(1234323) ainv = inv(a) @test cond(a, 1) == opnorm(a, 1) *opnorm(ainv, 1) @test cond(a, Inf) == opnorm(a, Inf)*opnorm(ainv, Inf) - @test cond(a[:, 1:5]) == (\)(extrema(svdvals(a[:, 1:5]))...) + @test cond(a[:, 1:5]) == (/)(reverse(extrema(svdvals(a[:, 1:5])))...) @test_throws ArgumentError cond(a,3) end end diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index 8bc84d93c6348..dd16842961561 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -791,8 +791,8 @@ end U = UpperTriangular(randn(elty, K, K)) L = LowerTriangular(randn(elty, K, K)) D = Diagonal(randn(elty, K)) - @test (U / D)::UpperTriangular{elty} == UpperTriangular(Matrix(U) / Matrix(D)) - @test (L / D)::LowerTriangular{elty} == LowerTriangular(Matrix(L) / Matrix(D)) + @test (U / D)::UpperTriangular{elty} ≈ UpperTriangular(Matrix(U) / Matrix(D)) rtol=2eps(real(elty)) + @test (L / D)::LowerTriangular{elty} ≈ LowerTriangular(Matrix(L) / Matrix(D)) rtol=2eps(real(elty)) @test (D \ U)::UpperTriangular{elty} == UpperTriangular(Matrix(D) \ Matrix(U)) @test (D \ L)::LowerTriangular{elty} == LowerTriangular(Matrix(D) \ Matrix(L)) end @@ -806,8 +806,8 @@ end D0 = Diagonal(zeros(elty, K)) @test (D \ S)::Tridiagonal{elty} == Tridiagonal(Matrix(D) \ Matrix(S)) @test (D \ T)::Tridiagonal{elty} == Tridiagonal(Matrix(D) \ Matrix(T)) - @test (S / D)::Tridiagonal{elty} == Tridiagonal(Matrix(S) / Matrix(D)) - @test (T / D)::Tridiagonal{elty} == Tridiagonal(Matrix(T) / Matrix(D)) + @test (S / D)::Tridiagonal{elty} ≈ Tridiagonal(Matrix(S) / Matrix(D)) rtol=2eps(real(elty)) + @test (T / D)::Tridiagonal{elty} ≈ Tridiagonal(Matrix(T) / Matrix(D)) rtol=2eps(real(elty)) @test_throws SingularException D0 \ S @test_throws SingularException D0 \ T @test_throws SingularException S / D0 @@ -851,8 +851,8 @@ end D = Diagonal(rand(1:20, K)) @test (D \ S)::Tridiagonal{Float64} == Tridiagonal(Matrix(D) \ Matrix(S)) @test (D \ T)::Tridiagonal{Float64} == Tridiagonal(Matrix(D) \ Matrix(T)) - @test (S / D)::Tridiagonal{Float64} == Tridiagonal(Matrix(S) / Matrix(D)) - @test (T / D)::Tridiagonal{Float64} == Tridiagonal(Matrix(T) / Matrix(D)) + @test (S / D)::Tridiagonal{Float64} ≈ Tridiagonal(Matrix(S) / Matrix(D)) rtol=2eps() + @test (T / D)::Tridiagonal{Float64} ≈ Tridiagonal(Matrix(T) / Matrix(D)) rtol=2eps() end @testset "eigenvalue sorting" begin @@ -960,7 +960,7 @@ end @testset "divisions functionality" for elty in (Int, Float64, ComplexF64) B = Diagonal(rand(elty,5,5)) x = rand(elty) - @test \(x, B) == /(B, x) + @test \(x, B) ≈ /(B, x) rtol=2eps() end @testset "promotion" begin diff --git a/stdlib/LinearAlgebra/test/generic.jl b/stdlib/LinearAlgebra/test/generic.jl index 77668cdb69b62..d490f0ea72b21 100644 --- a/stdlib/LinearAlgebra/test/generic.jl +++ b/stdlib/LinearAlgebra/test/generic.jl @@ -155,8 +155,8 @@ end @testset "Scaling with rdiv! and ldiv!" begin @test rdiv!(copy(a), 5.) == a/5 - @test ldiv!(5., copy(a)) == a/5 - @test ldiv!(zero(a), 5., copy(a)) == a/5 + @test ldiv!(5., copy(a)) == 5\a + @test ldiv!(zero(a), 5., copy(a)) == 5\a end @testset "Scaling with 3-argument mul!" begin @@ -441,17 +441,12 @@ Base.:-(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k - b.k) Base.:*(a::ModInt{n}, b::ModInt{n}) where {n} = ModInt{n}(a.k * b.k) Base.:-(a::ModInt{n}) where {n} = ModInt{n}(-a.k) Base.inv(a::ModInt{n}) where {n} = ModInt{n}(invmod(a.k, n)) -Base.:/(a::ModInt{n}, b::ModInt{n}) where {n} = a*inv(b) Base.zero(::Type{ModInt{n}}) where {n} = ModInt{n}(0) Base.zero(::ModInt{n}) where {n} = ModInt{n}(0) Base.one(::Type{ModInt{n}}) where {n} = ModInt{n}(1) Base.one(::ModInt{n}) where {n} = ModInt{n}(1) Base.conj(a::ModInt{n}) where {n} = a -Base.adjoint(a::ModInt{n}) where {n} = ModInt{n}(conj(a)) -Base.transpose(a::ModInt{n}) where {n} = a # see Issue 20978 -LinearAlgebra.Adjoint(a::ModInt{n}) where {n} = adjoint(a) -LinearAlgebra.Transpose(a::ModInt{n}) where {n} = transpose(a) @testset "Issue 22042" begin A = [ModInt{2}(1) ModInt{2}(0); ModInt{2}(1) ModInt{2}(1)] diff --git a/test/errorshow.jl b/test/errorshow.jl index 72a2ebb1e9cbe..31e217aefd7dc 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -398,8 +398,8 @@ let err_str @test occursin("MethodError: no method matching +(::$Int, ::Vector{Float64})", err_str) @test occursin("For element-wise addition, use broadcasting with dot syntax: scalar .+ array", err_str) err_str = @except_str rand(5) - 1//3 MethodError - @test occursin("MethodError: no method matching -(::Vector{Float64}, ::Rational{$Int})", err_str) - @test occursin("For element-wise subtraction, use broadcasting with dot syntax: array .- scalar", err_str) + @test occursin("MethodError: no method matching +(::Vector{Float64}, ::Rational{$Int})", err_str) + @test occursin("For element-wise addition, use broadcasting with dot syntax: array .+ scalar", err_str) end diff --git a/test/int.jl b/test/int.jl index d7b79fb6c1e0c..b019bf697647e 100644 --- a/test/int.jl +++ b/test/int.jl @@ -123,7 +123,7 @@ end @test mod(123, UInt8) === 0x7b primitive type MyBitsType <: Signed 8 end -@test_throws MethodError ~reinterpret(MyBitsType, 0x7b) +@test_throws ErrorException ~reinterpret(MyBitsType, 0x7b) @test signed(MyBitsType) === MyBitsType UItypes = Base.BitUnsigned_types