# Qr decomposition matrix type

**URL:** <https://discourse.julialang.org/t/qr-decomposition-matrix-type/27566>\
**Category:** General Usage\
**Tags:** question\
**Created:** [August 15, 2019, 1:35am UTC](https://discourse.julialang.org/t/qr-decomposition-matrix-type/27566 "2019-08-15T01:35:48Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![\_dominic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/_dominic/32/7845_2.png) [@\_dominic](https://discourse.julialang.org/u/_dominic)\
**Post date:** [August 15, 2019, 1:35am UTC](https://discourse.julialang.org/t/qr-decomposition-matrix-type/27566/1 "2019-08-15T01:35:48Z")

</div>

I just want to compute a qr decomposition and pass the Q matrix to the log function

```julia
using LinearAlgebra
D = rand(Float64, 3, 3)
Q, R = qr(D)
W = log(Q) # Error

```

Why is Q not a simple regular matrix type? How can I convert it to a regular matrix?

---

<div class="post-metadata">

**Author:** ![kmundnic](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@kmundnic](https://discourse.julialang.org/u/kmundnic)\
**Post date:** [August 15, 2019, 4:32am UTC](https://discourse.julialang.org/t/qr-decomposition-matrix-type/27566/2 "2019-08-15T04:32:19Z")

</div>

You can convert `Q` to a `Matrix{Float64}` using

```julia
Q = convert(Matrix{Float64}, Q)

```

As to why Q is not of type `Matrix{Float64}`, I don’t know, that’s something that I don’t understand yet.

Note that in your decomposition, most likely `Q` will have negative values. If you want to apply `log` to _every entry_ of `Q`, you can use `.` notation (dot notation)

```julia
W = log.(Q)

```

However, this will likely throw an error since, as I said before, `Q` will likely have negative entries.

---

<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:** [August 15, 2019, 7:43am UTC](https://discourse.julialang.org/t/qr-decomposition-matrix-type/27566/3 "2019-08-15T07:43:49Z")

</div>

First of all, on a general note, if you wrap your code in a triple tick block ```` <code goes here> ```` it will be displayed much more nicely.

To your actual questions:

> [@\_dominic](#):
>
> Why is Q not a simple regular matrix type?

The reason why many things in Julia are stored in special types (not just `Q` of a QR decomposition) is generally two fold:

- **Data structuring: we can store the object much more efficiently while still make them _behave_ as if they were, say, an `AbstractMatrix`.** This is known as _duck typing_. As long as it quacks and walks like a duck, from an outsiders point of view it _is_ a duck. Example: `Diagonal(D)`. Clearly, it would be a waste of memory to store all the zero matrix elements for a diagonal matrix. Hence, internally, we only store the diagonal entries as a vector (see [here](https://github.com/JuliaLang/julia/blob/f2c3d4dbe85874c3cd19ccc42dfaff251397e413/stdlib/LinearAlgebra/src/diagonal.jl#L5) that this is indeed what Julia does.). However, the `Diagonal` matrix will still _behave_ like a regular matrix in many cases.

- **Method dispatch: special function implementations**. Julia always selects a specific method of a function based on all argument types (multiple dispatch). We can utilize this to implement special, fast algorithms for certain matrix types. Example: say, I’d want to calculate the determinant of a `Diagonal` matrix. Naively, I could treat it like any other `Matrix` and use something like the [Rule of Sarrus](https://en.wikipedia.org/wiki/Rule_of_Sarrus) (assuming `3x3` here for the sake of the argument). Obviously, it would be much more efficient to only multiply the non-zero diagonal elements. This is [precisely what Julia does](https://github.com/JuliaLang/julia/blob/f2c3d4dbe85874c3cd19ccc42dfaff251397e413/stdlib/LinearAlgebra/src/diagonal.jl#L475).

Turning to your specific case, we can check what that `QRCompactWY` object really is by asking for help in the REPL, `? QRCompactWY`, or [consulting the docs](https://docs.julialang.org/en/latest/stdlib/LinearAlgebra/#LinearAlgebra.QRCompactWY). Personally, I don’t know anything about this format (frankly, I also don’t care), but there I’d find all the implementation details. In many cases, a `QRCompactWY` will just behave like a matrix. For example, I can multiply it with a vector, which will call a non-generic implementation of `*` in `qr.jl` (check ` @which Q * rand(3)`).

If you feel that `log(Q::QRCompactWY)` should work as well, than perhaps there is a special implementation or a fallback method missing in `stdlib/LinearAlgebra/qr.jl`. You could consider opening an issue or even better a pull request in that case.

> [@\_dominic](#):
>
> How can I convert it to a regular matrix?

Note that you can always access the fallback by changing `Q`s type (and hence its data structure) first, by calling `log(Matrix(Q))`.

---

<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:** [August 15, 2019, 9:04am UTC](https://discourse.julialang.org/t/qr-decomposition-matrix-type/27566/4 "2019-08-15T09:04:46Z")

</div>

Note that in addition to the explanations, `log` should work for all square `AbstractMatrix` values, in the worst case by using the fallback

```julia
log(A::AbstractMatrix) = log(Matrix(A))

```

(this assumes you want the matrix, and not the elementwise, logarithm).

Consider opening an issue, or making a small pull request to fix it.

---

<div class="post-metadata">

**Author:** ![\_dominic](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/_dominic/32/7845_2.png) [@\_dominic](https://discourse.julialang.org/u/_dominic)\
**Post date:** [August 15, 2019, 8:03pm UTC](https://discourse.julialang.org/t/qr-decomposition-matrix-type/27566/5 "2019-08-15T20:03:34Z")

</div>

thanks crstnbr, your explanation covered most of my frustrations with getting started with Julia. Doesn’t _duck typing_ cause reductions in performance then?

---

<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:** [August 15, 2019, 10:54pm UTC](https://discourse.julialang.org/t/qr-decomposition-matrix-type/27566/6 "2019-08-15T22:54:51Z")

</div>

> [@\_dominic](#):
>
> Doesn’t _duck typing_ cause reductions in performance then?

Why would you think that? For most cases, it’s quite the opposite.

---

<div class="post-metadata">

**Author:** ![loisel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/loisel/32/50626_2.png) [@loisel](https://discourse.julialang.org/u/loisel)\
**Post date:** [August 18, 2019, 2:28pm UTC](https://discourse.julialang.org/t/qr-decomposition-matrix-type/27566/7 "2019-08-18T14:28:13Z")

</div>

The algorithm for QR decomposition is by [Householder reflections](https://en.wikipedia.org/wiki/QR_decomposition#Using_Householder_reflections). For an n \times k matrix A, k \leq n, the main algorithm outputs an n \times k upper triangular matrix R and the set of k Householder vectors of dimensions n in O(nk^2) FLOPS. Converting the k Householder vectors to the n \times n matrix Q is an auxiliary algorithm requiring O(n^2k) FLOPS.

For example, if k=1, these are O(n) and O(n^2) FLOPS respectively; thus, actually computing the Q matrix is by far the most expensive step in this case. As a result, one avoids computing the actual matrix Q when possible. For example, it is possible to solve least-squares problems without actually computing Q, using only O(nk^2) FLOPS and not the full O(n^2k) FLOPS.
