Lo uso std::complex<>
en mis programas y tengo que luchar con los indicadores del compilador y la solución para cada nuevo compilador o actualización del compilador. Intentaré contar estas peleas en orden cronológico:
- Las mediciones de rendimiento mostraron que un paso que involucraba solo calcular el cuadrado del valor absoluto de un campo de números complejos tomó más tiempo que un FFT anterior para gcc-4.x. Excavar en el código ensamblador generado mostró que
std::norm
(El | zEl |2) calculó el valor absoluto (El | zEl |) evitando el desbordamiento, y luego cuadró el resultado. Este problema podría solucionarse mediante el indicador de compilación -ffast-math
.
- El compilador intel icc en linux (o enlazador) compilado
std::arg
a un no-opt bajo ciertas configuraciones (compatibilidad de enlace con una versión gcc específica). El problema resurgió con demasiada frecuencia, por lo que std::arg
tuvo que ser reemplazado por atan2(imag(),real())
. Pero fue demasiado fácil olvidar esto al escribir código nuevo.
- El tipo
std::complex
utiliza diferentes convenciones de llamada (= ABI) que el tipo complejo C99 integrado y el tipo complejo Fortran incorporado para las nuevas versiones de gcc.
- El
-ffast-math
indicador de compilación interactúa con el manejo de excepciones de punto flotante de maneras inesperadas. Lo que sucede es que el compilador extrae las divisiones de los bucles, lo que provoca division by zero
excepciones en tiempo de ejecución. Estas excepciones nunca habrían ocurrido dentro del ciclo, porque la división correspondiente no tuvo lugar debido a la lógica circundante. Esa fue realmente mala, porque era una biblioteca que se compiló por separado del programa que usaba la entrega de excepciones de punto flotante (usando diferentes indicadores de compilación) y se topaba con estos problemas (los equipos correspondientes estaban sentados en partes opuestas del mundo, así que Este problema realmente causó problemas graves). Esto se resolvió haciendo la optimización utilizada por el compilador a mano con más cuidado.
- La biblioteca se convirtió en parte del programa y ya no utilizó el
-ffast-math
indicador de compilación. Después de una actualización a una versión más nueva de gcc, el rendimiento se redujo en un factor enorme. Todavía no he investigado este problema en detalle, pero me temo que está relacionado con el Anexo G del C99 . Tengo que admitir que estoy completamente confundido por esta extraña definición de multiplicación para números complejos, e incluso parece que existen diferentes versiones de esto con afirmaciones de que las otras versiones están equivocadas. Espero que el -fcx-limited-range
indicador de compilación resuelva el problema, porque parece haber otro problema relacionado con -ffast-math
esta nueva versión de gcc.
- El
-ffast-math
indicador de compilación hace que el comportamiento sea NaN
completamente impredecible para las versiones más nuevas de gcc (incluso isnan
se ve afectado). La única solución parece ser evitar cualquier aparición NaN
en el programa, lo que anula el propósito de la existencia de NaN
.
Ahora puede preguntar si planeo abandonar los tipos complejos integrados y std::complex
por estas razones. Me quedaré con los tipos integrados, siempre y cuando me quede con C ++. En caso de que C ++ logre volverse completamente inutilizable para la informática científica, preferiría considerar cambiar a un lenguaje que se ocupe más de los problemas relevantes para la informática científica.
z
es una expresión de tipo lvalue cvstd::complex<T>
a continuación,reinterpret_cast<cv T(&)[2]>(z)
yreinterpret_cast<cv T(&)[2]>(z)[0]
designará la parte real dez
, yreinterpret_cast<cv T(&)[2]>(z)[1]
designará la parte imaginaria dez
. También se abordan las matrices de números complejos.