ztyh
ztyh

Reputation: 421

About behaviour of / by vector in Julia

3/[2;2] gives

1×2 LinearAlgebra.Transpose{Float64,Array{Float64,1}}:
 0.75  0.75

while 3 ./[2;2] gives

2-element Array{Float64,1}:
 1.5
 1.5

The second one is easy to comprehend. It broadcasts 3 and performs element wise division. But what is the reasoning behind having the first operation behave as it did? I assume it took the sum of the vector, which was 2x1, performed division of 3 by 4 and broadcast it to a 1x2 transposed vector. I can accept taking the sum of the vector to perform division, but why the transpose? Or why not just return a scalar?

Upvotes: 4

Views: 578

Answers (2)

hckr
hckr

Reputation: 5583

It simply gives the right hand side operand's pseudo-inverse.

julia> ?/
...  
Right division operator: multiplication of x by the inverse of y on the right.

Although it seems surprising at first sight, it is actually the natural behavior. A rowvector*columnvector gives a scalar and hence a scalar divided by a column vector should give a row vector, which is the case. Note that RowVector has been removed in 1.0 and what you get is actually a row vector represented with Transpose.

You can write @less 1 / [2;2] to see what actually happens.

Also take a look at this GitHub issue to understand the behaviour a bit more and this discourse topic for some use cases.

Upvotes: 5

carstenbauer
carstenbauer

Reputation: 10157

It seems it is calculating the pseudoinverse of the vector and then multiplying by 3.

Using @which 3/[2;2] and so on to see what actually happens, I found that it is eventually calling the following method in stdlib/LinearAlgebra/generic.jl:

function _vectorpinv(dualfn::Tf, v::AbstractVector{Tv}, tol) where {Tv,Tf}
    res = dualfn(similar(v, typeof(zero(Tv) / (abs2(one(Tv)) + abs2(one(Tv))))))
    den = sum(abs2, v)
    # as tol is the threshold relative to the maximum singular value, for a vector with
    # single singular value σ=√den, σ ≦ tol*σ is equivalent to den=0 ∨ tol≥1
    if iszero(den) || tol >= one(tol)
        fill!(res, zero(eltype(res)))
    else
        res .= dualfn(v) ./ den
    end
    return res
end

which in the given case effectively becomes transpose([2;2])/sum(abs2, [2;2]) which is the pseudoinverse.

However, this is a bit above my head. So someone more qualified might prove me wrong.

Upvotes: 2

Related Questions