flintlib / arb

Arb has been merged into FLINT -- use https://github.com/flintlib/flint/ instead
http://arblib.org/
GNU Lesser General Public License v2.1
457 stars 137 forks source link

Fix arb_pow for x just barely containing 0, y>0. #445

Closed postmath closed 1 year ago

postmath commented 1 year ago

I rearranged the existing code for negative exact large integers y a little; explanation follows. Of course I'm happy to undo this if you prefer.

This code interacts with the new branch in a slightly complicated way: if y is an exact small integer (or half integer), we want to keep using the existing code that calls arb_pow_fmpz_binexp, so the new code needs to come after that test. However, if y is an exact big negative integer, then the current code negates x if its midpoint is negative, which would screw up the new code if we inserted it after the block testing for arb_is_exact(y) && !arf_is_special(arb_midref(x)), keeping the latter unchanged. I assume we want to keep testing that condition only once (as in the original code), so instead of immediately negating x and calling _arb_pow_exp, I chose to instead just store the decision that x needs to be negated. Furthermore, in the original code, _arb_pow_exp takes a flag for negating the input, but the calling code has to negate the result if applicable; given that the decision now needs to be stored, I thought it a little cleaner to store both decisions in one variable and do both steps in _arb_pow_exp. That's what the sign_type is about.

The most obvious alternative would be to store the result of the test arb_is_exact(y) && !arf_is_special(arb_midref(x)) and mirror the original code a bit more closely, inserting the new code truly in between the two parts of the big if block. I'd be entirely happy to do it that way instead if you prefer.

fredrik-johansson commented 1 year ago

Looks good, thanks. The CI is failing for unrelated reasons, so I will merge this. Apologies for the delay.