Skip to content

Commit

Permalink
convert instead of constructor in twice (#52)
Browse files Browse the repository at this point in the history
* convert instead of constructor in twice

* Update tests to Half{One} constructor

* Update suggested calls

* Specialize one

Following the suggestion in
#52 (comment)
  • Loading branch information
jishnub authored Apr 24, 2023
1 parent f3661b8 commit 8ba7551
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 10 deletions.
22 changes: 12 additions & 10 deletions src/HalfIntegers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ HalfInteger(x::HalfInteger) = x
HalfInteger(x::Rational{T}) where T = Half{T}(x)
HalfInteger(x::BigFloat) = BigHalfInt(x)

(T::Type{<:AbstractFloat})(x::HalfInteger) = T(float(x))
(T::Type{<:AbstractFloat})(x::HalfInteger) = convert(T, float(x))
(T::Type{<:Integer})(x::HalfInteger) =
isinteger(x) ? T(twice(x) >> 1) : throw(InexactError(Symbol(T), T, x))
isinteger(x) ? convert(T, twice(x) >> 1) : throw(InexactError(Symbol(T), T, x))
(::Type{Bool})(x::HalfInteger) = invoke(Bool, Tuple{Real}, x)
@static if VERSION v"1.5.0-DEV.820"
function (::Type{Rational})(x::HalfInteger)
Expand Down Expand Up @@ -159,8 +159,8 @@ Base.floor(T::Type{<:Integer}, x::HalfInteger) = round(T, x, RoundDown)
Base.trunc(T::Type{<:Integer}, x::HalfInteger) = round(T, x, RoundToZero)

Base.round(T::Type{<:Integer}, x::HalfInteger, r::RoundingMode=RoundNearest) =
T(twice(round(x, r)) >> 1)
Base.round(T::Type{<:Integer}, x::HalfInteger, ::typeof(RoundDown)) = T(twice(x) >> 1)
convert(T, twice(round(x, r)) >> 1)
Base.round(T::Type{<:Integer}, x::HalfInteger, ::typeof(RoundDown)) = convert(T, twice(x) >> 1)

Base.round(x::HalfInteger, ::typeof(RoundNearest)) =
isinteger(x) ? +x :
Expand Down Expand Up @@ -245,11 +245,11 @@ function coschalf(x::Integer)
if xm4 == 0
2*x⁻¹
elseif xm4 == 1
(-4/T(π))*x⁻¹*x⁻¹
(-4/convert(T, π))*x⁻¹*x⁻¹
elseif xm4 == 2
-2*x⁻¹
else
(4/T(π))*x⁻¹*x⁻¹
(4/convert(T, π))*x⁻¹*x⁻¹
end
end

Expand Down Expand Up @@ -444,8 +444,8 @@ julia> twice(Complex{BigInt}, HalfInt(5/2) + HalfInt(3)*im)
5 + 6im
```
"""
twice(T::Type{<:Integer}, x::Number) = T(twice(x))
twice(T::Type{<:Integer}, x::Integer) = twice(T(x)) # convert to T first to reduce probability of overflow
twice(T::Type{<:Integer}, x::Number) = convert(T, twice(x))::T
twice(T::Type{<:Integer}, x::Integer) = twice(convert(T, x)::T) # convert to T first to reduce probability of overflow
twice(::Type{Complex{T}}, x::Number) where T<:Integer = Complex(twice(T,real(x)), twice(T,imag(x)))

function twice(T::Type{<:Integer}, x::Rational)
Expand Down Expand Up @@ -519,9 +519,9 @@ julia> onehalf(HalfInt)
"""
onehalf(x::Union{Number,Missing}) = onehalf(typeof(x))

onehalf(T::Type{<:Number}) = T(onehalf(HalfInteger))
onehalf(T::Type{<:Number}) = convert(T, onehalf(HalfInteger))
onehalf(T::Type{<:HalfInteger}) = half(T, 1)
onehalf(T::Type{<:AbstractFloat}) = T(0.5)
onehalf(T::Type{<:AbstractFloat}) = convert(T, 0.5)
@static if VERSION v"1.5.0-DEV.820"
onehalf(::Type{Rational}) = Base.unsafe_rational(1, 2)
onehalf(::Type{Rational{T}}) where T = Base.unsafe_rational(T, 1, 2)
Expand Down Expand Up @@ -668,4 +668,6 @@ const HalfUInt128 = Half{UInt128}

Base.float(::Type{BigHalfInt}) = BigFloat

Base.one(::Type{Half{T}}) where T = half(twice(one(T)))

end # module
7 changes: 7 additions & 0 deletions test/customtypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Base.iseven(::One) = false
Base.one(::One) = One()
Base.sign(::One) = One()
Base.:+(x::One, y::One) = 2
Base.convert(::Type{One}, x::Int) = x == 1 ? One() : error("can't convert $x to One")

@testset "Custom types" begin
@testset "Construction" begin
Expand Down Expand Up @@ -50,6 +51,12 @@ Base.:+(x::One, y::One) = 2
@test @inferred(denominator(half(One()))) == 2
@test @inferred(Rational(half(One()))) == 1//2
@test @inferred(Rational{Int}(half(One()))) == 1//2

@test Half{One}(half(One())) === half(One())
@test Half{One}(half(1)) === half(One())

@test one(half(One())) == 1
@test one(half(One())) * half(One()) == half(One())
end

@testset "Properties" begin
Expand Down

4 comments on commit 8ba7551

@jishnub
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@sostock Could you bump the patch version, so that this change is included? Thanks!

@jishnub
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Gentle bump @sostock

@sostock
Copy link
Owner

Choose a reason for hiding this comment

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

I will make a release later today, but I would make this a feature release (I don’t consider it a bugfix).

@sostock
Copy link
Owner

Choose a reason for hiding this comment

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

#53

Please sign in to comment.