Skip to content

Eigenbox - #764

Open
blegat wants to merge 10 commits into
JuliaIntervals:masterfrom
blegat:eigenbox
Open

blegat wants to merge 10 commits into
JuliaIntervals:masterfrom
blegat:eigenbox

Conversation

@blegat

@blegat blegat commented Jun 21, 2026 •

Copy link
Copy Markdown

As discussed during the meeting, the current implementation in the LinearAlgebra extension is incorrect for large intervals while the implementation in IntervalLinearAlgebra works for large interval but is its computation of eigvals for the matrix of centers and radius is just using floating point computation. By combining both, we have a fully rigorous eigen function for matrices of intervals.

This was done by Claude Code but I have done a pass too, it looks good.

  • Add tests
  • Allow the user to choose it with alg

Closes #753

@github-actions

github-actions Bot commented Jun 21, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark Results (Julia v1)

Time benchmarks
master 4d76209... master / 4d76209...
BigFloat MPFI/basics/* 22.1 ± 3.8 μs 21.8 ± 3.9 μs 1.02 ± 0.25
BigFloat MPFI/basics/+ 12.5 ± 3.9 μs 12.7 ± 3.9 μs 0.981 ± 0.43
BigFloat MPFI/basics/- 13.2 ± 3.8 μs 13.3 ± 3.7 μs 0.989 ± 0.4
BigFloat MPFI/basics// 24.8 ± 8.8 μs 25.2 ± 7.9 μs 0.984 ± 0.47
BigFloat MPFI/basics/abs 9.84 ± 3.5 μs 9.89 ± 3.5 μs 0.995 ± 0.5
BigFloat MPFI/basics/acos 0.674 ± 0.01 ms 0.675 ± 0.01 ms 0.999 ± 0.021
BigFloat MPFI/basics/asin 0.662 ± 0.01 ms 0.664 ± 0.012 ms 0.998 ± 0.024
BigFloat MPFI/basics/atan 2.1 ± 0.012 ms 2.1 ± 0.0091 ms 1 ± 0.0072
BigFloat MPFI/basics/cos 0.241 ± 0.0093 ms 0.241 ± 0.0094 ms 1 ± 0.055
BigFloat MPFI/basics/cosh 0.432 ± 0.013 ms 0.432 ± 0.012 ms 0.999 ± 0.041
BigFloat MPFI/basics/exp 0.505 ± 0.012 ms 0.505 ± 0.012 ms 1 ± 0.032
BigFloat MPFI/basics/inv 17.2 ± 3.6 μs 17.6 ± 3.6 μs 0.981 ± 0.29
BigFloat MPFI/basics/log 0.473 ± 0.011 ms 0.471 ± 0.011 ms 1 ± 0.033
BigFloat MPFI/basics/sin 0.346 ± 0.011 ms 0.343 ± 0.011 ms 1.01 ± 0.045
BigFloat MPFI/basics/sinh 0.573 ± 0.01 ms 0.574 ± 0.011 ms 0.998 ± 0.026
BigFloat MPFI/basics/sqrt 23.1 ± 3.8 μs 22.7 ± 3.8 μs 1.02 ± 0.24
BigFloat MPFI/basics/tan 0.277 ± 0.0099 ms 0.275 ± 0.0099 ms 1 ± 0.051
BigFloat MPFI/basics/tanh 0.588 ± 0.01 ms 0.59 ± 0.011 ms 0.996 ± 0.025
BigFloat bareinterval/basics/* 0.0395 ± 0.0027 ms 0.0398 ± 0.0027 ms 0.992 ± 0.095
BigFloat bareinterval/basics/+ 22.5 ± 3.7 μs 23 ± 3.7 μs 0.977 ± 0.22
BigFloat bareinterval/basics/- 22.9 ± 3.8 μs 23.1 ± 3.7 μs 0.991 ± 0.23
BigFloat bareinterval/basics// 19.9 ± 5.4 μs 20 ± 5.4 μs 0.996 ± 0.38
BigFloat bareinterval/basics/abs 15.8 ± 3.5 μs 15.9 ± 3.5 μs 0.994 ± 0.31
BigFloat bareinterval/basics/acos 0.711 ± 0.014 ms 0.713 ± 0.014 ms 0.996 ± 0.028
BigFloat bareinterval/basics/asin 0.701 ± 0.015 ms 0.703 ± 0.015 ms 0.997 ± 0.029
BigFloat bareinterval/basics/atan 2.09 ± 0.013 ms 2.11 ± 0.012 ms 0.994 ± 0.0082
BigFloat bareinterval/basics/cos 0.44 ± 0.1 ms 0.423 ± 0.099 ms 1.04 ± 0.34
BigFloat bareinterval/basics/cosh 0.482 ± 0.014 ms 0.485 ± 0.013 ms 0.993 ± 0.039
BigFloat bareinterval/basics/exp 0.514 ± 0.012 ms 0.514 ± 0.012 ms 1 ± 0.032
BigFloat bareinterval/basics/inv 26.8 ± 3.6 μs 26.8 ± 3.7 μs 0.998 ± 0.19
BigFloat bareinterval/basics/log 0.509 ± 0.012 ms 0.507 ± 0.012 ms 1 ± 0.034
BigFloat bareinterval/basics/sin 0.578 ± 0.099 ms 0.564 ± 0.093 ms 1.03 ± 0.24
BigFloat bareinterval/basics/sinh 0.582 ± 0.012 ms 0.584 ± 0.012 ms 0.998 ± 0.029
BigFloat bareinterval/basics/sqrt 0.0328 ± 0.0026 ms 0.0324 ± 0.0025 ms 1.01 ± 0.11
BigFloat bareinterval/basics/tan 0.345 ± 0.063 ms 0.334 ± 0.014 ms 1.03 ± 0.19
BigFloat bareinterval/basics/tanh 0.597 ± 0.012 ms 0.599 ± 0.012 ms 0.997 ± 0.028
BigFloat interval/basics/* 0.0431 ± 0.013 ms 0.043 ± 0.013 ms 1 ± 0.42
BigFloat interval/basics/+ 17.1 ± 9.3 μs 18.7 ± 9.1 μs 0.913 ± 0.67
BigFloat interval/basics/- 16.9 ± 0.33 μs 17.3 ± 0.41 μs 0.977 ± 0.03
BigFloat interval/basics// 20.3 ± 0.37 μs 20.9 ± 0.47 μs 0.971 ± 0.028
BigFloat interval/basics/abs 15.8 ± 8.8 μs 15.8 ± 8.8 μs 0.997 ± 0.78
BigFloat interval/basics/acos 0.704 ± 0.041 ms 0.706 ± 0.04 ms 0.996 ± 0.08
BigFloat interval/basics/asin 0.69 ± 0.0091 ms 0.689 ± 0.011 ms 1 ± 0.02
BigFloat interval/basics/atan 2.1 ± 0.012 ms 2.17 ± 0.011 ms 0.966 ± 0.0073
BigFloat interval/basics/cos 0.345 ± 0.013 ms 0.334 ± 0.013 ms 1.03 ± 0.055
BigFloat interval/basics/cosh 0.466 ± 0.012 ms 0.467 ± 0.012 ms 0.999 ± 0.036
BigFloat interval/basics/exp 0.521 ± 0.0098 ms 0.521 ± 0.0095 ms 0.999 ± 0.026
BigFloat interval/basics/inv 22.6 ± 0.42 μs 22.1 ± 0.34 μs 1.02 ± 0.025
BigFloat interval/basics/log 0.503 ± 0.016 ms 0.502 ± 0.02 ms 1 ± 0.051
BigFloat interval/basics/sin 0.494 ± 0.013 ms 0.484 ± 0.013 ms 1.02 ± 0.04
BigFloat interval/basics/sinh 0.59 ± 0.011 ms 0.59 ± 0.011 ms 1 ± 0.027
BigFloat interval/basics/sqrt 0.0395 ± 0.011 ms 0.0406 ± 0.012 ms 0.973 ± 0.4
BigFloat interval/basics/tan 0.288 ± 0.012 ms 0.281 ± 0.013 ms 1.03 ± 0.063
BigFloat interval/basics/tanh 0.604 ± 0.01 ms 0.605 ± 0.0098 ms 0.999 ± 0.023
bareinterval/basics/* 1.63 ± 0.05 μs 1.63 ± 0.05 μs 1 ± 0.043
bareinterval/basics/+ 0.501 ± 0.02 μs 0.501 ± 0.04 μs 1 ± 0.089
bareinterval/basics/- 0.531 ± 0.04 μs 0.531 ± 0.011 μs 1 ± 0.078
bareinterval/basics// 1.27 ± 0.03 μs 1.26 ± 0.03 μs 1.01 ± 0.034
bareinterval/basics/abs 0.161 ± 0.011 μs 0.16 ± 0.01 μs 1.01 ± 0.093
bareinterval/basics/acos 2.71 ± 0.03 μs 2.71 ± 0.021 μs 1 ± 0.013
bareinterval/basics/asin 3 ± 0.03 μs 3.02 ± 0.021 μs 0.99 ± 0.012
bareinterval/basics/atan 13.3 ± 0.25 μs 13.2 ± 0.23 μs 1.01 ± 0.026
bareinterval/basics/cos 0.0926 ± 0.032 ms 0.0707 ± 0.004 ms 1.31 ± 0.45
bareinterval/basics/cosh 7.19 ± 0.04 μs 7.16 ± 0.021 μs 1 ± 0.0063
bareinterval/basics/exp 4.27 ± 0.05 μs 4.26 ± 0.05 μs 1 ± 0.017
bareinterval/basics/inv 1.16 ± 0.06 μs 1.05 ± 0.02 μs 1.1 ± 0.061
bareinterval/basics/log 5.65 ± 0.03 μs 1.93 ± 0.021 μs 2.92 ± 0.035
bareinterval/basics/sin 0.0916 ± 0.0083 ms 0.069 ± 0.0039 ms 1.33 ± 0.14
bareinterval/basics/sinh 9.99 ± 0.05 μs 9.96 ± 0.05 μs 1 ± 0.0071
bareinterval/basics/sqrt 1.27 ± 0.051 μs 1.16 ± 0.03 μs 1.1 ± 0.052
bareinterval/basics/tan 0.0515 ± 0.0045 ms 0.0394 ± 0.0026 ms 1.31 ± 0.14
bareinterval/basics/tanh 0.308 ± 0.01 ms 0.311 ± 0.0093 ms 0.991 ± 0.044
interval/basics/* 3.05 ± 0.09 μs 2.77 ± 0.08 μs 1.1 ± 0.045
interval/basics/+ 1.59 ± 0.08 μs 1.34 ± 0.06 μs 1.19 ± 0.08
interval/basics/- 1.61 ± 0.04 μs 1.36 ± 0.05 μs 1.18 ± 0.052
interval/basics// 1.99 ± 0.35 μs 1.81 ± 0.64 μs 1.1 ± 0.43
interval/basics/abs 0.351 ± 0.14 μs 0.341 ± 0.1 μs 1.03 ± 0.51
interval/basics/acos 3.34 ± 0.07 μs 3.41 ± 0.06 μs 0.979 ± 0.027
interval/basics/asin 3.54 ± 0.05 μs 3.55 ± 0.041 μs 0.997 ± 0.018
interval/basics/atan 13.2 ± 0.21 μs 11.9 ± 0.14 μs 1.11 ± 0.022
interval/basics/cos 0.0919 ± 0.031 ms 0.0701 ± 0.0037 ms 1.31 ± 0.45
interval/basics/cosh 8.92 ± 0.071 μs 8.91 ± 0.071 μs 1 ± 0.011
interval/basics/exp 4.82 ± 0.07 μs 4.82 ± 0.06 μs 1 ± 0.019
interval/basics/inv 1.64 ± 0.05 μs 1.58 ± 0.041 μs 1.04 ± 0.041
interval/basics/log 2.54 ± 0.07 μs 2.54 ± 0.069 μs 1 ± 0.039
interval/basics/sin 0.0911 ± 0.031 ms 0.069 ± 0.0037 ms 1.32 ± 0.46
interval/basics/sinh 10.6 ± 0.1 μs 10.6 ± 0.1 μs 0.996 ± 0.013
interval/basics/sqrt 1.67 ± 0.049 μs 1.61 ± 0.051 μs 1.04 ± 0.045
interval/basics/tan 0.0516 ± 0.0037 ms 0.0395 ± 0.002 ms 1.31 ± 0.11
interval/basics/tanh 0.305 ± 0.014 ms 0.308 ± 0.013 ms 0.991 ± 0.062
time_to_load 0.108 ± 0.0017 s 0.118 ± 0.0015 s 0.913 ± 0.018
Memory benchmarks
master 4d76209... master / 4d76209...
BigFloat MPFI/basics/* 0.332 k allocs: 17.7 kB 0.332 k allocs: 17.7 kB 1
BigFloat MPFI/basics/+ 0.302 k allocs: 16.5 kB 0.302 k allocs: 16.5 kB 1
BigFloat MPFI/basics/- 0.302 k allocs: 16.5 kB 0.302 k allocs: 16.5 kB 1
BigFloat MPFI/basics// 0.302 k allocs: 16.5 kB 0.302 k allocs: 16.5 kB 1
BigFloat MPFI/basics/abs 0.302 k allocs: 16.5 kB 0.302 k allocs: 16.5 kB 1
BigFloat MPFI/basics/acos 1.14 k allocs: 0.0407 MB 1.14 k allocs: 0.0407 MB 1
BigFloat MPFI/basics/asin 1.08 k allocs: 0.0417 MB 1.08 k allocs: 0.0417 MB 1
BigFloat MPFI/basics/atan 2.14 k allocs: 0.0543 MB 2.14 k allocs: 0.0543 MB 1
BigFloat MPFI/basics/cos 1.56 k allocs: 0.0425 MB 1.56 k allocs: 0.0425 MB 1
BigFloat MPFI/basics/cosh 0.759 k allocs: 0.0313 MB 0.759 k allocs: 0.0313 MB 1
BigFloat MPFI/basics/exp 0.902 k allocs: 0.036 MB 0.902 k allocs: 0.036 MB 1
BigFloat MPFI/basics/inv 0.302 k allocs: 16.5 kB 0.302 k allocs: 16.5 kB 1
BigFloat MPFI/basics/log 0.407 k allocs: 20.6 kB 0.407 k allocs: 20.6 kB 1
BigFloat MPFI/basics/sin 1.91 k allocs: 0.0536 MB 1.91 k allocs: 0.0536 MB 1
BigFloat MPFI/basics/sinh 0.915 k allocs: 0.0369 MB 0.915 k allocs: 0.0369 MB 1
BigFloat MPFI/basics/sqrt 0.302 k allocs: 16.5 kB 0.302 k allocs: 16.5 kB 1
BigFloat MPFI/basics/tan 1.65 k allocs: 0.0493 MB 1.65 k allocs: 0.0493 MB 1
BigFloat MPFI/basics/tanh 0.908 k allocs: 0.0362 MB 0.908 k allocs: 0.0362 MB 1
BigFloat bareinterval/basics/* 0.262 k allocs: 26 kB 0.262 k allocs: 26 kB 1
BigFloat bareinterval/basics/+ 0.202 k allocs: 20.4 kB 0.202 k allocs: 20.4 kB 1
BigFloat bareinterval/basics/- 0.202 k allocs: 20.4 kB 0.202 k allocs: 20.4 kB 1
BigFloat bareinterval/basics// 0.1 k allocs: 10.8 kB 0.1 k allocs: 10.8 kB 1
BigFloat bareinterval/basics/abs 0.199 k allocs: 20.1 kB 0.199 k allocs: 20.1 kB 1
BigFloat bareinterval/basics/acos 1.27 k allocs: 0.0692 MB 1.27 k allocs: 0.0692 MB 1
BigFloat bareinterval/basics/asin 1.17 k allocs: 0.0659 MB 1.17 k allocs: 0.0659 MB 1
BigFloat bareinterval/basics/atan 2.04 k allocs: 0.058 MB 2.04 k allocs: 0.058 MB 1
BigFloat bareinterval/basics/cos 2.58 k allocs: 0.196 MB 2.45 k allocs: 0.185 MB 1.06
BigFloat bareinterval/basics/cosh 1.01 k allocs: 0.0671 MB 1.01 k allocs: 0.0671 MB 1
BigFloat bareinterval/basics/exp 0.802 k allocs: 0.0397 MB 0.802 k allocs: 0.0397 MB 1
BigFloat bareinterval/basics/inv 0.198 k allocs: 20 kB 0.198 k allocs: 20 kB 1
BigFloat bareinterval/basics/log 0.616 k allocs: 0.0522 MB 0.616 k allocs: 0.0522 MB 1
BigFloat bareinterval/basics/sin 3.02 k allocs: 0.209 MB 2.9 k allocs: 0.197 MB 1.06
BigFloat bareinterval/basics/sinh 0.815 k allocs: 0.0407 MB 0.815 k allocs: 0.0407 MB 1
BigFloat bareinterval/basics/sqrt 0.26 k allocs: 25.8 kB 0.26 k allocs: 25.8 kB 1
BigFloat bareinterval/basics/tan 1.73 k allocs: 0.129 MB 1.67 k allocs: 0.124 MB 1.05
BigFloat bareinterval/basics/tanh 0.808 k allocs: 0.0399 MB 0.808 k allocs: 0.0399 MB 1
BigFloat interval/basics/* 0.263 k allocs: 26.8 kB 0.263 k allocs: 26.8 kB 1
BigFloat interval/basics/+ 0.203 k allocs: 21.2 kB 0.203 k allocs: 21.2 kB 1
BigFloat interval/basics/- 0.203 k allocs: 21.2 kB 0.203 k allocs: 21.2 kB 1
BigFloat interval/basics// 0.101 k allocs: 11.6 kB 0.101 k allocs: 11.6 kB 1
BigFloat interval/basics/abs 0.2 k allocs: 20.9 kB 0.2 k allocs: 20.9 kB 1
BigFloat interval/basics/acos 1.71 k allocs: 0.11 MB 1.71 k allocs: 0.11 MB 1
BigFloat interval/basics/asin 1.47 k allocs: 0.0944 MB 1.47 k allocs: 0.0944 MB 1
BigFloat interval/basics/atan 2.04 k allocs: 0.0593 MB 2.04 k allocs: 0.0594 MB 0.998
BigFloat interval/basics/cos 2.58 k allocs: 0.197 MB 2.45 k allocs: 0.186 MB 1.06
BigFloat interval/basics/cosh 1.01 k allocs: 0.0679 MB 1.01 k allocs: 0.0679 MB 0.999
BigFloat interval/basics/exp 0.803 k allocs: 0.0407 MB 0.803 k allocs: 0.0407 MB 1
BigFloat interval/basics/inv 0.199 k allocs: 20.8 kB 0.199 k allocs: 20.8 kB 1
BigFloat interval/basics/log 0.917 k allocs: 0.0805 MB 0.917 k allocs: 0.0805 MB 1
BigFloat interval/basics/sin 3.02 k allocs: 0.209 MB 2.9 k allocs: 0.198 MB 1.06
BigFloat interval/basics/sinh 0.816 k allocs: 0.0416 MB 0.816 k allocs: 0.0417 MB 0.996
BigFloat interval/basics/sqrt 0.714 k allocs: 0.0675 MB 0.714 k allocs: 0.0675 MB 1
BigFloat interval/basics/tan 1.73 k allocs: 0.13 MB 1.67 k allocs: 0.125 MB 1.05
BigFloat interval/basics/tanh 0.809 k allocs: 0.041 MB 0.809 k allocs: 0.041 MB 1
bareinterval/basics/* 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/+ 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/- 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics// 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/abs 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/acos 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/asin 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/atan 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/cos 0.806 k allocs: 0.0623 MB 0.56 k allocs: 0.0423 MB 1.47
bareinterval/basics/cosh 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/exp 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/inv 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/log 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/sin 0.806 k allocs: 0.0623 MB 0.56 k allocs: 0.0423 MB 1.47
bareinterval/basics/sinh 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/sqrt 2 allocs: 1.62 kB 2 allocs: 1.62 kB 1
bareinterval/basics/tan 0.416 k allocs: 0.0328 MB 0.29 k allocs: 23.1 kB 1.45
bareinterval/basics/tanh 1.03 k allocs: 0.0359 MB 1.03 k allocs: 0.0359 MB 1
interval/basics/* 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/+ 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/- 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics// 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/abs 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/acos 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/asin 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/atan 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/cos 0.807 k allocs: 0.0631 MB 0.561 k allocs: 0.0431 MB 1.46
interval/basics/cosh 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/exp 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/inv 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/log 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/sin 0.807 k allocs: 0.0631 MB 0.561 k allocs: 0.0431 MB 1.46
interval/basics/sinh 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/sqrt 3 allocs: 2.45 kB 3 allocs: 2.45 kB 1
interval/basics/tan 0.417 k allocs: 0.0336 MB 0.291 k allocs: 24 kB 1.44
interval/basics/tanh 1.03 k allocs: 0.0367 MB 1.03 k allocs: 0.0367 MB 1
time_to_load 0.2 k allocs: 11.8 kB 0.204 k allocs: 11.9 kB 0.984

@blegat

blegat commented Aug 21, 2026

Copy link
Copy Markdown
Author

@OlivierHnt kind reminder :)

@OlivierHnt

Copy link
Copy Markdown
Member

I have not forgotten but I do not know the math behind these algorithms so I need to find time to look into that.

Btw I put your fix to disambiguate mul! for Julia v1.10 in #775.

@OlivierHnt

Copy link
Copy Markdown
Member

It's already the end of October 🤦 Ok I will put on an alarm on this.

@OlivierHnt

OlivierHnt commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Ok so computing the extreme eigenvalues with the interval version of eigvals makes it rigorous unlike IntervalLinearAlgebra.jl.

CI is failing pretty badly now though because the export list in test/IntervalArithmetic.jl was not updated.

Dealing with LinearAlgebra.jl is always a mess in my experience because there are so many special type matrices and they keep changing the internal logic and dispatch...

Some comments

  1. The Rohn bounds use round-to-nearest: interval(λmin - ρ, λmax + ρ) --> interval(λmin, λmax) + interval(-ρ, ρ).

  2. NG flag on eigenvalues:

    • λ + μ*im --> complex(λ, μ).
    • For Symmetric input the values are never NG even when the input is.
  3. Conversion of rational to floats: 0.5 * (A + A') --> interval(T, 1//2) * (A + A').

  4. Also, on Julia ≥ 1.12, somehow eigen(::Symmetric/Hermitian) lets LinearAlgebra's sqrt, svd, etc. run on interval matrices which are not rigorous (e.g., sqrt(interval.([2 1 0; 1 2 0; 0 0 -2^-50]))).

  5. On Julia ≥ 1.13, eigen(Symmetric(A)) throws when the diagonal is not thin because the contraction runs on the wrapper: _eigen_contraction(A, …) --> _eigen_contraction(Matrix(A), …).

  6. Repeated midpoint eigenvalues (e.g. interval.([1 0; 0 1])) throw instead of falling back: inv(mid.(DF)) --> lu(mid.(DF); check = false), and return false when it fails (after fixing 1).

  7. Unbounded entries now throw instead of returning NaI.

I also feel like there is an issue with eigvals. It does not benefit from this change no, since it seems that it accepts alg but ignores it, no?

- Rohn bounds rounded outward
- propagate NG flag to eigenvalues, use complex(λ, μ)
- convert 1//2 to interval instead of 0.5
- block non-rigorous LinearAlgebra matrix functions of Symmetric/Hermitian interval matrices
- run the contraction on Matrix(A) for Symmetric/Hermitian wrappers
- fall back to Rohn when mid.(DF) is singular (repeated eigenvalues)
- return NaI for unbounded entries
- eigvals uses the alg keyword
- move tests to test/ext and update the export list
@blegat

blegat commented Nov 2, 2026

Copy link
Copy Markdown
Author

CI is passing now and it should have addressed your comments

Comment thread docs/src/manual/usage.md Outdated
Comment on lines +184 to +202
### Linear algebra

Interval matrices support standard linear algebra operations from the `LinearAlgebra`
standard library. The eigendecomposition (`eigen`, `eigvals`) uses several algorithms
that can be selected via the `alg` keyword argument:

- [`IntervalEigen`](@ref IntervalArithmetic.IntervalEigen) (default): tries the contraction mapping theorem first, falls back to the Rohn enclosure.
- [`IntervalEigenContraction`](@ref IntervalArithmetic.IntervalEigenContraction): contraction mapping only.
- [`IntervalEigenRohn`](@ref IntervalArithmetic.IntervalEigenRohn): Rohn eigenvalue enclosure.
- [`IntervalEigenHertz`](@ref IntervalArithmetic.IntervalEigenHertz): Hertz exact hull (exponential complexity).

All algorithms are subtypes of [`AbstractIntervalEigenAlg`](@ref IntervalArithmetic.AbstractIntervalEigenAlg).

```@repl usage
using LinearAlgebra
A = interval.([1.0 0.5; 0.5 2.0])
eigen(A)
eigen(A; alg = IntervalEigenRohn())
```

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be in the Interfaces part of the documentation?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also something is a little misleading. Gershgorin and the contraction argument are two different things.
It seems like IntervalEigen for eigvals means Gershgorin, or did I misunderstand?

function LinearAlgebra.eigvals!(A::AbstractMatrix{<:Interval}; permute::Bool=true, scale::Bool=true, sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby)
const _EigenAlg = IntervalArithmetic.AbstractIntervalEigenAlg

function LinearAlgebra.eigvals!(A::AbstractMatrix{<:Interval}; alg::_EigenAlg=IntervalArithmetic.IntervalEigen(), permute::Bool=true, scale::Bool=true, sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could use <:RealOrComplexI directly instead of also defining an other method below for complex interval, no?

function _eigvals(::IntervalArithmetic.IntervalEigen, A, permute, scale, sortby)
λ = _eigvals_gershgorin(A, permute, scale, sortby)
all(isbounded, λ) && return λ
return _eigvals(IntervalArithmetic.IntervalEigenRohn(), A, permute, scale, sortby)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rohn is always better than Gershgorin?
Should we take an intersection?

LinearAlgebra.eigen!(A; alg, permute, scale, sortby)

LinearAlgebra.eigen(A::_SymHermInterval; alg::_EigenAlg=IntervalArithmetic.IntervalEigen(), sortby::Union{Function,Nothing}=LinearAlgebra.eigsortby) =
LinearAlgebra.eigen!(Matrix(A); alg, sortby)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but here we can guarantee that the eigenvalues are real actually

Comment thread src/IntervalArithmetic.jl Outdated
IntervalEigenRohn

Rohn eigenvalue enclosure (fast, O(n³)). Returns a single interval enclosing all
eigenvalues and [`nai`](@ref) eigenvectors. Valid for any interval radius.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when called with eigen

Comment on lines +367 to +385
# matrix functions of `Symmetric` and `Hermitian` interval matrices
# note: the LinearAlgebra methods rely on `eigen`, but assume that the eigenvectors are
# orthonormal and that the eigenvalues are accurate up to roundoff errors (e.g. `sqrt`
# rounds slightly negative eigenvalues to zero), which is not rigorous

Base.exp(A::_SymHermInterval) = exp(Matrix(A))
Base.log(A::_SymHermInterval) = log(Matrix(A))

for f ∈ (:sqrt, :cbrt, :cis, :cos, :sin, :tan, :cosh, :sinh, :tanh, :acos, :asin, :atan, :acosh, :asinh, :atanh, :sincos)
@eval Base.$f(::_SymHermInterval; kwargs...) = _throw_matrix_function($f)
end

Base.:^(A::_SymHermInterval, p::Integer) = Matrix(A)^p
Base.:^(A::_SymHermInterval, p::Real) = isinteger(p) ? Matrix(A)^Integer(p) : _throw_matrix_function(^)

LinearAlgebra.svd(::_SymHermInterval; full::Bool=false) = _throw_matrix_function(LinearAlgebra.svd)
LinearAlgebra.svdvals!(::_SymHermInterval) = _throw_matrix_function(LinearAlgebra.svdvals!)

_throw_matrix_function(f) = throw(ArgumentError("`$f` is not supported for `Symmetric` or `Hermitian` interval matrices"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these really needed? I did not try it but are these not already throwing an error?

- Intersect Gershgorin with Rohn in the default `eigvals`, as neither is
  always tighter, and use it as the fallback of the default `eigen`
- Fix Gershgorin: the discs are complex even for real matrices, and
  overlapping discs are merged into the hull of their connected component
- Only use the symmetric reduction of Rohn and Hertz for `Symmetric` and
  `Hermitian` wrappers, as a plain matrix with symmetric entries contains
  non-symmetric matrices
- Return real eigenvalues for real symmetric and Hermitian wrappers
- Fix the similarity transform for complex Hermitian midpoint matrices
- Merge the real and complex `eigvals!` methods
- Remove the `svdvals!` override, which is rigorous since it relies on `eigvals`
- Move the linear algebra docs to a new Interfaces page

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants