# Should \`conj\` always materialize the result?

**URL:** <https://discourse.julialang.org/t/should-conj-always-materialize-the-result/105911>\
**Category:** Internals & Design\
**Tags:** linearalgebra\
**Created:** [November 7, 2023, 6:45pm UTC](https://discourse.julialang.org/t/should-conj-always-materialize-the-result/105911 "2023-11-07T18:45:28Z")\
**Posts on this page:** 3\
**Page:** 1

<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:** [November 7, 2023, 6:45pm UTC](https://discourse.julialang.org/t/should-conj-always-materialize-the-result/105911/1 "2023-11-07T18:45:28Z")

</div>

The docstring for `conj` states that

```julia
conj(A::AbstractArray)

  Return an array containing the complex conjugate of each entry in array A.

  Equivalent to `conj.(A)`, except that when `eltype(A) <: Real` `A` is returned without copying, and that when `A` has zero dimensions, a 0-dimensional array is returned (rather than a scalar).

```

Except, `conj` is special-cased to be lazy for `Adjoint` and `Transpose`, so it is not equivalent to `conj.(A)` as the result shares memory with the original array. For example:

```julia
julia> A = rand(ComplexF64,2,2)'
2×2 adjoint(::Matrix{ComplexF64}) with eltype ComplexF64:
 0.891314-0.0686279im 0.0718785-0.679878im
 0.685828-0.0606725im 0.155366-0.0544453im

julia> B = conj(A)
2×2 transpose(::Matrix{ComplexF64}) with eltype ComplexF64:
 0.891314+0.0686279im 0.0718785+0.679878im
 0.685828+0.0606725im 0.155366+0.0544453im

julia> B .*= 2
2×2 transpose(::Matrix{ComplexF64}) with eltype ComplexF64:
 1.78263+0.137256im 0.143757+1.35976im
 1.37166+0.121345im 0.310732+0.108891im

julia> A
2×2 adjoint(::Matrix{ComplexF64}) with eltype ComplexF64:
 1.78263-0.137256im 0.143757-1.35976im
 1.37166-0.121345im 0.310732-0.108891im

```

This behavior has explicit tests for it, so this appears intentional. Would it be better to change this behavior and be consistent with the docstring (and with other matrices in general)?

---

<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:** [November 7, 2023, 6:50pm UTC](https://discourse.julialang.org/t/should-conj-always-materialize-the-result/105911/2 "2023-11-07T18:50:18Z")

</div>

This seems to have been discussed in [spezialized conj of Transpose/Adjoint by simeonschaub · Pull Request #33609 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/33609)

---

<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:** [November 7, 2023, 9:51pm UTC](https://discourse.julialang.org/t/should-conj-always-materialize-the-result/105911/3 "2023-11-07T21:51:42Z")

</div>

> [@jishnub](#):
>
> Would it be better to change this behavior and be consistent with the docstring (and with other matrices in general)?

I think it would be better to clarify the docstring.

`conj(A)` is _algebraically_ equivalent to `conj.(A)` in that `conj.(A) == conj(A)` for all `A`. It isn’t necessarily _computationally_ equivalent, both because `conj(A)` may not allocate a new matrix (e.g. if `eltype(A) <: Real`) and because `conj.(A)` “fuses” with other dot calls (like any dot call).
