Skip to content

Commit

Permalink
Merge 3247893 into c88b584
Browse files Browse the repository at this point in the history
  • Loading branch information
blegat committed Nov 19, 2019
2 parents c88b584 + 3247893 commit 59f8d88
Show file tree
Hide file tree
Showing 11 changed files with 868 additions and 6 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ os:
- linux
- osx
julia:
- 1.0
- 1.1
- 1.2
- 1.3
- nightly
matrix:
allow_failures:
Expand Down
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
julia = "1.1"

[extras]
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]
test = ["Test", "OffsetArrays", "SparseArrays"]
11 changes: 11 additions & 0 deletions src/MutableArithmetics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,25 @@ module MutableArithmetics
# slowdown because it compiles something that works for any `N`. See
# https://github.com/JuliaLang/julia/issues/32761 for details.

# `copy(::BigInt)` and `copy(::Array)` does not copy its elements so we need `deepcopy`.
mutable_copy(x) = deepcopy(x)

include("interface.jl")
include("shortcuts.jl")

# Test that can be used to test an implementation of the interface
include("Test/Test.jl")

# Implementation of the interface for Base types
import LinearAlgebra
const Scaling = Union{Number, LinearAlgebra.UniformScaling}
include("bigint.jl")
include("linear_algebra.jl")

isequal_canonical(a, b) = a == b

include("rewrite.jl")

include("dispatch.jl")

end # module
16 changes: 14 additions & 2 deletions src/bigint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,22 @@ promote_operation(::typeof(+), ::Vararg{Type{BigInt}, N}) where {N} = BigInt
function mutable_operate_to!(output::BigInt, ::typeof(+), a::BigInt, b::BigInt)
return Base.GMP.MPZ.add!(output, a, b)
end
#function mutable_operate_to!(output::BigInt, op::typeof(+), a::BigInt, b::LinearAlgebra.UniformScaling)
# return mutable_operate_to!(output, op, a, b.λ)
#end

# *
promote_operation(::typeof(*), ::Vararg{Type{BigInt}, N}) where {N} = BigInt
function mutable_operate_to!(output::BigInt, ::typeof(*), a::BigInt, b::BigInt)
return Base.GMP.MPZ.mul!(output, a, b)
end

function mutable_operate_to!(output::BigInt, op::Union{typeof(*), typeof(+)},
a::BigInt, b::BigInt, c::Vararg{BigInt, N}) where N
mutable_operate_to!(output, op, a, b)
return mutable_operate!(op, output, c...)
end

