Repository navigation
pow : les contournements de l'ancien CORE-MATH retirés, la puissance minuscule de |y| ≥ 2^1013 gardée - #213
Merged
Merged
Conversation
…y power kept from 2^1013
….md and the manual
Jordan08
added a commit
that referenced
this pull request
Oct 27, 2026
This was referenced Oct 27, 2026
Jordan08
added a commit
that referenced
this pull request
Oct 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Point PH.1 de
TODO.md: « après un import d'un CORE-MATH d'aprèsc01f08c5, retirer le contournement du<decr_pow(pow_rounded_up()etpow_rounded_dn()». L'import du 27 octobre (0b2ae6d1,cb731c0) a repris ce commit amont. La pull request retire degaol/core/gaol_interval_core.cppce que le commit rend inutile, et garde une seule puissance calculée à part, pour un autre défaut decr_pow()quec01f08c5ne corrige pas.Le défaut, reproduit
cr_pow()met son approximation de log(x) à NaN exprès pour |y| < 2^-969 et pour |y| ≥ 2^1014 (l'exposant deysous 0x36 ou à partir de 0x7f5), puis testaitrh * rh < 0x1p-1022pour effacer un sous-dépassement parasite. Deux défauts en sortaient :<d'un NaN lève l'exception d'opération invalide (pow([1, 2], [1e-300])tuait un programme qui l'avait activée) ;FE_OVERFLOWpour une puissance qui s'annule.c01f08c5(patch d'Erik Enikeev, 5 octobre, pour un sous-dépassement parasite) teste l'exposant derh(((_rh.u >> 52) & 0x7ff) < 0x200) : ni NaN comparé, ni carré. GAOL calculait ces puissances lui-même (1 + 2^-52, 1, +oo ou 2^-1074).Reproduit avec le
pow.cd'avant l'import et celui d'après, compilés comme GAOL le fait (-O2 -frounding-math -ffp-contract=off), sur 20 exposants de grandeur extrême, 14 bases, les deux signes et les quatre arrondis (2 240 appels) : mêmes valeurs bit à bit ; avec Clang 18 et 21 et avec GCC-O0, l'ancien lève l'invalidité 616 fois et le débordement 664 fois, le nouveau 0 et 576 (ceux d'un vrai débordement) ; avec GCC-O2l'ancien ne lève rien d'anormal (cause non cherchée). La CI a des jobs Clang et Debug : c'est là que le défaut se voit.Ce que la pull request change
pow_rounded_up()ne calcule plus à part les exposants de grandeur extrême (|y| < 2^-969 et |y| ≥ 2^1014), ni les puissances inférieures à 1 pour |y| ≥ 2^450 ;pow_up_without_overflow_exception()n'a plus la branche det ≥ 1100; ils appellentcr_pow(). Le commentaire deroot_of_power_near()et ceux des tests disent ce qu'il en est.Ce qui reste, et pourquoi (un défaut de plus de
cr_pow())En retirant tout, la comparaison avec la base a montré 160 cas où
powlèveFE_OVERFLOWpour un résultat fini (pow([2^-1074], [1.5·2^1014]),[0, 2^-1074]) :is_exact()decr_pow()calculey * e(e est l'exposant de x quand x est une puissance de 2 et y un entier) et ce produit déborde à partir de |y e| = 2^1024, c'est-à-dire pour |y| ≥ 2^1014 environ (|e| va jusqu'à 1 074). GAOL garde donc, danspow_rounded_up(), la seule puissance minuscule : pour x fini > 0 autre que 1, (x > 1) ≠ (y > 0) et |y| ≥ 2^1013, la puissance arrondie vers le haut est 2^-1074 (|y log x| ≥ 2^960). Ce défaut n'est pas dans3rd/README.md; il est à proposer en amont avec les autres (PH.1), sans envoi.Tests, et comment on montre qu'ils échouent sans le correctif
Les tests existants (
rounding_direction) couvraient déjà les deux défauts : les 13extreme_powersavecFE_INVALIDactivé, et 20 000 tirages par fonction depow,pow_rel,pow_exponent_relsansFE_OVERFLOWpour un résultat sans borne infinie.pow.cremis (arbre de la base, Clang 21) :rounding_directionéchoue, 1 899 vérifications sur 1 151 964 (invalidité, mort sur SIGFPE, débordement). Avec le nouveaupow.c: 1 151 964 vérifications, 0 échec.trap_cases()pour la puissance gardée (pow([2^-1074], [1.5 2^1014]),pow([2^-16], 2^1020),gaol_ieee1788::pow([2^-1000], [2^1013, 2^1020]), bornes[0, 2^-1074], avecFE_OVERFLOWactivé dans un processus enfant) : sans le raccourci gardé, les trois échouent (débordement, puis SIGFPE) ; avec lui, ils passent.pow(I, J),pow(I, double),pow_reletpow_exponent_reld'une grille d'opérandes extrêmes : 0 différence de borne ; 0 invalidité de part et d'autre (33 345 avec l'ancienpow.c) ;FE_OVERFLOWen plus dans 14 642 cas, tous avec une borne supérieure infinie (aucun avec une borne finie). La base ne levait pas le débordement de ces bornes infinies pour |y| ≥ 2^1014 ;doc/using.mddit queFE_OVERFLOWsignale une borne infinie.Pour
doc/differences.mdetChangeLog(pull request de synthèse)powd'un exposant de grandeur extrême ne lève plus l'invalidité (déjà dit) ; il est maintenant calculé par CORE-MATH, que l'amont a corrigé, sauf la puissance minuscule de |y| ≥ 2^1013.FE_OVERFLOWest levé, pour une borne supérieure infinie, avec |y| ≥ 2^1014 comme avec les autres exposants, etFE_UNDERFLOWpeut l'être pour une puissance minuscule finie que CORE-MATH calcule maintenant (la documentation ne promet rien sur le sous-dépassement).Relecture
Un relecteur indépendant (sous-agent, sans mon contexte) n'a trouvé aucun point bloquant. Il a construit la base et la branche avec Clang 21 et GCC 15 (
-O2,-O3et-O0en Debug), dans les quatre arrondis, avec les intervalles FPU et dans le conteneur Debian i386 (GCC 14.2), et comparé environ 9 millions de sorties depow(I, J),pow(I, double),gaol_ieee1788::pow,pow_rel,pow_exponent_rel,powRev1/2et des puissances entières au-delà desint, sur une grille de 70 bases et 140 exposants, 800 000 paires de boîtes et 3 millions de tirages proches des seuils :-O0comme-O2, FPU comme SSE2 ;FE_OVERFLOWen plus seulement quand le résultat a une borne infinie ;FE_UNDERFLOWen plus sur des résultats finis minuscules (CORE-MATH les calcule maintenant) ; aucunFE_INVALIDniFE_DIVBYZEROde plus, aucunFE_OVERFLOWpour un résultat fini, aucun indicateur en moins ;pow.c(Clang 21),rounding_directionéchoue 1 899 fois (invalidité et mort sur SIGFPE pour 11 des 13extreme_powers, débordements dans les tirages) ; sans le raccourci gardé, seuls les 3 cas nouveaux échouent, chacun deux fois ; sur la branche ils passent ;is_exact()ne déborde qu'à partir de |y| ≥ 2^1013,93, donc 2^1013 suffit, et le raccourci est juste pour les deux signes de y.Corrigé à sa demande : le commentaire de
root_of_power_near()(inexact sur 1/y), la précision que le raccourci est une borne supérieure, non la valeur arrondie, pour y infini (la base faisait de même ;root_of_power_near()n'en fait qu'un point de départ), une référence croisée entrepow_rounded_up()etpow_up_without_overflow_exception(), un commentaire périmé detests/ieee1788.cppet la phrase dedoc/using.mdet du manuel. Il doutait de la date du 5 octobre pourc01f08c5(il n'a pas pu consulter l'amont) : je l'ai relue dans un clone de CORE-MATH, 5 octobre 2026 à 15 h 08.Il note un risque résiduel : le chemin NaN de CORE-MATH est de nouveau atteint pour |y| < 2^-969 et |y| ≥ 2^1014, et sur un compilateur qui rend signalante une comparaison silencieuse (if-conversion de GCC sur ARM 32 bits et POWER9, GCC 9 vectorisé) il pourrait lever l'invalidité ; les 13
extreme_powers(indicateur et enfant sous SIGFPE) le diront sur ces jobs.Vérifié en local
Suite complète (
ctest),-Wall -Wextra -Werror: GCC 15.2 SSE2 (61 tests, avec les exemples), FPU (58), Clang 18 (61), GCC Debug avec ASan et UBSan (61) ; Clang 21 (45, sans les exemples).rounding_direction: 1 151 964 vérifications, 0 échec. Le manuel se construit (deux passes depdflatex, 0 erreur) avec le seul « Overfull » qu'avait la base. Aucun fichier de build ne change : autotools et meson n'ont pas été relancés.Non vérifiable ici : Visual C++ (
/fp:strict,/W4 /WX), clang-cl, MinGW-w64, MSYS2, macOS, ARM 32 bits, POWER, s390x, RISC-V et GCC 9 : seule la CI les couvre, et c'est elle qui dira le risque ci-dessus.Dépendances
Aucune. L'import de CORE-MATH
0b2ae6d1(cb731c0) est déjà dansconfigure-clean.Questions ouvertes
is_exact(): à écrire dans3rd/README.mdet à proposer à l'amont avec À communiquer à CORE-MATH : correctifs, défauts et proposition (regroupe #65, #66, #102, #104) #125 ? (rien n'est envoyé.)is_exact().