/
githubmirror
/
julia
Обзор
Документация
Войти
/
githubmirror
/
julia
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
base/arraymath.jl
317 строк
7 KB
johroj
Fix unary plus (#61052)
20 фев 2026, 16:53
Не верифицирован
20 фев 2026, 16:53
9aff288
Код
Авторство
О чём код?
# This file is a part of Julia. License is MIT: https://julialang.org/license ## Binary arithmetic operators ## function _broadcast_preserving_zero_d(f, A, B) broadcast_preserving_zero_d(f, A, B) end # Using map over broadcast enables vectorization for wide matrices with few rows. # This is because we use linear indexing in `map` as opposed to Cartesian indexing in broadcasting. # https://github.com/JuliaLang/julia/issues/47873#issuecomment-1352472461 function _broadcast_preserving_zero_d(f, A::Array{<:Any,N}, B::Array{<:Any,N}, Cs::Array{<:Any,N}...) where {N} map(f, A, B, Cs...) end function _broadcast_preserving_zero_d(f, A::Array, B::Array, Cs::Array...) # we already know that the shapes are compatible. # We just need to select the size corresponding to the highest ndims # and reshape all the arrays to that size arrays = (A, B, Cs...) sz = mapreduce(size, (x,y) -> length(x) > length(y) ? x : y, arrays) # Skip reshaping where possible to avoid the overhead arrays_sameshape = map(x -> length(sz) == ndims(x) ? x : reshape(x, sz), arrays) map(f, arrays_sameshape...) end function _broadcast_preserving_zero_d(f, A::Array, B::Number) map(Fix2(f, B), A) end function _broadcast_preserving_zero_d(f, A::Number, B::Array) map(Fix1(f, A), B) end for f in (:+, :-) @eval function ($f)(A::AbstractArray, B::AbstractArray) promote_shape(A, B) # check size compatibility _broadcast_preserving_zero_d($f, A, B) end end +(A::Array) = map(+, A) function +(A::Array, B::Array, Cs::Array...) promote_shape(A, B) for C in Cs promote_shape(A, C) # check size compatibility end _broadcast_preserving_zero_d(+, A, B, Cs...) end for f in (:/, :\, :*) if f !== :/ @eval ($f)(A::Number, B::AbstractArray) = _broadcast_preserving_zero_d($f, A, B) end if f !== :\ @eval ($f)(A::AbstractArray, B::Number) = _broadcast_preserving_zero_d($f, A, B) end end ## data movement ## """ reverse(A; dims=:) Reverse `A` along dimension `dims`, which can be an integer (a single dimension), a tuple of integers (a tuple of dimensions) or `:` (reverse along all the dimensions, the default). See also [`reverse!`](@ref) for in-place reversal. # Examples ```jldoctest julia> b = Int64[1 2; 3 4] 2×2 Matrix{Int64}: 1 2 3 4 julia> reverse(b, dims=2) 2×2 Matrix{Int64}: 2 1 4 3 julia> reverse(b) 2×2 Matrix{Int64}: 4 3 2 1 ``` !!! compat "Julia 1.6" Prior to Julia 1.6, only single-integer `dims` are supported in `reverse`. """ reverse(A::AbstractArray; dims::D=:) where {D} = _reverse(A, dims) _reverse(A, dims::D) where {D} = reverse!(copymutable(A); dims) """ reverse!(A; dims=:) Like [`reverse`](@ref), but operates in-place in `A`. !!! compat "Julia 1.6" Multidimensional `reverse!` requires Julia 1.6. """ reverse!(A::AbstractArray; dims::D=:) where {D} = _reverse!(A, dims) _reverse!(A::AbstractArray{<:Any,N}, ::Colon) where {N} = _reverse!(A, ntuple(identity, Val{N}())) _reverse!(A, dim::Integer) = _reverse!(A, (Int(dim),)) _reverse!(A, dims::NTuple{M,Integer}) where {M} = _reverse!(A, Int.(dims)) function _reverse!(A::AbstractArray{<:Any,N}, dims::NTuple{M,Int}) where {N,M} dims === () && return A # nothing to reverse dimrev = ntuple(k -> k in dims, Val{N}()) # boolean tuple indicating reversed dims if N < M || M != sum(dimrev) throw(ArgumentError("invalid dimensions $dims in reverse!")) end # swapping loop only needs to traverse ≈half of the array halfsz = ntuple(k -> k == dims[1] ? size(A,k) ÷ 2 : size(A,k), Val{N}()) last1 = ntuple(k -> lastindex(A,k)+firstindex(A,k), Val{N}()) # offset for reversed index for i in CartesianIndices(ntuple(k -> firstindex(A,k):firstindex(A,k)-1+@inbounds(halfsz[k]), Val{N}())) iₜ = Tuple(i) iᵣ = CartesianIndex(ifelse.(dimrev, last1 .- iₜ, iₜ)) @inbounds A[iᵣ], A[i] = A[i], A[iᵣ] end if M > 1 && isodd(size(A, dims[1])) # middle slice for odd dimensions must be recursively flipped mid = firstindex(A, dims[1]) + (size(A, dims[1]) ÷ 2) midslice = CartesianIndices(ntuple(k -> k == dims[1] ? (mid:mid) : (firstindex(A,k):lastindex(A,k)), Val{N}())) _reverse!(view(A, midslice), dims[2:end]) end return A end # fix ambiguity with array.jl: _reverse!(A::AbstractVector, dim::Tuple{Int}) = _reverse!(A, first(dim)) """ rotl90(A) Rotate matrix `A` left 90 degrees. # Examples ```jldoctest julia> a = [1 2; 3 4] 2×2 Matrix{Int64}: 1 2 3 4 julia> rotl90(a) 2×2 Matrix{Int64}: 2 4 1 3 ``` """ function rotl90(A::AbstractMatrix) ind1, ind2 = axes(A) B = similar(A, (ind2,ind1)) n = first(ind2)+last(ind2) for i=axes(A,1), j=ind2 B[n-j,i] = A[i,j] end return B end """ rotr90(A) Rotate matrix `A` right 90 degrees. # Examples ```jldoctest julia> a = [1 2; 3 4] 2×2 Matrix{Int64}: 1 2 3 4 julia> rotr90(a) 2×2 Matrix{Int64}: 3 1 4 2 ``` """ function rotr90(A::AbstractMatrix) ind1, ind2 = axes(A) B = similar(A, (ind2,ind1)) m = first(ind1)+last(ind1) for i=ind1, j=axes(A,2) B[j,m-i] = A[i,j] end return B end """ rot180(A) Rotate matrix `A` 180 degrees. # Examples ```jldoctest julia> a = [1 2; 3 4] 2×2 Matrix{Int64}: 1 2 3 4 julia> rot180(a) 2×2 Matrix{Int64}: 4 3 2 1 ``` """ function rot180(A::AbstractMatrix) B = similar(A) ind1, ind2 = axes(A,1), axes(A,2) m, n = first(ind1)+last(ind1), first(ind2)+last(ind2) for j=ind2, i=ind1 B[m-i,n-j] = A[i,j] end return B end """ rotl90(A, k) Left-rotate matrix `A` 90 degrees counterclockwise an integer `k` number of times. If `k` is a multiple of four (including zero), this is equivalent to a `copy`. # Examples ```jldoctest julia> a = [1 2; 3 4] 2×2 Matrix{Int64}: 1 2 3 4 julia> rotl90(a,1) 2×2 Matrix{Int64}: 2 4 1 3 julia> rotl90(a,2) 2×2 Matrix{Int64}: 4 3 2 1 julia> rotl90(a,3) 2×2 Matrix{Int64}: 3 1 4 2 julia> rotl90(a,4) 2×2 Matrix{Int64}: 1 2 3 4 ``` """ function rotl90(A::AbstractMatrix, k::Integer) k = mod(k, 4) k == 1 ? rotl90(A) : k == 2 ? rot180(A) : k == 3 ? rotr90(A) : copy(A) end """ rotr90(A, k) Right-rotate matrix `A` 90 degrees clockwise an integer `k` number of times. If `k` is a multiple of four (including zero), this is equivalent to a `copy`. # Examples ```jldoctest julia> a = [1 2; 3 4] 2×2 Matrix{Int64}: 1 2 3 4 julia> rotr90(a,1) 2×2 Matrix{Int64}: 3 1 4 2 julia> rotr90(a,2) 2×2 Matrix{Int64}: 4 3 2 1 julia> rotr90(a,3) 2×2 Matrix{Int64}: 2 4 1 3 julia> rotr90(a,4) 2×2 Matrix{Int64}: 1 2 3 4 ``` """ rotr90(A::AbstractMatrix, k::Integer) = rotl90(A,-k) """ rot180(A, k) Rotate matrix `A` 180 degrees an integer `k` number of times. If `k` is even, this is equivalent to a `copy`. # Examples ```jldoctest julia> a = [1 2; 3 4] 2×2 Matrix{Int64}: 1 2 3 4 julia> rot180(a,1) 2×2 Matrix{Int64}: 4 3 2 1 julia> rot180(a,2) 2×2 Matrix{Int64}: 1 2 3 4 ``` """ rot180(A::AbstractMatrix, k::Integer) = mod(k, 2) == 1 ? rot180(A) : copy(A)