Multiplication broken upon upgrade to Julia 0.5.0


#1

Hello. I have a script that contains the following line:

A[k+1:n,k+1:n] -= A[k+1:n,k] * A[k,k+1:n] 

where k and n are integers and the values in the two-dimensional array are floats. Previously, in Julia 0.4.6, this was no problem and I achieved the results I desired with no errors. However, in 0.5.0, I get an error

ERROR: MethodError: no method matching *(::Array{Float64,1}, ::Array{Float64,1})

along with a lot of text referencing closest candidates. Has something fundamentally changed in Julia 0.5.0 that no longer allows this? How may this be rectified?

Please let me know if my entire script is needed to understand the issue more fully.

Thank you.


#2

Yes, this is https://github.com/JuliaLang/julia/pull/13612 (which is listed under “breaking changes” in the 0.5 NEWS).

In 0.5, you need to add an explicit transpose to get a row vector for the second term:

A[k+1:n,k+1:n] -= A[k+1:n,k] * A[k,k+1:n].'

In 0.6, you can do:

view(A,k+1:n,k+1:n) .-= view(A,k+1:n,k) .* view(A,k,k+1:n).'

and the whole operation occurs in-place, with a single fused loop, without allocating temporary matrices for the right-hand-side operations.


#3

Or in v0.5,

A[k+1:n,k+1:n] -= A[k+1:n,k] * A[k:k,k+1:n]

Indexing with range k:k preserves dimension as in v0.4


#4

Is the view on the left-hand side necessary? I thought slicing was only on the right?


#5

Yes, because it is the left-hand side of .-=. If you do A[...] .-= X, this is equivalent to A[...] .= A[...] .- X, in which case the slice A[...] on the right-hand side makes a copy.


#6
julia> VERSION
v"0.6.0-dev.2199"

julia> A = eye(Int,4);

julia> k,n=1,4; view(A,k+1:n,k+1:n) .-= view(A,k+1:n,k) .* view(A,k,k+1:n).'
ERROR: syntax: invalid assignment location "view(A,+(k,1):n,+(k,1):n)"

#7

It’s not completely clear in the docs whether you should be able to assign to a view: http://docs.julialang.org/en/stable/stdlib/arrays/#Base.view

You can assign like this: view(A, ...)[:,:] = ..., but that sort of ruins the rest of the idea.


#8

Yes, because it is the left-hand side of .-=. If you do A[…] .-= X, this is equivalent to A[…] .= A[…] .- X, in which case the slice A[…] on the right-hand side makes a copy.

Isn’t this kind of unfortunate? It seems unnatural to have to add view here.


#9

Yeah, I understand it after it’s explained, but it feels like a violation of the rule “indexing on the left is a view” which I thought was always true. I think this is a good reason to start pushing for “always a view again”, especially after views keep getting cheaper and cheaper.