# Adding vectors of different lengths

**URL:** <https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948>\
**Category:** New to Julia\
**Tags:** performance\
**Created:** [February 7, 2017, 5:27am UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948 "2017-02-07T05:27:11Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![stst](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stst/32/17252_2.png) [@stst](https://discourse.julialang.org/u/stst)\
**Post date:** [February 7, 2017, 5:27am UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/1 "2017-02-07T05:27:12Z")

</div>

I am porting code from Matlab to Julia, and I am having trouble finding an efficient way of adding vectors that differ in length. Here are the essential lines, from inside a recursive function:

```julia
% Matlab code
t1 = recursive_function(a+1,b-1,c,d,params);
t2 = recursive_function(a ,b-1,c,d,params); % numel(t2)==numel(t1)-1
result = t1 + [params.AB*t2 0]; % one example
result = t1 + [0 params.AB*t2]; % another example

```

`result` is what gets returned by the function. I translated this to Julia in the obvious (and likely overly naïve) way

```julia
# Julia code
t1 = recursive_function(a+1,b-1,c,d,params)
t2 = recursive_function(a ,b-1,c,d,params) # numel(t2)==numel(t1)-1
result = t1 + push!(params.AB*t2,0.0) # one example
result = t1 + unshift!(0.0,params.AB*t2) # another example

```

With this, I get a lot of memory allocations. `@code_warntype` doesn’t highlight any type instabilities.

Is there a more efficient way to calculate `result`?

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [February 7, 2017, 6:53am UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/2 "2017-02-07T06:53:05Z")

</div>

Are you able to do this in-place, i.e., destroy `t1`? If so, you should try

```julia
@view(t1[1:end-1]) .+= t2
@view(t1[2:end]) .+= t2

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [February 7, 2017, 8:00am UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/3 "2017-02-07T08:00:48Z")

</div>

> [@fengyang.wang](#):
>
> `@view(t1[1:end-1]) .+= t2`

My attempt on version 0.5:

```julia
julia> t1, t2 = rand(10^3), rand(10^3-1);
julia> @view(t1[1:end-1]) .+= t2
syntax: invalid assignment location "true&&Base.view(t1,1:-(Base.endof(t1),1))"

```

while  
`julia> t1[1:end-1] .+= t2`  
works fine. Very odd.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [February 7, 2017, 9:06am UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/4 "2017-02-07T09:06:20Z")

</div>

I’m not sure why @fengyang.wang’s solution isn’t working for me, but here is a pretty speedy alternative:

```julia
for i in eachindex(t2)
    @inbounds t1[i+1] += t2[i]
end
for i in eachindex(t2)
    @inbounds t1[i] += t2[i]
end

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 7, 2017, 1:03pm UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/5 "2017-02-07T13:03:23Z")

</div>

You can’t use `@view` on the lhs of an assignment. In 0.6, you can do:

```julia
@views t1[1:end-1] .+= t2

```

to update `t1` in-place, but writing out the loop is a fast and reasonable option as well.

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [February 7, 2017, 8:10pm UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/6 "2017-02-07T20:10:57Z")

</div>

I hadn’t realized that. Is there any reason why `@view` cannot be used on the LHS? I was under the impression that `.+=` lowered to a `broadcast!` call, so the LHS could be any object, evaluated greedily.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 8, 2017, 5:03am UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/7 "2017-02-08T05:03:12Z")

</div>

> [@fengyang.wang](#):
>
> I hadn’t realized that. Is there any reason why `@view` cannot be used on the LHS?

Yes. `@view a[i]` transforms the expression to `view(a, i)`. So, if you did `@view a[i] = 3` it would transform to `view(a, i) = 3`, which is a function declaration and not an assignment.

As discussed in [Create `@view` macro for creating SubArrays via indexing. by simonbyrne · Pull Request #16564 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/16564), the `@view` macro was therefore purposely designed in a funny way to prevent you from using it on the lhs of an assignment. Unfortunately, this prevents it from being used on the lhs of `.=`, too, where a `view` call would be fine.

Note that doing a slice on the lhs of `=` actually does not produce a slice object: `a[1:2] = ...` turns into a call to `setindex!(a, ..., 1:2)`. So, it already acts in-place and there is no need for `@view`. The problem comes with an updating operator like `+=`, where the lhs is actually used on both the left and right-hand sides of the expression.

The solution is to use `@views` on the whole expression (or a block containing the expression); this looks at the whole expression and does the right thing to prevent any slices from allocating copies. `@views` is a new feature of 0.6, but works on 0.4 and 0.5 via the latest Compat.

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [February 8, 2017, 5:15am UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/8 "2017-02-08T05:15:39Z")

</div>

I still do not fully understand why it is prevented from being on the LHS of `.+=`. To be precise in where I am confused, here is an annotated REPL session

```julia
julia> A = rand(5);

julia> (true && A) = 1; # assignment, expected to fail
ERROR: syntax: invalid assignment location "true&&A"

julia> (true && A) += 1; # assignment, expected to fail
ERROR: syntax: invalid assignment location "true&&A"

julia> (true && A) .= 1; # broadcast!, expected to work

julia> (true && A) .+= 1; # broadcast!, expected to work
ERROR: syntax: invalid assignment location "true&&A"

```

It is this last line that confuses me. To borrow some not-100%-accurate terminology from C++, my understanding was that what goes on the LHS of `=` and `+=` must be an “lvalue”, which `(true && A)` is not. But what goes on the LHS of `.=` and `.+=` is an “rvalue”, which `(true && A)` is. Indeed it seems I am correct for `.=`, but not for `.+=`.

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [February 8, 2017, 5:39am UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/9 "2017-02-08T05:39:35Z")

</div>

After thinking about it some more, I understand now why the `.+=` case is more difficult than the `.=` case, although I think it could be supported with a little more effort. The idea is that

```julia
a += x

```

expands to

```julia
a = a + x

```

and the `a` is duplicated onto both left and right hand sides. This cannot be an issue because for the standard `=` operator, the only kinds of expressions `a` for which this makes sense are names, fields, and `ref`s. For each of these, the operation of “setting” is a fundamentally different operation than “getting”.

In the case of

```julia
A .= x

```

considerably greater flexibility is available for the left-hand side `A`, and indeed this can take on any value that can normally be on the right hand side without issue. (Except, perhaps, as a special case values like `A[x:y]` are rewritten to be views, because otherwise the behaviour of modifying a newly-allocated object and then throwing away the result is nonsensical and error-prone. This seems to be the case on 0.5 at least; I don’t know if it has been changed in 0.6.)

In the case of

```julia
A .+= x

```

it is expanded to

```julia
A .= A .+ x

```

and it is here that `A` is restricted to being something simple. Suppose it were not; then we might have

```julia
somefunction(A) .= somefunction(A) .+ x

```

and the `somefunction` would be called twice, perhaps expensive, and perhaps with additional unwanted side effects. Instead this would need to be expanded to

```julia
let tmp = somefunction(A)
    tmp .= tmp .+ x
end

```

which is not currently supported by the update operator expander.

Hence, if my understanding is correct, it is not a semantic reason that `@views(A[x:y]) .+= x` is not allowed, but instead simply that the code to do it properly has not been written yet, so it is prohibited. Since alternatives like `@views` exist, presumably this is a low priority and unlikely to make it into 0.6.

Does this sound right?

---

<div class="post-metadata">

**Author:** ![stst](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stst/32/17252_2.png) [@stst](https://discourse.julialang.org/u/stst)\
**Post date:** [February 8, 2017, 7:20am UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/10 "2017-02-08T07:20:54Z")

</div>

This works great, giving 50x speedup - wonderful, thanks!

Question concerning the usage of `@inbounds`: What’s the difference between the above and the following?

```julia
@inbounds for i in eachindex(t2)
    t1[i+1] += t2[i]
end

```

(The [documentation](http://docs.julialang.org/en/stable/manual/performance-tips/) gives both. This [post](https://groups.google.com/forum/#!searchin/julia-users/inbounds%7Csort:relevance/julia-users/XGW0T2oh5HQ/UbLqR_jtexwJ) doesn’t quite clarify this.) I don’t see any noticeable performance difference for my use case, but there are differences where `$(Expr(:inbounds, true))` shows up in the `@code_warntype` output. Here is my test code:

```julia
function test1!(t1,t2,M)
  for k in 1:M
    for i in eachindex(t2)
        @inbounds t1[i+1] += t2[i]
    end
  end
end

function test2!(t1,t2,M)
  for k in 1:M
    @inbounds for i in eachindex(t2)
        t1[i+1] += t2[i]
    end
  end
end

N = 1000
t1 = zeros(N+1)
t2 = rand(N)
M = 10000
@code_warntype test1!(t1,t2,M)
@code_warntype test2!(t1,t2,M)

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [February 8, 2017, 11:33am UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/11 "2017-02-08T11:33:21Z")

</div>

> [@stst](#):
>
> What’s the difference between the above and the following?

As far as I know, there is no difference. I chose this for aesthetic reasons.

Be aware, though, that you should be very certain when you use `@inbounds`. If there is any uncertainty about the lengths of the vectors you should drop it, or perhaps explicitely perform a check before the loop.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 8, 2017, 1:13pm UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/12 "2017-02-08T13:13:09Z")

</div>

> [@fengyang.wang](#):
>
> I still do not fully understand why it is prevented from being on the LHS of .+=.

You’re right, I think it’s a bug in the parser. In 0.4, `x .+= y` corresponded to `x = x .+ y`. When that was changed to mean `x .= x .+ y` in 0.5, I guess we forgot to eliminate the syntax error for the LHS being an rvalue. Can you file an issue?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 8, 2017, 1:19pm UTC](https://discourse.julialang.org/t/adding-vectors-of-different-lengths/1948/13 "2017-02-08T13:19:03Z")

</div>

> [@fengyang.wang](#):
>
> and the somefunction would be called twice

Yes, but it would be straightforward, in principle, to eliminate the double call during lowering.
