# Taking Complex Autodiff Seriously in ChainRules

**URL:** <https://discourse.julialang.org/t/taking-complex-autodiff-seriously-in-chainrules/39317>\
**Category:** Specific Domains\
**Tags:** numerics, chainrulescore, complex-numbers\
**Created:** [May 12, 2020, 1:52am UTC](https://discourse.julialang.org/t/taking-complex-autodiff-seriously-in-chainrules/39317 "2020-05-12T01:52:35Z")\
**Posts on this page:** 1\
**Showing post:** 52

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [May 21, 2020, 2:23am UTC](https://discourse.julialang.org/t/taking-complex-autodiff-seriously-in-chainrules/39317/52 "2020-05-21T02:23:38Z")

</div>

The pullback of a function in Zygote is a function \mathcal{B\_f}(v) = J\_f^\dagger \* v where v is a vector, J\_f is the Jacobian of the function f and ^\dagger is the Hermitian conjugate.

Zygote will treat a `struct` with `n` fields as if it were a vector of length `n`, so the complex number `1 + 0im` is treated like the vector `[1 0]` and `0 + 1im` is treated like the vector `[0, 1]` in the above Jacobian vector product. The vector returned from this product is then converted into a struct

That is, in this case \mathcal{B}\_f(1) = J\_f^\dagger \* [1, 0] and \mathcal{B}\_f(i) = J\_f ^\dagger \* [0, 1]. The Jacobian here is `2x2`, so this function returns a vector with two elements which are then interpreted as the real and imaginary parts of a complex number.

This is how Zygote deals with all `struct`s, and it’s quite beautiful imo.

---

_[View the full topic](https://discourse.julialang.org/t/taking-complex-autodiff-seriously-in-chainrules/39317)._
