Skip to content

Commit

Permalink
Enable rational conversion for types that cannot represent the number…
Browse files Browse the repository at this point in the history
… two (#49)

* change promotion in rational conversion

* Use twice in unsafe_rational

Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com>

* update other constructors

* Add test

* Update test/customtypes.jl

Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com>

---------

Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com>
  • Loading branch information
jishnub and sostock authored Mar 10, 2023
1 parent 215556a commit 82a8348
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/HalfIntegers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,19 @@ HalfInteger(x::BigFloat) = BigHalfInt(x)
if isinteger(x)
Base.unsafe_rational(tx >> 1, one(tx))
else
Base.unsafe_rational(tx, oftype(tx, 2))
Base.unsafe_rational(tx, twice(one(tx)))
end
end
function (::Type{Rational{T}})(x::HalfInteger) where T
tx = twice(x)
if isinteger(x)
Base.unsafe_rational(T, tx >> 1, one(tx))
else
Base.unsafe_rational(T, tx, oftype(tx,2))
Base.unsafe_rational(T, tx, twice(one(tx)))
end
end
else
(T::Type{<:Rational})(x::HalfInteger) = (tx=twice(x); T(tx,oftype(tx,2)))
(T::Type{<:Rational})(x::HalfInteger) = (tx=twice(x); T(tx,twice(one(tx))))
end

Base.ArithmeticStyle(::Type{<:HalfInteger}) = Base.ArithmeticWraps()
Expand Down
10 changes: 10 additions & 0 deletions test/customtypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ MyHalfInt(x::MyHalfInt) = x
HalfIntegers.half(::Type{MyHalfInt}, x) = MyHalfInt(half(HalfInt, x))
HalfIntegers.twice(x::MyHalfInt) = twice(x.val)

struct One <: Integer end
Base.promote_rule(::Type{One}, ::Type{T}) where {T<:Number} = promote_type(Bool, T)
Base.Int(::One) = 1
Base.iseven(::One) = false
Base.one(::One) = One()
Base.:+(x::One, y::One) = 2

@testset "Custom types" begin
@testset "Construction" begin
@test MyHalfInt(2.5) isa MyHalfInt
Expand All @@ -35,6 +42,9 @@ HalfIntegers.twice(x::MyHalfInt) = twice(x.val)
@test_throws InexactError Integer(MyHalfInt(3/2))
@test_throws InexactError Int(MyHalfInt(3/2))
@test_throws InexactError UInt(MyHalfInt(-1))

@test Rational(half(One())) == 1//2
@test Rational{Int}(half(One())) == 1//2
end

@testset "Properties" begin
Expand Down

2 comments on commit 82a8348

@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 also bump the version? Thanks!

@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 want merge #51 before the release, so that sign(half(Odd(1))) and denominator(half(Odd(1))) work as well. After that, I will make a release.

Please sign in to comment.