# Pinning LinearAlgebra in Julia 1.6.2

**URL:** <https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596>\
**Category:** General Usage\
**Tags:** linearalgebra\
**Created:** [August 18, 2021, 11:52am UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596 "2021-08-18T11:52:11Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![fipelle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fipelle/32/4772_2.png) [@fipelle](https://discourse.julialang.org/u/fipelle)\
**Post date:** [August 18, 2021, 11:52am UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/1 "2021-08-18T11:52:11Z")

</div>

Hi,

I am testing two packages in Julia 1.6.2 (TSAnalysis.jl and a new private package in the same area), as I have been using them with the LTS version until now. They seem to be working fine and pass all unit tests except one. In the problematic test, I have noticed that there are small differences (in the order of 1e-16 to 1e-8) in the output.

I cannot post a reproducible example for now, since the relevant code is still not available on Git and might be too complicated to describe in detail here. However, broadly speaking, I am processing a model with large `Symmetric` block diagonal covariance matrices with the Kalman filter in TSAnalysis.jl. At the second iteration of the filter (`t=2`), the covariance matrix P\_post already shows 1e-14 differences compared to the LTS output. Over time, this gap increases.

I am unsure what is creating these differences. I suppose that it can be either the `inv` function for symmetric matrices, the use of `Symmetric(...)` itself, changes in the `lyap` function or in more standard matrix operations (e.g., matrix product, adjoint). Therefore, I was wondering if it could be possible to pin down LinearAlgebra to the LTS version or if there exists a list of critical changes.

Thank you.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [August 18, 2021, 12:16pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/2 "2021-08-18T12:16:07Z")

</div>

The standard libraries are fixed for each julia version (for now). So if you want different versions of LinearAlgebra you need different Julia versions.

> [@fipelle](#):
>
> or to get a complete list of changes / a hint regarding what is possibly going on.

Not sure I get what you mean here. List of changes of LinearAlgebra? The code is here: [https://github.com/JuliaLang/julia/tree/master/stdlib/LinearAlgebra](https://github.com/JuliaLang/julia/tree/master/stdlib/LinearAlgebra), so you could use various git-tools to dig into it.

---

<div class="post-metadata">

**Author:** ![fipelle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fipelle/32/4772_2.png) [@fipelle](https://discourse.julialang.org/u/fipelle)\
**Post date:** [August 18, 2021, 1:11pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/3 "2021-08-18T13:11:17Z")

</div>

Thanks, will do. I was actually looking for a list of critical changes if the functions listed above, but I can certainly look into the list of commits **[I have edited the OP to explain it upfront]**

> [@mauro3](#):
>
> The standard libraries are fixed for each julia version (for now). So if you want different versions of LinearAlgebra you need different Julia versions

This is quite annoying for comparisons 😕

---

<div class="post-metadata">

**Author:** ![John\_Gibson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/john_gibson/32/5321_2.png) [@John\_Gibson](https://discourse.julialang.org/u/John_Gibson)\
**Post date:** [August 18, 2021, 2:07pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/4 "2021-08-18T14:07:35Z")

</div>

It’s annoying, but the amplification of floating point errors is kind of a fundamental issue of numerical computations. It’s better to have your tests check whether error is under some bound than to require exact replication of previous results.

For example, consider solving this Ax=b system by two different algorithms, SVD and QR. Both methods produce approximate x’s that satisfy the equation to roughly 1e-15. But the x’s they produce differ from each other and from the “true” x by 1e-6. Neither of the solved x’s is better than the other. (Similarly, if there’s a 1e-8 difference between answers produced for your problem by Julia 1.5 linear algebra and 1.6, it’s unlikely that either answer is better than the other.) The issue is that x cannot be computed to more than six digits precision in 64-bit floating point arithmetic, for an Ax=b problem with the 8x8 Hilbert matrix A. A unit test for this problem should simply check that the norm(Ax-b) \< 1e-15 and that the computed x differs from the original by less than 1e-05.

```julia
julia> A = [1/(i+j-1) for i in 1:8, j in 1:8];

julia> x = rand(8)
8-element Vector{Float64}:
 0.1278532352020687
 0.7676493945865812
 0.00913463981518925
 0.6222238155162669
 0.10323435913906587
 0.9791508421975381
 0.6803781015368064
 0.9531836668412241

julia> b = A*x;

julia> norm(A*x-b)
0.0

julia> Asvd = svd(A);

julia> Aqr = qr(A);

julia> xsvd = Asvd\b
8-element Vector{Float64}:
 0.12785323521152347
 0.7676493940367002
 0.009134647388002199
 0.6222237729310713
 0.10323447719153722
 0.979150671248731
 0.6803782255013682
 0.953183631315329

julia> xqr = Aqr\b
8-element Vector{Float64}:
 0.12785323514108654
 0.7676493978160822
 0.009134598049168947
 0.6222240397918233
 0.10323375917314824
 0.9791516866231814
 0.6803775032989913
 0.9531838349809921

julia> norm(A*xsvd-b)
1.1511037319626838e-15

julia> norm(A*xqr-b)
4.1910000110727263e-16

julia> norm(x-xsvd)
2.4831498398415594e-7

julia> norm(x-xqr)
1.229319971970093e-6

julia> norm(xsvd-xqr)
1.4775841522815336e-6

```

---

<div class="post-metadata">

**Author:** ![fipelle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fipelle/32/4772_2.png) [@fipelle](https://discourse.julialang.org/u/fipelle)\
**Post date:** [August 18, 2021, 2:36pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/5 "2021-08-18T14:36:48Z")

</div>

Thank you, John. That’s helpful.

Just a few points:

1. Are the 1e-5 and 1e-6 specific to this example or generalise to a wider class of linear systems? If they do generalise, where can I read more about it?
2. The norm sounds like a good idea to handle floating point errors in unit tests and I will use it 🙂 For now, I was simply using the `round` function with `digits=10` following a similar logic in mind.
3. The approach based on the `round` function is enough for a battery of tests, except for the one described in my first post. Do you think that the block diagonal structure of the covariance matrix used in this very test might be the cause of this numerical instability?

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [August 18, 2021, 3:22pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/6 "2021-08-18T15:22:59Z")

</div>

> [@fipelle](#):
>
> ut I can certainly look into the list of commits **[I have edited the OP to explain it upfront]**

There is also [https://github.com/JuliaLang/julia/blob/master/HISTORY.md](https://github.com/JuliaLang/julia/blob/master/HISTORY.md) which should list all major changes. But all changes should be non-breaking. So if you find something breaking, then report it.

---

<div class="post-metadata">

**Author:** ![fipelle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fipelle/32/4772_2.png) [@fipelle](https://discourse.julialang.org/u/fipelle)\
**Post date:** [August 18, 2021, 3:25pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/7 "2021-08-18T15:25:23Z")

</div>

Thanks. I am incrementally upgrading Julia starting from the LTS version to understand what happened!

---

<div class="post-metadata">

**Author:** ![fipelle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fipelle/32/4772_2.png) [@fipelle](https://discourse.julialang.org/u/fipelle)\
**Post date:** [August 18, 2021, 6:01pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/8 "2021-08-18T18:01:41Z")

</div>

I tried with all versions listed in [Julia Downloads (Old releases)](https://julialang.org/downloads/oldreleases/#v142_may_23_2020). It works fine up to v1.4.2 (i.e., at the same floating precision of the LTS version). It stops working with v1.5.4. I will edit this post later today if I get to the bottom of it.

---

<div class="post-metadata">

**Author:** ![John\_Gibson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/john_gibson/32/5321_2.png) [@John\_Gibson](https://discourse.julialang.org/u/John_Gibson)\
**Post date:** [August 18, 2021, 6:35pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/9 "2021-08-18T18:35:55Z")

</div>

You’re welcome; I’m glad that helps. To your questions:

1. The 1e-06 error was specific to the given example, but it does follow a general theory for linear systems and even more broadly, all numeric calculation. The theory for Ax=b problems is that for appropriately stable solution algorithms the error in x obeys the bound

2. Norms are great for unit tests!

3. I bet if you compute the condition number of the block-diagonal matrix in your example, you’ll find it is about 10^8. That follows from \kappa(A) \approx \epsilon\_m^{-1} \; || x - \hat{x} ||/||x|| \approx 10^{16} \cdot 10^{-8}

---

<div class="post-metadata">

**Author:** ![fipelle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fipelle/32/4772_2.png) [@fipelle](https://discourse.julialang.org/u/fipelle)\
**Post date:** [August 18, 2021, 7:26pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/10 "2021-08-18T19:26:38Z")

</div>

Thanks again, I will definitely take a look at this textbook.

The issue I described above is observed when moving from 1.4.2 to 1.5.0. I am comparing these versions of Julia on git and I suppose that the different floating precision depends on changes in LinearAlgebra such as:

1. the inclusion of `spmv!` (for which I cannot find an official documentation);
2. the new promotion rules for `Diagonal` and `Symmetric` matrix sums and subtractions.

I think they are non-breaking per se, but when used within a loop they might amplify floating point differences.

---

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [August 18, 2021, 7:42pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/11 "2021-08-18T19:42:13Z")

</div>

> [@fipelle](#):
>
> The issue I described above is observed when moving from 1.4.2 to 1.5.0.

Do you happen to use random numbers in the test? The way random numbers are generated changed with v1.5, so if you do use random numbers that could be the reason.

---

<div class="post-metadata">

**Author:** ![fipelle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fipelle/32/4772_2.png) [@fipelle](https://discourse.julialang.org/u/fipelle)\
**Post date:** [August 18, 2021, 7:43pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/12 "2021-08-18T19:43:50Z")

</div>

I do, but I am using `StableRNGs`. Shouldn’t it be safe with 1.5?

---

<div class="post-metadata">

**Author:** ![StevenWhitaker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevenwhitaker/32/9749_2.png) [@StevenWhitaker](https://discourse.julialang.org/u/StevenWhitaker)\
**Post date:** [August 18, 2021, 8:20pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/13 "2021-08-18T20:20:15Z")

</div>

> [@fipelle](#):
>
> I am using `StableRNGs` .

I’ve never actually used that package, but yes, I believe random numbers generated using that package should be reproducible across Julia versions.

---

<div class="post-metadata">

**Author:** ![John\_Gibson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/john_gibson/32/5321_2.png) [@John\_Gibson](https://discourse.julialang.org/u/John_Gibson)\
**Post date:** [August 18, 2021, 9:27pm UTC](https://discourse.julialang.org/t/pinning-linearalgebra-in-julia-1-6-2/66596/14 "2021-08-18T21:27:45Z")

</div>

I don’t think that you’re getting a less precise answer with 1.5.0. I think instead you get _equally imprecise_ answers in 1.4.2 and 1.5.0 (like in my example, both xsvd and xqr are equally imprecise). But if you use the 1.4.2 answer as the standard, then it appears that 1.5.0 answer is in error.

Neither answer is better than the other. They’re equally imprecise. The error shows up in different ways depending on how you do the algorithm, maybe something to do with changes in promotion rules. But the change does not mean worsening. Just different.

This is expected behavior from a theory-of-numerics perspective. Maybe there’s more going on in your example than I know about. But what you’re seeing is expected. And the fix is to make your unit tests check that the computation aligns with theory (error bounded as discussion above), and not to expect higher accuracy than is possible.
