2016-01-02 1 views
1

J'ai écrit une petite bibliothèque (en C++ 11) pour calculer avec des quaternions, mais j'ai rapidement réalisé qu'il y a beaucoup de problèmes de précision/précision étant donné que quelques opérations en virgule flottante sont impliqués. Cela m'a conduit à regarder std :: complex et IEEE 754. std :: complex fait un bon travail sur les NaNs en particulier. Est-ce la seule chose dont j'ai besoin pour devenir "conforme à la norme IEEE 754"? Plus généralement, existe-t-il une «recette» pour transformer une bibliothèque numérique autrement naïve en une bibliothèque «conforme à la norme IEEE 754»?Comment rendre ma bibliothèque C++ compatible avec IEEE 754

Remarque: le problème est pas de savoir si le compilateur est IEEE 754, mais si je devais prendre des mesures spéciales dans mes propres algorithmes pour satisfaire IEEE 754. Après tout, je suis dans la même position que celui qui a écrit std :: complexe, et ils ont pris des mesures supplémentaires, par exemple pour NaNs.

+0

Note de côté: si vous tenez compte de la vitesse soyez au courant de [mauvaise performance de 'std :: complex'] (https://www.youtube.com/watch?v=he-XVt1xIE0) – Drop

+0

Merci! En effet, je prévois de rendre la conformité IEEE 754 optionnelle. Mais un papier d'Intel (bien sûr!) M'a averti des crashs de fusées et plus si ma lib n'était pas IEEE-754. – Frank

+0

Les opérations de quaternion (comme la multiplication) traitent souvent des sommes courantes des produits (signés). Vous pouvez regarder [Résumé Kahan] (https://en.wikipedia.org/wiki/Kahan_summation_algorithm) comme un moyen relativement peu coûteux d'améliorer la précision avec la conformité IEEE-754. Vous pourriez également envisager une mise en œuvre relativement mature comme la classe de quaternion de Boost. J'imagine que les concepts complexes comme les coupures de branches, etc., deviennent beaucoup plus étranges dans un sens théorique avec les quaternions, si vous voulez être cohérent. –

Répondre

1

Vous pouvez simplement vérifier votre tête de la bibliothèque <limits>numeric_limits::is_iec559 constante (CEI 559 est le même que IEEE 754) pour voir si oui ou non votre compilateur C++ prend déjà en charge IEEE 754.

+0

Paul - oui, en effet, mais cela ne semble pas être la fin de l'histoire. Si vous jetez un oeil à la bibliothèque std :: complex par exemple, il a du code pour gérer les NaNs - donc je pensais qu'en tant que programmeur, je devais ajouter du code similaire partout où mes algorithmes pouvaient produire des NaN. – Frank

0

Rendre l'IEEE conforme arithmétique est pas votre tâche mais celle du compilateur.

Votre compilateur est conforme ou non à la norme IEEE (@Paul) et vous ne pouvez rien y faire. Plus précisément, vous ne pouvez pas écrire un programme non conforme à la norme IEEE en utilisant un double arithmétique du compilateur conforme à la norme IEEE (veuillez ne pas me prendre au mot ici :)). Ceci est juste similaire à ce que vous pouvez difficilement écrire un programme non-ISO/IEC 14882: 2011-comliant avec un compilateur ISO/IEC 14882: 2011-comliant. Ceci ne garantit cependant pas que le programme donne une sortie attendue et qu'il est exempt d'opérations bizarres, y compris UB. Et cela est similaire à l'endroit où les NaN et les INF entrent en jeu dans IEEE 754. Ils sont là pour donner une "réponse raisonnable" aux opérations mathématiques mal définies telles que les opérations 0/0 ou hors limites telles que 1/0.

La norme ne se soucie pas de la façon dont vous traitez ces réponses dans votre bibliothèque (c'est-à-dire comment vous les traduisez à l'utilisateur lib). La norme ne spécifie qu'une manière d'utiliser ces "réponses raisonnables" dans une autre opération mathématique encore une autre "réponse raisonnable".

Vous pouvez être intéressé par http://perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf (lecture assez difficile, mais vaut la peine au moins pour saisir l'idée)

Ps J'ai vérifié ma lib < mise en œuvre complexe> (MinGW 4.9.1. 32bit) et n'a pas remarqué n'importe quelle magie de NaNS là.

+0

Si j'avais un dollar pour chaque fois que quelqu'un parlait de l'article de Goldberg comme dernier mot dans les questions à virgule flottante ... –

+0

@PavDub - archivez l'implémentation gcc de std :: complex. J'ai vu un code spécial pour NaNs là. J'ai aussi vu une présentation d'un Allemand qui se plaignait que ce traitement supplémentaire faisait que ses calculs - qu'il pourrait prouver ne donneraient jamais de NaN - étaient trop lents. – Frank

+0

@Frank I ** n'a pas ** parcouru l'implémentation complexe ligne par ligne mais n'a pas remarqué de trace de NaN à première vue. Pourriez-vous me poster votre mise en œuvre? Pas que je ne te croie pas mais je suis juste curieux ... (le mien est là: [link] (http://wikisend.org/)com/download/379378/complex.h)) – PavDub

0

[@Frank: commentaires ci-dessous ma dernière réponse 3 août à 07:38]

Lors de la multiplication des nombres comlex, NaN peut être un résultat de - en utilisant la notation de XCode iplementation à uploaded by @Frank - PasteBin:

__x is NaN if any of __a, __b, __c, __d is Nan or 
__ac == +INF && __bd == +INF or 
__ac == -INF && __bd == -INF or 
__a == (+/-)INF && __c == 0 or *vice versa* or 
__b == (+/-)INF && __d == 0 or *vice versa* or 

__y is NaN if any of __a, __b, __c, __d is Nan or 
__ad == -INF && __bc == +INF or 
__ad == +INF && __bc == -INF or 
__a == (+/-)INF && __d == 0 or *vice versa* or 
__b == (+/-)INF && __c == 0 or *vice versa* or 

ils (auteurs XCode STL) jouer avec ceux-ci pour tenir compte des cas tels que

(INF + INFi)*(c + di) 
(INF + INFi)*(0 + 0i) 
etc... 

l'astuce (le plus probable) est de définir le INFs- et N aNs contenant des valeurs soit de (+/-) 1 ou (+/-) 0 de sorte que le recalcul finale

if (__recalc) 
{ 
    __x = _Tp(INFINITY) * (__a * __c - __b * __d); 
    __y = _Tp(INFINITY) * (__a * __d + __b * __c); 
} 

des résultats dans

INF * (+/-)INF = (+/-)INF or 
INF * (+/-)0 = NaN 

selon le cas.

C'est le

comment vous les traduire à l'utilisateur lib

ps.> Je n'ai pas le temps d'aller si profondément dans le problème pour que je puisse juger de leur mise en œuvre, mais il est très probable raisonnable. (ce Math forum link est utile mais je ne suis d'aucun secours pour le traduire facilement en la notation numérique [a + bi]) Quoi qu'il en soit, MinGW 4.9.1. L'implémentation de 32bit Win laisse cette tâche ouverte et l'utilisateur doit traiter les cas de coin. Vous pouvez d'abord adopter la stratégie MinGW ou vous pouvez prendre celle de XCode si vous savez comment traiter correctement les cas d'angle de l'algèbre des quaterions. En tout cas ce n'est plus beaucoup sur Comment rendre ma bibliothèque C++ conforme à IEEE 754 ...

+0

donc c'était la genèse de ce fil: j'ai regardé ce qu'ils faisaient pour std :: complex, et ça m'a fait réfléchir à savoir si je devais gérer tous les cas qu'ils traitent dans mes propres opérations, et si cela devait être "conforme à la norme IEEE-754": je pensais que cette norme décrivait ce qui était attendu dans ces cas de coin - mon erreur alors. – Frank