# Why is \`copy(adjoint)\` not an adjoint object?

**URL:** https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371
**Category:** Internals & Design
**Tags:** column-major, row-major, adjoint, copy, deepcopy
**Created:** [February 16, 2021, 4:17am UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371 "2021-02-16T04:17:58Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)
#### Post date: [February 16, 2021, 4:17am UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/1 "2021-02-16T04:17:59Z")

</div>

This surprised me:

```julia
julia> typeof(copy(rand(4,4)'))
Matrix{Float64} (alias for Array{Float64, 2})

julia> typeof(deepcopy(rand(4,4)'))
LinearAlgebra.Adjoint{Float64, Matrix{Float64}}

```

I have an algorithm which looks prettier when written assuming row-major order. To ensure the code looks pretty and it also runs fast on Julia’s native column-major arrays, I simply used the `Adjoint` object. It works great and it is both fast and the code looks nice. However, the speedup was lost when I ran it on copies of my arrays. Personally, I got to fix that simply by using `deepcopy`, and it is truly not a problem, but the behavior of `copy` surprised me.

This does not seem to be a question of shallow copy vs deep copy, right? It is more of a question related to the fact that `copy` implicitly runs `collect` on the object it is copying? This sound counterintuitive to me. Is there any rationale behind it, or is it more of a random historic fact?

---

<div class="post-metadata">

### Author: ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)
#### Post date: [February 16, 2021, 4:23am UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/2 "2021-02-16T04:23:15Z")

</div>

More generally, why is `copy` not preserving the type of the object it is copying?

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [February 16, 2021, 9:30am UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/3 "2021-02-16T09:30:44Z")

</div>

Same remark seems to have been made [here](https://discourse.julialang.org/t/meaning-of-copy-for-arrays/43420) by @dlfivefifty. It does not say if a PR was created.

---

<div class="post-metadata">

### Author: ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)
#### Post date: [February 16, 2021, 9:52am UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/4 "2021-02-16T09:52:43Z")

</div>

`copy` was chosen as the function that materializes lazy adjoints and transposes (xref [https://github.com/JuliaLang/julia/pull/25364](https://github.com/JuliaLang/julia/pull/25364)).

---

<div class="post-metadata">

### Author: ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)
#### Post date: [February 16, 2021, 1:29pm UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/5 "2021-02-16T13:29:45Z")

</div>

But that was apparently when `collect` was supposed to be deprecated (replaced with `Array`), which didn’t happen… See [https://github.com/JuliaLang/julia/issues/16029](https://github.com/JuliaLang/julia/issues/16029)

In any case, I wonder what was the rationale: it seems more useful and intuitive to use `collect` or `Array` for materialization and have `copy` make a straight copy?

---

<div class="post-metadata">

### Author: ![fph](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fph/32/17159_2.png) [@fph](https://discourse.julialang.org/u/fph)
#### Post date: [February 16, 2021, 2:39pm UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/6 "2021-02-16T14:39:50Z")

</div>

This may be related to another thread of mine where I reported that adjointness ‘disappears’ after `abs.`: [How to write generic low-rank updates?](https://discourse.julialang.org/t/how-to-write-generic-low-rank-updates/46370)

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [February 16, 2021, 3:12pm UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/7 "2021-02-16T15:12:47Z")

</div>

I think that the fundamental question is _why_ you would want to copy a `LinearAlgebra.Adjoint`.

---

<div class="post-metadata">

### Author: ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)
#### Post date: [February 16, 2021, 3:55pm UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/8 "2021-02-16T15:55:42Z")

</div>

That question seems weird to me, as it can be asked of any functionality. Here is of the top of my head:

- First and foremost, the whole point of `LinearAlgebra.Adjoint` is that it is lazy-ish, which permits certain optimizations. Otherwise we would just always use an explicit transpose. It is also **the** way to create a row-major matrix in Julia, which is important for efficient use of CPU cache by some algorithms.
- the copy is of use for benchmarks of in-place operations
- or for Monte Carlo simulations involving states stored in such an object
- purely for consistency purposes: `copy` changing the type of an object seems like a weird contract

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [February 16, 2021, 4:00pm UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/9 "2021-02-16T16:00:49Z")

</div>

The interface of `copy` is mostly a convention, but generally if the argument is a wrapper that provides a “view” (eg `Adjoint`, `PermutedDimsArray`, `SubArray`), would you expect that it copies the parent and makes a similar view?

This may be a reasonable use case in some contexts, but that’s not how it works currently — maybe finding a different name for it would be the best way forward, instead of breaking `copy`.

In the meantime, you can copy the parent if you want to modify an object like this.

---

<div class="post-metadata">

### Author: ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)
#### Post date: [February 16, 2021, 4:05pm UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/10 "2021-02-16T16:05:25Z")

</div>

Yeah, I did expect it would copy the parent and make a similar view. I see how this can go wrong if the parent is much bigger.

The status quo now makes sense to me (the current convention about copies of views). It is certainly not an intuitive convention to me, but I can hardly claim some universal opinion here.

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [February 17, 2021, 7:59pm UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/11 "2021-02-17T19:59:13Z")

</div>

As mentioned in the thread linked above

```julia
julia> copy([1,2]')
1×2 LinearAlgebra.Adjoint{Int64,Array{Int64,1}}:
 1 2

```

so `copy` does preserve `Adjoint` wrappers at times.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [February 17, 2021, 9:02pm UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/12 "2021-02-17T21:02:18Z")

</div>

That final case is important — and hopefully proves the rule by exception — because adjoint vectors behave differently than one-row matrices.

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [February 18, 2021, 7:03am UTC](https://discourse.julialang.org/t/why-is-copy-adjoint-not-an-adjoint-object/55371/13 "2021-02-18T07:03:11Z")

</div>

How should wrappers of `Adjoint` vectors behave? I guess it will make sense to preserve their nature. Currently

```julia
julia> OffsetArray([1,2]', 0, 0)
1×2 OffsetArray(adjoint(::Vector{Int64}), 1:1, 1:2) with eltype Int64 with indices 1:1×1:2:
 1 2

julia> OffsetArray([1,2]', 0, 0) |> copy
1×2 OffsetArray(::Matrix{Int64}, 1:1, 1:2) with eltype Int64 with indices 1:1×1:2:
 1 2

```

In this case the copy is a 1-row matrix and not an `Adjoint`. Would it make sense for `OffsetArray`s to pass on the `copy` operation to the parent?
