Skip to content

Commit

Permalink
add some methods for unary +, -, *, abs
Browse files Browse the repository at this point in the history
This is the first time that `abs` is implemented for `BigInt` and
`Rational`.

Fixes #237.
  • Loading branch information
nsajko committed Nov 28, 2023
1 parent 444331d commit 3fb2ec5
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/implementations/BigFloat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ function operate_to!(output::BigFloat, ::typeof(+), a::BigFloat, b::BigFloat)
return output
end

operate_to!(out::BigFloat, ::typeof(+), a::BigFloat) = operate_to!(out, copy, a)

operate!(::typeof(+), a::BigFloat) = a

# -

promote_operation(::typeof(-), ::Vararg{Type{BigFloat},N}) where {N} = BigFloat
Expand All @@ -101,13 +105,23 @@ function operate!(::typeof(-), x::BigFloat)
return x
end

function operate_to!(o::BigFloat, ::typeof(-), x::BigFloat)
operate_to!(o, copy, x)
return operate!(-, o)
end

# Base.abs

function operate!(::typeof(Base.abs), x::BigFloat)
x.sign = abs(x.sign)
return x
end

function operate_to!(o::BigFloat, ::typeof(abs), x::BigFloat)
operate_to!(o, copy, x)
return operate!(abs, o)
end

# *

promote_operation(::typeof(*), ::Type{BigFloat}, ::Type{BigFloat}) = BigFloat
Expand All @@ -125,6 +139,10 @@ function operate_to!(output::BigFloat, ::typeof(*), a::BigFloat, b::BigFloat)
return output
end

operate_to!(out::BigFloat, ::typeof(*), a::BigFloat) = operate_to!(out, copy, a)

operate!(::typeof(*), a::BigFloat) = a

# Base.fma

function promote_operation(
Expand Down
26 changes: 26 additions & 0 deletions src/implementations/BigInt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ function operate_to!(output::BigInt, ::typeof(+), a::BigInt, b::BigInt)
return Base.GMP.MPZ.add!(output, a, b)
end

operate_to!(out::BigInt, ::typeof(+), a::BigInt) = operate_to!(out, copy, a)

operate!(::typeof(+), a::BigInt) = a

# -

promote_operation(::typeof(-), ::Vararg{Type{BigInt},N}) where {N} = BigInt
Expand All @@ -52,6 +56,24 @@ function operate_to!(output::BigInt, ::typeof(-), a::BigInt, b::BigInt)
return Base.GMP.MPZ.sub!(output, a, b)
end

operate_to!(out::BigInt, ::typeof(-), a::BigInt) = Base.GMP.MPZ.neg!(out, a)

operate!(::typeof(-), a::BigInt) = operate_to!(a, -, a)

# abs

promote_operation(::typeof(abs), ::Type{BigInt}) = BigInt

function operate!(::typeof(abs), n::BigInt)
n.size = abs(n.size)
return n
end

function operate_to!(o::BigInt, ::typeof(abs), n::BigInt)
operate_to!(o, copy, n)
return operate!(abs, o)
end

# *

promote_operation(::typeof(*), ::Type{BigInt}, ::Type{BigInt}) = BigInt
Expand All @@ -60,6 +82,10 @@ function operate_to!(output::BigInt, ::typeof(*), a::BigInt, b::BigInt)
return Base.GMP.MPZ.mul!(output, a, b)
end

operate_to!(out::BigInt, ::typeof(*), a::BigInt) = operate_to!(out, copy, a)

operate!(::typeof(*), a::BigInt) = a

promote_operation(::typeof(div), ::Type{BigInt}, ::Type{BigInt}) = BigInt

function operate_to!(output::BigInt, ::typeof(div), a::BigInt, b::BigInt)
Expand Down
38 changes: 38 additions & 0 deletions src/implementations/Rational.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,38 @@ function operate_to!(output::Rational, ::typeof(+), x::Rational, y::Rational)
return output
end

function operate_to!(out::Q, ::typeof(+), x::Q) where {Q<:Rational}
return operate_to!(out, copy, x)
end

operate!(::typeof(+), x::Rational) = x

function operate_to!(out::Q, ::typeof(-), x::Q) where {Q<:Rational}
operate_to!(out.num, -, x.num)
operate_to!(out.den, copy, x.den)
return out
end

function operate!(::typeof(-), x::Rational)
operate!(-, x.num)
return x
end

# abs

promote_operation(::typeof(abs), ::Type{Q}) where {Q<:Rational} = Q

function operate!(::typeof(abs), x::Rational)
operate!(abs, x.num)
return x
end

function operate_to!(o::Q, ::typeof(abs), x::Q) where {Q<:Rational}
operate_to!(o.num, abs, x.num)
operate_to!(o.den, copy, x.den)
return o
end

# *

function promote_operation(
Expand Down Expand Up @@ -174,6 +206,12 @@ function operate_to!(output::Rational, ::typeof(*), x::Rational, y::Rational)
)
end

function operate_to!(out::Q, ::typeof(*), x::Q) where {Q<:Rational}
return operate_to!(out, copy, x)
end

operate!(::typeof(*), x::Rational) = x

# gcd

function promote_operation(
Expand Down
23 changes: 23 additions & 0 deletions test/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,26 @@ end
y = MA.operate!!(MA.add_mul, z, 2.4, LinearAlgebra.Diagonal(1:2))
@test y == LinearAlgebra.Diagonal(2.4 * (1:2))
end

@testset "unary op(::$T)" for T in (
Float64,
BigFloat,
Int,
BigInt,
Rational{Int},
Rational{BigInt},
)
@test MA.operate!!(+, T(7)) == 7
@test MA.operate!!(*, T(7)) == 7
@test MA.operate!!(-, T(7)) == -7

@test MA.operate_to!!(T(6), +, T(7)) == 7
@test MA.operate_to!!(T(6), *, T(7)) == 7
@test MA.operate_to!!(T(6), -, T(7)) == -7

@test MA.operate!!(abs, T(7)) == 7
@test MA.operate!!(abs, T(-7)) == 7

@test MA.operate_to!!(T(6), abs, T(7)) == 7
@test MA.operate_to!!(T(6), abs, T(-7)) == 7
end

0 comments on commit 3fb2ec5

Please sign in to comment.