# Problem with Complex{Rationals}

**URL:** <https://discourse.julialang.org/t/problem-with-complex-rationals/9474>\
**Category:** General Usage\
**Created:** [March 3, 2018, 1:03pm UTC](https://discourse.julialang.org/t/problem-with-complex-rationals/9474 "2018-03-03T13:03:48Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [March 3, 2018, 1:03pm UTC](https://discourse.julialang.org/t/problem-with-complex-rationals/9474/1 "2018-03-03T13:03:48Z")

</div>

Hello,  
I have found something which makes it difficult to work with the field Q(i)

> julia\> Complex{Rational{Int}}\<:Complex{Real}  
> false

Is it possible to make julia understand that this should be true?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [March 3, 2018, 1:10pm UTC](https://discourse.julialang.org/t/problem-with-complex-rationals/9474/2 "2018-03-03T13:10:06Z")

</div>

You are hitting the covariance / contravariance distinction, see [https://docs.julialang.org/en/stable/manual/types/#Parametric-Composite-Types-1](https://docs.julialang.org/en/stable/manual/types/#Parametric-Composite-Types-1).

You have for example:

```julia
julia> Complex{Rational{Int}} <: Complex{<:Real}
true

```

where ` Complex{<:Real} = Complex{T} where {T <: Real}`

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [March 3, 2018, 1:10pm UTC](https://discourse.julialang.org/t/problem-with-complex-rationals/9474/3 "2018-03-03T13:10:38Z")

</div>

> [@Jean\_Michel](#):
>
> Is it possible to make julia understand that this should be true?

That’s just type covariance. Read [https://docs.julialang.org/en/stable/manual/types/#Parametric-Composite-Types-1](https://docs.julialang.org/en/stable/manual/types/#Parametric-Composite-Types-1) . But basically if your issue was dispatch then you’re do

```julia
function f(x::Complex{T}) where T<:Real

```

(oh, jinx! 😄)

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [March 3, 2018, 1:14pm UTC](https://discourse.julialang.org/t/problem-with-complex-rationals/9474/4 "2018-03-03T13:14:28Z")

</div>

Thank you! It was not for dispatching but to make a test. It is a bit mind-boggling that

> julia\> Complex{Rational{Int}} \<: Complex{\<:Real}  
> true

but

> julia\> Complex{Rational{Int}} \<: Complex{Real}  
> false

It will take me some time to be completely confortable with julia’s type system

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [March 3, 2018, 1:18pm UTC](https://discourse.julialang.org/t/problem-with-complex-rationals/9474/5 "2018-03-03T13:18:34Z")

</div>

> [@Jean\_Michel](#):
>
> Complex{Real}

For example:

A vector of `Complex{Real}` is able to hold values with different types:

```julia
julia> Complex{Real}[Complex(1, 2), Complex(1.0, 2.0)]
2-element Array{Complex{Real},1}:
   1+2im  
 1.0+2.0im

```

A vector of `Complex{<:Real}` can hold values of `Complex{T}` where `T <: Real` _but all values must be of the same type_. In a sense, you are free to choose `T <: Real` but after you have chosen it, you are stuck with it.

---

<div class="post-metadata">

**Author:** ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)\
**Post date:** [March 3, 2018, 1:27pm UTC](https://discourse.julialang.org/t/problem-with-complex-rationals/9474/6 "2018-03-03T13:27:43Z")

</div>

Ok, it makes sense when you think of collections. I guess this is how you have to think about types.

---

<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:** [March 3, 2018, 4:10pm UTC](https://discourse.julialang.org/t/problem-with-complex-rationals/9474/7 "2018-03-03T16:10:54Z")

</div>

You should also understand that this distinction is absolutely critical for performance. It’s not just an arbitrary pedantic choice. Think about how instances of the types are actually stored and processed on the computer.

A `Complex{Rational{Int}}` for `a+bi` can be (and is) stored as four consecutive `Int` (64-bit integer) values: `(anum,aden,bnum,bden)`. For operations on such quantities, since the compiler knows everything’s type and how it is stored, it can load the numerators and denominators directly into integer registers and perform arithmetic immediately with corresponding machine instructions. An array of `n` such values is stored as an array of `4n` 64-bit integers consecutively in memory.

Conversely, if you have a `Complex{Real}` value, then the real and imaginary parts can be of any `Real` type. That means that they must each be a [“box”](https://stackoverflow.com/questions/13055/what-is-boxing-and-unboxing-and-what-are-the-trade-offs) that has a type tag (to indicate what `Real` type it is) followed by the actual value. Since these values may be of different sizes depending on the type, to store a `Complex{Real}` instance in a fixed amount of memory it must store _pointers_ to the boxes. So, to work with a `Complex{Real}` value, the processor must fetch the pointers, then use the pointers to fetch the type tags, then dispatch to code that does `+` (for example) on the actual values for those types. Huge overhead! And an array of `Complex{Real}` objects must be an array of pairs of pointers to boxes — looping over the array to do some operation, since _every element can be a different type_ you need to do the pointer-chasing and dynamic dispatch for _every element_.

If you have a compiled function that operates on a `Complex{Real}` or an array of `Complex{Real}`, therefore, it is completely different from code that operates on `Complex{Rational{Int}}`. You can’t use either one for the other. (If `A` is a subtype of `B`, it essentially means “compiled code for `B` can be used on instances of `A`” — this is the _purpose_ of the subtype relation, to decide what code is applicable to what types.)

This is why Julia’s parametric types have the “invariant” semantics that they do. Once you get used to it, it’s quite easy to work with, and allows you to have generic types like `Complex` that are still fast and efficient for concrete instances.

---

<div class="post-metadata">

**Author:** ![Azamat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/azamat/32/6892_2.png) [@Azamat](https://discourse.julialang.org/u/Azamat)\
**Post date:** [November 25, 2018, 10:03am UTC](https://discourse.julialang.org/t/problem-with-complex-rationals/9474/8 "2018-11-25T10:03:08Z")

</div>

Is there speed advantage of the signature  
`f(x::T) where {T <: SomeAbstractType} = ...`  
over the  
`f(x::SomeAbstractType) = ...` ?

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [November 25, 2018, 12:06pm UTC](https://discourse.julialang.org/t/problem-with-complex-rationals/9474/9 "2018-11-25T12:06:35Z")

</div>

No. Indicating types in method signatures is generally speaking irrelevant for performance (even if you just define `f(x) =... ` it will have the same speed) . It’s more like defining a user interface in the sense of only allowing certain types to be passed to the function. However, even this is identical on your example.
