Я використовую 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. Адресуються також масиви складних чисел.