Я використовую std::complex<>
у своїх програмах, і мені доводиться боротись із прапорами компілятора та способом вирішення кожного нового компілятора чи оновлення компілятора. Я спробую перерахувати ці поєдинки в хронологічному порядку:
- Вимірювання продуктивності показали, що крок, що включає лише обчислення площі абсолютного значення поля складних чисел, за gcc-4.x зайняв більше часу, ніж попередній FFT. Копання в сформованому коді асемблера показало, що
std::norm
( ) обчислювало абсолютне значення ( ) таким чином, щоб уникнути переповнення, а потім підкреслити результат. Цю проблему можна вирішити прапором компіляції .| z ||z|2|z|-ffast-math
- Компілятор Intel icc на linux (або linker) компілюється
std::arg
для не-вибору в певних конфігураціях (сумісність посилань із певною версією gcc). Проблема виникала занадто часто, тому її std::arg
довелося замінити на atan2(imag(),real())
. Але було занадто просто забути це, коли писав новий код.
- Тип
std::complex
використовує різні умови викликів (= ABI), ніж комплексний тип вбудованого C99, а вбудований комплексний тип Fortran для новіших версій gcc.
- У
-ffast-math
компіляції прапор взаємодіє з обробкою з плаваючою точкою виключення несподіваним чином. Що відбувається - компілятор витягує поділи з циклів, тим самим спричиняючи division by zero
винятки під час виконання. Ці винятки ніколи б не траплялися всередині циклу, оскільки відповідний поділ не відбувся через навколишню логіку. Це було дуже погано, оскільки це була бібліотека, яка була складена окремо від програми, яка використовувала передачу виключень із плаваючою комою (використовуючи різні прапорці компіляції) та натрапила на ці випуски (відповідні команди сиділи в різних частинах світу, так це питання справді спричинило погані неприємності). Це було вирішено, зробивши оптимізацію, яку використовував компілятор вручну, більш ретельно.
- Бібліотека стала частиною програми і більше не використовувала
-ffast-math
прапор компіляції. Після оновлення до новішої версії gcc продуктивність знизилася на величезний фактор. Я ще не детально досліджував це питання, але побоююсь, що він пов'язаний із додатком C99 C99 . Я мушу визнати, що мене цілком бентежить це дивне визначення множення на складні числа, і навіть, здається, існують різні версії цього з твердженнями, що інші версії помилково керуються. Я сподіваюся, що -fcx-limited-range
прапор компіляції вирішить проблему, тому що, здається, є ще одна проблема, пов’язана з -ffast-math
цією новою версією gcc.
-ffast-math
Прапор компіляції робить поведінку NaN
абсолютно непередбачуваним для нових версій GCC (навіть isnan
вражений). Здається, єдиним способом вирішення проблеми є уникнення будь-якої появи NaN
в програмі, яка перемагає мету існування NaN
.
Тепер ви можете запитати, чи я планую відмовитися від вбудованих складних типів і std::complex
з цих причин. Я залишатимусь із вбудованими типами, поки я залишаюся з C ++. У випадку, якщо C ++ вдасться стати абсолютно непридатним для наукових обчислень, я б вважав за краще перейти на мову, яка б більше піклувалася про питання, що стосуються наукових обчислень.
z
вираз значення lv значення типу cv,std::complex<T>
тоreinterpret_cast<cv T(&)[2]>(z)
іreinterpret_cast<cv T(&)[2]>(z)[0]
позначає реальну частинуz
, іreinterpret_cast<cv T(&)[2]>(z)[1]
позначає уявну частинуz
. Адресуються також масиви складних чисел.