La plupart des bibliothèques C ++ les plus connues en science informatique telles que Eigen , Trilinos et deal.II utilisent l'objet de bibliothèque d'en-tête de modèle C ++ standard std::complex<>
, pour représenter des nombres à virgule flottante complexes.
Dans la réponse de Jack Poulson à une question sur les constructeurs par défaut, il souligne qu'il a sa propre implémentation std::complex
dans Elemental "pour un certain nombre de raisons". Quelles sont ces raisons? Quels sont les avantages et les inconvénients de cette approche?
la source
z
est une expression lvalue de type cvstd::complex<T>
alorsreinterpret_cast<cv T(&)[2]>(z)
etreinterpret_cast<cv T(&)[2]>(z)[0]
doit désigner la partie réelle dez
, etreinterpret_cast<cv T(&)[2]>(z)[1]
doit désigner la partie imaginaire dez
. Des tableaux de nombres complexes sont également traités.J'utilise
std::complex<>
dans mes programmes, et je dois me battre avec des drapeaux de compilateur et une solution de contournement pour chaque nouveau compilateur ou mise à niveau du compilateur. Je vais essayer de raconter ces combats par ordre chronologique:std::norm
-ffast-math
std::arg
en non-opt dans certaines configurations (compatibilité des liens avec une version spécifique de gcc). Le problème a refait surface trop souvent et a doncstd::arg
dû être remplacé paratan2(imag(),real())
. Mais il était trop facile d'oublier cela lors de l'écriture de nouveau code.std::complex
utilise des conventions d'appel différentes (= ABI) que le type complexe C99 intégré et le type complexe Fortran intégré pour les versions gcc plus récentes.-ffast-math
indicateur de compilation interagit avec la gestion des exceptions à virgule flottante de manière inattendue. Ce qui se passe, c'est que le compilateur extrait les divisions des boucles, provoquant ainsi desdivision by zero
exceptions lors de l'exécution. Ces exceptions ne se seraient jamais produites à l'intérieur de la boucle, car la division correspondante n'a pas eu lieu en raison de la logique environnante. Celui-là était vraiment mauvais, car c'était une bibliothèque qui était compilée séparément du programme qui utilisait la remise d'exception en virgule flottante (en utilisant différents drapeaux de compilation) et rencontrait ces problèmes (les équipes correspondantes étaient assis dans des parties opposées du monde, donc ce problème a vraiment causé de gros ennuis). Cela a été résolu en faisant l'optimisation utilisée par le compilateur à la main avec plus de soin.-ffast-math
indicateur de compilation. Après une mise à niveau vers une nouvelle version de gcc, les performances ont chuté d'un facteur énorme. Je n'ai pas encore étudié cette question en détail, mais je crains qu'elle soit liée à l' annexe G de la C99 . Je dois admettre que je suis complètement confus par cette étrange définition de la multiplication pour les nombres complexes, et il semble même exister différentes versions de cela avec des affirmations selon lesquelles les autres versions sont erronées. J'espère que l'-fcx-limited-range
indicateur de compilation résoudra le problème, car il semble y avoir un autre problème lié à-ffast-math
cette nouvelle version de gcc.-ffast-math
indicateur de compilation rend le comportement deNaN
complètement imprévisible pour les nouvelles versions de gcc (mêmeisnan
est affecté). La seule solution de contournement semble être d'éviter toute occurrence deNaN
dans le programme, ce qui va à l'encontre de l'objectif de l'existence deNaN
.Vous pouvez maintenant demander si je prévois d'abandonner les types complexes intégrés et
std::complex
pour ces raisons. Je vais rester avec les types intégrés, tant que je reste avec C ++. Dans le cas où le C ++ devrait réussir à devenir complètement inutilisable pour le calcul scientifique, je préférerais envisager de passer à un langage qui prend plus en charge les problèmes liés au calcul scientifique.la source