Skip to content

Conversation

@rfourquet
Copy link
Member

No description provided.

base/intfuncs.jl Outdated
function digits!{T<:Integer}(a::AbstractArray{T,1}, n::Integer, base::Integer=10)
2 <= base || throw(ArgumentError("base must be ≥ 2, got $base"))
base - 1 <= typemax(T) || throw(ArgumentError("type $T too small for base $base"))
!applicable(typemax, T) ||
Copy link
Member

Choose a reason for hiding this comment

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

why not applicable(typemax, T) && ...?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because then the second branch of the && must be parenthesized (one more character, you know!)

Copy link
Member Author

Choose a reason for hiding this comment

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

Would it be clearer if I change the test to:

applicable(typemax, T) &&
        base - 1 > typemax(T) && throw(ArgumentError("type $T too small for base $base"))

?

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure we really want to call applicable here: based on the @code_llvm it doesn't seem to be evaluated only at compile time. Unless anyone can think of something better, it might be better to just have T == BigInt || base-1 <= typemax(T) || ...

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, I didn't expect that to be a performance problem, but still it seems to be reasonable (of the order of 30 percent penalty for small numbers). I just tried with method_exists instead, but this is far worse. I don't like the T == BigInt solution, as it doesn't handle number types defined outside of Base.

Copy link
Member

Choose a reason for hiding this comment

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

See #16422. What do you mean by "far worse"?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah thanks, I had seen that one but totally forgot about it. As @timholy seemed to want it merged soon, I will update this PR using method_exists, and hope for the best. For now, this is one order of magnitude slower (for the digits of small numbers).

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that issue has a high chance of getting closed without merging, as @timholy noted in reply to Jameson's comments on its dangerous implementation.

Copy link
Member Author

Choose a reason for hiding this comment

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

OK so let's not hold our breath. I just tried a new version where I replace applicable by hastypemax defined as follows:

hastypemax{T<:Base.BitInteger}(::Type{T}) = true
hastypemax{T<:BigInt}(::Type{T}) = false
hastypemax(::Type{T}) = applicable(typemax, T)

The perfs seem to be similar to the base version, maybe few percents behind (hastypemax may be not removed at compilation time?). But it's a bit ugly, I'd rather wait for applicable (or method_exists) to be improved, and pay 30% penalty in the meantime. But if someone thinks it's important to preserve every bit of efficiency in digits!, I will update with this hastypemax function.

@rfourquet rfourquet added bignums BigInt and BigFloat bugfix This change fixes an existing bug labels May 23, 2017
@rfourquet
Copy link
Member Author

Related to #7501.

@rfourquet rfourquet force-pushed the rf/digits-big branch 2 times, most recently from d7d5736 to 078b81f Compare July 4, 2017 12:31
@rfourquet
Copy link
Member Author

I updated with the hastypemax solution (outlined above #16844 (comment)), which is the most conservative w.r.t. performances. This is a rather trivial fix, I will merge soon if no objection.

@StefanKarpinski
Copy link
Member

This is a bugfix, so it should be backportable; however, it does introduce a new internal trait. How do you feel about potentially backporting this, @tkelman?

@tkelman
Copy link
Contributor

tkelman commented Jul 11, 2017

None of the existing traits would cover this?

Copy link
Member

@Sacha0 Sacha0 left a comment

Choose a reason for hiding this comment

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

superficially lgtm (i.e. modulo @tkelman's hastypemaxquestion)! :)

@rfourquet
Copy link
Member Author

Rebased, to trigger an up-to-date build before merge :)
Also, I updated ::Type{<:BitInteger} to ::Union{Type{Int8}, ...}, similarly as was done in #22403.
@tkelman: I am not aware of an already existing trait covering this, do you have a hint were to look at?

@tkelman
Copy link
Contributor

tkelman commented Jul 12, 2017

Some of them are starting to get added in base/traits.jl - specifically here, would the existing uses of TypeArithmetic(::Type{<:Integer}) = ArithmeticOverflows() be more or less correct if BigInt was changed to a different value?

@rfourquet
Copy link
Member Author

would the existing uses of TypeArithmetic(::Type{<:Integer}) = ArithmeticOverflows() be more or less correct if BigInt was changed to a different value?

I think yes, partially. But as you say, this would require to change BigIngt like e.g. TypeArithmetic(::Type{BigInt}) = ArithmeticUnbounded(), which in turns needs to be taken into account in other places, like "range.jl". Also, this wouldn't directly handle the case of custom (unbounded) integer types, for which I call applicable here, unless the author specializes TypeArithmetic, which means the bug would not be totally fixed; so I'm a bit reluctant.

@rfourquet
Copy link
Member Author

Will merge within one or two days, if no objection.

@rfourquet rfourquet merged commit a2f4a05 into JuliaLang:master Jul 15, 2017
jeffwong pushed a commit to jeffwong/julia that referenced this pull request Jul 24, 2017
@nalimilan
Copy link
Member

This looks like another case where a trait would not really be needed if applicable/method_exists was resolved statically (#16422).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bignums BigInt and BigFloat bugfix This change fixes an existing bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants