diff --git a/src/HalfIntegers.jl b/src/HalfIntegers.jl index 6c2acea..42812a9 100644 --- a/src/HalfIntegers.jl +++ b/src/HalfIntegers.jl @@ -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) @@ -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 : @@ -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 @@ -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) @@ -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) @@ -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 diff --git a/test/customtypes.jl b/test/customtypes.jl index f71caea..a2617df 100644 --- a/test/customtypes.jl +++ b/test/customtypes.jl @@ -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 @@ -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