# add_mul
function mutable_operate_to!(output::BigInt, ::typeof(add_mul), args::Vararg{BigInt, N}) where N
return mutable_buffered_operate_to!(BigInt(), output, add_mul, args...)
Expand All @@ -30,6 +39,9 @@ function mutable_buffered_operate_to!(buffer::BigInt, output::BigInt, ::typeof(a
return mutable_operate_to!(output, +, a, buffer)
end

function mutable_operate_to!(output::BigInt, op::Function, a::Integer, b::Integer)
return mutable_operate_to!(output, op, convert(BigInt, a), convert(BigInt, b))
scaling_to_bigint(x::BigInt) = x
scaling_to_bigint(x::Number) = convert(BigInt, x)
scaling_to_bigint(J::LinearAlgebra.UniformScaling) = scaling_to_bigint(J.λ)
function mutable_operate_to!(output::BigInt, op::Function, args::Vararg{Scaling, N}) where N
return mutable_operate_to!(output, op, scaling_to_bigint.(args)...)
end
9 changes: 9 additions & 0 deletions src/dispatch.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
abstract type AbstractMutable end

# Special-case because the the base version wants to do fill!(::Array{AbstractVariableRef}, zero(GenericAffExpr{Float64,eltype(x)}))
_one_indexed(A) = all(x -> isa(x, Base.OneTo), axes(A))
function LinearAlgebra.diagm(x::AbstractVector{<:AbstractMutable})
@assert _one_indexed(x) # `LinearAlgebra.diagm` doesn't work for non-one-indexed arrays in general.
ZeroType = promote_operation(zero, eltype(x))
return LinearAlgebra.diagm(0 => copyto!(similar(x, ZeroType), x))
end
7 changes: 6 additions & 1 deletion src/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ function promote_operation end
function promote_operation(op::Function, args::Vararg{Type, N}) where N
return typeof(op(zero.(args)...))
end
promote_operation(::typeof(*), ::Type{T}) where {T} = T
function promote_operation(::typeof(*), ::Type{S}, ::Type{T}, ::Type{U}, args::Vararg{Type, N}) where {S, T, U, N}
return promote_operation(*, promote_operation(*, S, T), U, args...)
end

# Define Traits
abstract type MutableTrait end
Expand Down Expand Up @@ -40,7 +44,8 @@ function mutable_operate_to_fallback(::NotMutable, output, op::Function, args...
end

function mutable_operate_to_fallback(::IsMutable, output, op::Function, args...)
error("`mutable_operate_to!($op, $(args...))` is not implemented yet.")
error("`mutable_operate_to!($(typeof(output)), $op, ", join(typeof.(args), ", "),
")` is not implemented yet.")
end

"""
Expand Down
57 changes: 55 additions & 2 deletions src/linear_algebra.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,59 @@
import LinearAlgebra
mutability(::Type{<:Array}) = IsMutable()

mutability(::Type{<:Vector}) = IsMutable()
# Sum

function promote_operation(op::typeof(+), ::Type{Array{S, N}}, ::Type{Array{T, N}}) where {S, T, N}
return Array{promote_operation(op, S, T), N}
end
function mutable_operate!(::typeof(+), A::Array{S, N}, B::Array{T, N}) where{S, T, N}
for i in eachindex(A)
A[i] = operate!(+, A[i], B[i])
end
return A
end

# UniformScaling
function promote_operation(op::typeof(+), ::Type{Array{T, 2}}, ::Type{LinearAlgebra.UniformScaling{S}}) where {S, T}
return Array{promote_operation(op, T, S), 2}
end
function promote_operation(op::typeof(+), ::Type{LinearAlgebra.UniformScaling{S}}, ::Type{Array{T, 2}}) where {S, T}
return Array{promote_operation(op, S, T), 2}
end
function mutable_operate!(::typeof(+), A::Matrix, B::LinearAlgebra.UniformScaling)
n = LinearAlgebra.checksquare(A)
for i in 1:n
A[i, i] = operate!(+, A[i, i], B)
end
return A
end
function mutable_operate!(::typeof(add_mul), A::Matrix, B::Scaling, C::Scaling, D::Vararg{Scaling, N}) where N
return mutable_operate!(+, A, *(B, C, D...))
end
function mutable_operate!(::typeof(add_mul), A::Array{S, N}, B::Array{T, N}, α::Vararg{Scaling, M}) where {S, T, N, M}
for i in eachindex(A)
A[i] = operate!(add_mul, A[i], B[i], α...)
end
return A
end
function mutable_operate!(::typeof(add_mul), A::Array{S, N}, α::Scaling, B::Array{T, N}, β::Vararg{Scaling, M}) where {S, T, N, M}
for i in eachindex(A)
A[i] = operate!(add_mul, A[i], α, B[i], β...)
end
return A
end

# Product

function promote_operation(op::typeof(*), ::Type{Array{T, N}}, ::Type{S}) where {S, T, N}
return Array{promote_operation(op, T, S), N}
end
function promote_operation(op::typeof(*), ::Type{S}, ::Type{Array{T, N}}) where {S, T, N}
return Array{promote_operation(op, S, T), N}
end

function promote_operation(::typeof(*), ::Type{Matrix{S}}, ::Type{Vector{T}}) where {S, T}
return Vector{Base.promote_op(LinearAlgebra.matprod, S, T)}
end
function promote_operation(::typeof(*), ::Type{<:AbstractMatrix{S}}, ::Type{<:AbstractVector{T}}) where {S, T}
return Vector{Base.promote_op(LinearAlgebra.matprod, S, T)}
end
Expand Down
Loading

0 comments on commit 59f8d88

Please sign in to comment.