# This file is a part of Julia. License is MIT: https://julialang.org/license ctranspose(a::AbstractArray) = error("ctranspose not defined for $(typeof(a)). Consider using `permutedims` for higher-dimensional arrays.") transpose(a::AbstractArray) = error("transpose not defined for $(typeof(a)). Consider using `permutedims` for higher-dimensional arrays.") ## Matrix transposition ## """ transpose!(dest,src) Transpose array `src` and store the result in the preallocated array `dest`, which should have a size corresponding to `(size(src,2),size(src,1))`. No in-place transposition is supported and unexpected results will happen if `src` and `dest` have overlapping memory regions. """ transpose!(B::AbstractMatrix, A::AbstractMatrix) = transpose_f!(transpose, B, A) """ ctranspose!(dest,src) Conjugate transpose array `src` and store the result in the preallocated array `dest`, which should have a size corresponding to `(size(src,2),size(src,1))`. No in-place transposition is supported and unexpected results will happen if `src` and `dest` have overlapping memory regions. """ ctranspose!(B::AbstractMatrix, A::AbstractMatrix) = transpose_f!(ctranspose, B, A) function transpose!(B::AbstractVector, A::AbstractMatrix) indices(B,1) == indices(A,2) && indices(A,1) == 1:1 || throw(DimensionMismatch("transpose")) copy!(B, A) end function transpose!(B::AbstractMatrix, A::AbstractVector) indices(B,2) == indices(A,1) && indices(B,1) == 1:1 || throw(DimensionMismatch("transpose")) copy!(B, A) end function ctranspose!(B::AbstractVector, A::AbstractMatrix) indices(B,1) == indices(A,2) && indices(A,1) == 1:1 || throw(DimensionMismatch("transpose")) ccopy!(B, A) end function ctranspose!(B::AbstractMatrix, A::AbstractVector) indices(B,2) == indices(A,1) && indices(B,1) == 1:1 || throw(DimensionMismatch("transpose")) ccopy!(B, A) end const transposebaselength=64 function transpose_f!(f, B::AbstractMatrix, A::AbstractMatrix) inds = indices(A) indices(B,1) == inds[2] && indices(B,2) == inds[1] || throw(DimensionMismatch(string(f))) m, n = length(inds[1]), length(inds[2]) if m*n<=4*transposebaselength @inbounds begin for j = inds[2] for i = inds[1] B[j,i] = f(A[i,j]) end end end else transposeblock!(f,B,A,m,n,first(inds[1])-1,first(inds[2])-1) end return B end function transposeblock!(f, B::AbstractMatrix, A::AbstractMatrix, m::Int, n::Int, offseti::Int, offsetj::Int) if m*n<=transposebaselength @inbounds begin for j = offsetj+(1:n) for i = offseti+(1:m) B[j,i] = f(A[i,j]) end end end elseif m>n newm=m>>1 transposeblock!(f,B,A,newm,n,offseti,offsetj) transposeblock!(f,B,A,m-newm,n,offseti+newm,offsetj) else newn=n>>1 transposeblock!(f,B,A,m,newn,offseti,offsetj) transposeblock!(f,B,A,m,n-newn,offseti,offsetj+newn) end return B end function ccopy!(B, A) RB, RA = eachindex(B), eachindex(A) if RB == RA for i = RB B[i] = ctranspose(A[i]) end else for (i,j) = zip(RB, RA) B[i] = ctranspose(A[j]) end end end """ transpose(A::AbstractMatrix) The transposition operator (`.'`). # Example ```jldoctest julia> A = [1 2 3; 4 5 6; 7 8 9] 3×3 Array{Int64,2}: 1 2 3 4 5 6 7 8 9 julia> transpose(A) 3×3 Array{Int64,2}: 1 4 7 2 5 8 3 6 9 ``` """ function transpose(A::AbstractMatrix) ind1, ind2 = indices(A) B = similar(A, (ind2, ind1)) transpose!(B, A) end function ctranspose(A::AbstractMatrix) ind1, ind2 = indices(A) B = similar(A, (ind2, ind1)) ctranspose!(B, A) end @inline ctranspose(A::AbstractVector{<:Real}) = transpose(A) @inline ctranspose(A::AbstractMatrix{<:Real}) = transpose(A) function copy_transpose!(B::AbstractVecOrMat, ir_dest::Range{Int}, jr_dest::Range{Int}, A::AbstractVecOrMat, ir_src::Range{Int}, jr_src::Range{Int}) if length(ir_dest) != length(jr_src) throw(ArgumentError(string("source and destination must have same size (got ", length(jr_src)," and ",length(ir_dest),")"))) end if length(jr_dest) != length(ir_src) throw(ArgumentError(string("source and destination must have same size (got ", length(ir_src)," and ",length(jr_dest),")"))) end @boundscheck checkbounds(B, ir_dest, jr_dest) @boundscheck checkbounds(A, ir_src, jr_src) idest = first(ir_dest) for jsrc in jr_src jdest = first(jr_dest) for isrc in ir_src B[idest,jdest] = A[isrc,jsrc] jdest += step(jr_dest) end idest += step(ir_dest) end return B end