Skip to content

Commit 544c000

Browse files
authored
Release 1.0 (#728)
* Release 1.0 * Polish configuration system * Polish display of unbounded rational intervals * Fix test * Reintroduce `@interval` with two arguments and last cleanup * Fix docstrings * Fix `@interval` * Use `exact` instead of `ExactReal` as a constructor * Run tests on release candidates
1 parent 55d52b8 commit 544c000

21 files changed

+342
-373
lines changed

.github/workflows/CI.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ jobs:
1313
version:
1414
- '1.10'
1515
- '1'
16+
- 'pre'
1617
- 'nightly'
1718
os:
1819
- ubuntu-latest
@@ -25,8 +26,8 @@ jobs:
2526
- os: macOS-latest
2627
arch: x86
2728
steps:
28-
- uses: actions/checkout@v2
29-
- uses: julia-actions/setup-julia@v1
29+
- uses: actions/checkout@v4
30+
- uses: julia-actions/setup-julia@v2
3031
with:
3132
version: ${{ matrix.version }}
3233
arch: ${{ matrix.arch }}

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "IntervalArithmetic"
22
uuid = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253"
33
repo = "https://github.com/JuliaIntervals/IntervalArithmetic.jl.git"
4-
version = "0.23.0"
4+
version = "1.0.0"
55

66
[deps]
77
CRlibm = "96374032-68de-5a5b-8d9e-752f78720389"

ext/IntervalArithmeticLinearAlgebraExt.jl

Lines changed: 28 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ end
1313

1414
# contructor for `UniformScaling`
1515

16-
IntervalArithmetic.interval(::Type{T}, J::LinearAlgebra.UniformScaling, d::IntervalArithmetic.Decoration = com; format::Symbol = :infsup) where {T} =
17-
LinearAlgebra.UniformScaling(interval(T, J.λ, d; format = format))
18-
IntervalArithmetic.interval(J::LinearAlgebra.UniformScaling, d::IntervalArithmetic.Decoration = com; format::Symbol = :infsup) =
19-
LinearAlgebra.UniformScaling(interval(J.λ, d; format = format))
16+
IntervalArithmetic._interval_infsup(::Type{T}, J::LinearAlgebra.UniformScaling, H::LinearAlgebra.UniformScaling, d::IntervalArithmetic.Decoration) where {T<:IntervalArithmetic.NumTypes} =
17+
LinearAlgebra.UniformScaling(IntervalArithmetic._interval_infsup(T, J.λ, H.λ, d))
18+
19+
IntervalArithmetic._infer_numtype(J::LinearAlgebra.UniformScaling) = numtype(eltype(J))
20+
21+
IntervalArithmetic.exact(J::LinearAlgebra.UniformScaling) = LinearAlgebra.UniformScaling(exact(J.λ))
2022

2123
# by-pass generic `opnorm` from LinearAlgebra to prevent NG flag
2224

@@ -139,32 +141,22 @@ end
139141

140142
# matrix multiplication
141143

142-
function IntervalArithmetic.configure_matmul(matmul::Symbol)
143-
matmul (:slow, :fast) || return throw(ArgumentError("only the matrix multiplication mode `:slow` and `:fast` are available"))
144-
145-
@eval begin
146-
function LinearAlgebra.mul!(C::AbstractVector{<:RealOrComplexI}, A::AbstractVecOrMat, B::AbstractVector, α::Number, β::Number)
147-
size(A, 2) == size(B, 1) || return throw(DimensionMismatch("The number of columns of A must match the number of rows of B."))
148-
return IntervalArithmetic._mul!(IntervalArithmetic.MatMulMode{$(QuoteNode(matmul))}(), C, A, B, α, β)
149-
end
150-
151-
function LinearAlgebra.mul!(C::AbstractMatrix{<:RealOrComplexI}, A::AbstractVecOrMat, B::AbstractVecOrMat, α::Number, β::Number)
152-
size(A, 2) == size(B, 1) || return throw(DimensionMismatch("The number of columns of A must match the number of rows of B."))
153-
return IntervalArithmetic._mul!(IntervalArithmetic.MatMulMode{$(QuoteNode(matmul))}(), C, A, B, α, β)
154-
end
155-
end
156-
157-
return matmul
144+
function LinearAlgebra.mul!(C::AbstractVector{<:RealOrComplexI}, A::AbstractVecOrMat, B::AbstractVector, α::Number, β::Number)
145+
size(A, 2) == size(B, 1) || return throw(DimensionMismatch("The number of columns of A must match the number of rows of B."))
146+
return _mul!(IntervalArithmetic.default_matmul(), C, A, B, α, β)
158147
end
159148

160-
IntervalArithmetic.configure_matmul(:fast)
149+
function LinearAlgebra.mul!(C::AbstractMatrix{<:RealOrComplexI}, A::AbstractVecOrMat, B::AbstractVecOrMat, α::Number, β::Number)
150+
size(A, 2) == size(B, 1) || return throw(DimensionMismatch("The number of columns of A must match the number of rows of B."))
151+
return _mul!(IntervalArithmetic.default_matmul(), C, A, B, α, β)
152+
end
161153

162154
#
163155

164156
LinearAlgebra.mul!(C::AbstractVecOrMat{<:RealOrComplexI}, A::AbstractMatrix{<:RealOrComplexI}, B::AbstractVecOrMat{<:RealOrComplexI}) =
165157
LinearAlgebra.mul!(C, A, B, interval(true), interval(false))
166158

167-
function IntervalArithmetic._mul!(::IntervalArithmetic.MatMulMode{:slow}, C, A::AbstractMatrix, B::AbstractVecOrMat, α, β)
159+
function _mul!(::IntervalArithmetic.MatMulMode{:slow}, C, A::AbstractMatrix, B::AbstractVecOrMat, α, β)
168160
if iszero(α)
169161
if iszero(β)
170162
C .= zero(eltype(C))
@@ -221,14 +213,14 @@ end
221213
# fast matrix multiplication
222214
# Note: Rump's algorithm
223215

224-
function IntervalArithmetic._mul!(::IntervalArithmetic.MatMulMode{:fast}, C, A, B, α, β)
216+
function _mul!(::IntervalArithmetic.MatMulMode{:fast}, C, A, B, α, β)
225217
if Int == Int32
226218
@info "Fast multiplication is not supported on 32-bit systems, using the slow version"
227-
return IntervalArithmetic._mul!(IntervalArithmetic.MatMulMode{:slow}(), C, A, B, α, β)
219+
return _mul!(IntervalArithmetic.MatMulMode{:slow}(), C, A, B, α, β)
228220
else
229221
numtype(eltype(C)) <: Union{Float16,Float32,Float64} && return _fastmul!(C, A, B, α, β)
230222
@info "Fast multiplication is only supported for `Union{Float16,Float32,Float64}`, using the slow version"
231-
return IntervalArithmetic._mul!(IntervalArithmetic.MatMulMode{:slow}(), C, A, B, α, β)
223+
return _mul!(IntervalArithmetic.MatMulMode{:slow}(), C, A, B, α, β)
232224
end
233225
end
234226

@@ -413,11 +405,11 @@ function ___mul(A::AbstractMatrix{T}, B::AbstractVecOrMat{Interval{T}}) where {T
413405

414406
stride_A = _to_stride_64(A)
415407
stride_mB = _to_stride_64(mB)
416-
C₁ = IntervalArithmetic._sub_round.(
408+
C₁ = IntervalArithmetic._fround.(-,
417409
T.(_call_gem_openblas!(cache_2, stride_A, stride_mB, RoundDown), RoundDown),
418410
T.(rC, RoundUp),
419411
RoundDown)
420-
C₂ = cache_2; C₂ .= IntervalArithmetic._add_round.(
412+
C₂ = cache_2; C₂ .= IntervalArithmetic._fround.(+,
421413
T.(_call_gem_openblas!(cache_2, stride_A, stride_mB, RoundUp), RoundUp),
422414
T.(rC, RoundUp),
423415
RoundUp)
@@ -435,11 +427,11 @@ function ___mul(A::AbstractMatrix{Interval{T}}, B::AbstractVecOrMat{T}) where {T
435427

436428
stride_mA = _to_stride_64(mA)
437429
stride_B = _to_stride_64(B)
438-
C₁ = IntervalArithmetic._sub_round.(
430+
C₁ = IntervalArithmetic._fround.(-,
439431
T.(_call_gem_openblas!(cache_2, stride_mA, stride_B, RoundDown), RoundDown),
440432
T.(rC, RoundUp),
441433
RoundDown)
442-
C₂ = cache_2; C₂ .= IntervalArithmetic._add_round.(
434+
C₂ = cache_2; C₂ .= IntervalArithmetic._fround.(+,
443435
T.(_call_gem_openblas!(cache_2, stride_mA, stride_B, RoundUp), RoundUp),
444436
T.(rC, RoundUp),
445437
RoundUp)
@@ -455,76 +447,33 @@ function ___mul(A::AbstractMatrix{Interval{T}}, B::AbstractVecOrMat{Interval{T}}
455447
cache_2 = zeros(Float64, size(A, 1), size(B, 2))
456448

457449
absmA_rB = _call_gem_openblas!(cache_1, _to_stride_64(abs.(mA)), _to_stride_64(rB), RoundUp)
458-
U = rB; U .= IntervalArithmetic._add_round.(abs.(mB), rB, RoundUp)
450+
U = rB; U .= IntervalArithmetic._fround.(+, abs.(mB), rB, RoundUp)
459451
rA_U = _call_gem_openblas!(cache_2, _to_stride_64(rA), _to_stride_64(U), RoundUp)
460452

461453
cache_3 = zeros(Float64, size(A, 1), size(B, 2))
462454

463455
stride_mA = _to_stride_64(mA)
464456
stride_mB = _to_stride_64(mB)
465-
C₁ = IntervalArithmetic._sub_round.(
457+
C₁ = IntervalArithmetic._fround.(-,
466458
T.(_call_gem_openblas!(cache_3, stride_mA, stride_mB, RoundDown), RoundDown),
467-
IntervalArithmetic._add_round.(T.(absmA_rB, RoundUp), T.(rA_U, RoundUp), RoundUp),
459+
IntervalArithmetic._fround.(+, T.(absmA_rB, RoundUp), T.(rA_U, RoundUp), RoundUp),
468460
RoundDown)
469-
C₂ = cache_3; C₂ .= IntervalArithmetic._add_round.(
461+
C₂ = cache_3; C₂ .= IntervalArithmetic._fround.(+,
470462
T.(_call_gem_openblas!(cache_3, stride_mA, stride_mB, RoundUp), RoundUp),
471-
IntervalArithmetic._add_round.(T.(absmA_rB, RoundUp), T.(rA_U, RoundUp), RoundUp),
463+
IntervalArithmetic._fround.(+, T.(absmA_rB, RoundUp), T.(rA_U, RoundUp), RoundUp),
472464
RoundUp)
473465

474466
return C₁, C₂
475467
end
476468

477-
# function ___mul(A::AbstractMatrix{Interval{T}}, B::AbstractVecOrMat{Interval{T}}) where {T<:AbstractFloat}
478-
# k = size(A, 2)
479-
# u2 = eps(T) # twice the unit roundoff
480-
# @assert (2k + 2) * u2 ≤ 1
481-
482-
# mA, rA = _vec_or_mat_midradius(A)
483-
# mB, rB = _vec_or_mat_midradius(B)
484-
485-
# cache_1 = zeros(T, size(A, 1), size(B, 2))
486-
# cache_2 = zeros(T, size(A, 1), size(B, 2))
487-
# mC, μ = _fused_matmul!(cache_1, cache_2, mA, rA, mB, rB)
488-
489-
# γ = IntervalArithmetic._add_round.(IntervalArithmetic._mul_round.(convert(T, k + 1), eps.(μ), RoundUp), IntervalArithmetic._mul_round(IntervalArithmetic._inv_round(u2, RoundUp), floatmin(T), RoundUp), RoundUp)
490-
491-
# U = mA; U .= IntervalArithmetic._add_round.(abs.(mA), rA, RoundUp)
492-
# V = mB; V .= IntervalArithmetic._add_round.(abs.(mB), rB, RoundUp)
493-
494-
# cache_3 = zeros(Float64, size(A, 1), size(B, 2))
495-
# rC = IntervalArithmetic._add_round.(IntervalArithmetic._sub_round.(T.(_call_gem_openblas!(cache_3, _to_stride_64(U), _to_stride_64(V), RoundUp), RoundUp), μ, RoundUp), 2 .* γ, RoundUp)
496-
497-
# C₁ = μ; C₁ .= IntervalArithmetic._sub_round.(mC, rC, RoundDown)
498-
# C₂ = γ; C₂ .= IntervalArithmetic._add_round.(mC, rC, RoundUp)
499-
500-
# return C₁, C₂
501-
# end
502-
503-
# function _fused_matmul!(mC, μ, mA, rA, mB, rB)
504-
# Threads.@threads for j ∈ axes(mB, 2)
505-
# for l ∈ axes(mA, 2)
506-
# @inbounds for i ∈ axes(mA, 1)
507-
# a, c = mA[i,l], rA[i,l]
508-
# b, d = mB[l,j], rB[l,j]
509-
# e = sign(a) * min(abs(a), c)
510-
# f = sign(b) * min(abs(b), d)
511-
# p = a*b + e*f
512-
# mC[i,j] += p
513-
# μ[i,j] += abs(p)
514-
# end
515-
# end
516-
# end
517-
# return mC, μ
518-
# end
519-
520469
_to_stride_64(A::StridedArray{Float64}) = A
521470
_to_stride_64(A::StridedArray{<:AbstractFloat}) = Float64.(A, RoundUp)
522471
_to_stride_64(A::AbstractVector) = _to_stride_64(Vector(A))
523472
_to_stride_64(A::AbstractMatrix) = _to_stride_64(Matrix(A))
524473

525474
function _vec_or_mat_midradius(A::AbstractVecOrMat{Interval{T}}) where {T<:AbstractFloat}
526-
mA = IntervalArithmetic._div_round.(IntervalArithmetic._add_round.(inf.(A), sup.(A), RoundUp), convert(T, 2), RoundUp)
527-
rA = IntervalArithmetic._sub_round.(mA, inf.(A), RoundUp)
475+
mA = IntervalArithmetic._fround.(/, IntervalArithmetic._fround.(+, inf.(A), sup.(A), RoundUp), convert(T, 2), RoundUp)
476+
rA = IntervalArithmetic._fround.(-, mA, inf.(A), RoundUp)
528477
return mA, rA
529478
end
530479

0 commit comments

Comments
 (0)