回答:
この議論は、PETScリストで何度も取り上げられていると思います。私の主な理由は次のとおりです。
C ++標準では、std :: complexは、float、double、およびlong doubleデータ型に対してのみ定義されています。したがって、4倍精度などの他のデータ型には使用できません。
この規格は、複雑な算術演算の安定性については保証しません。
標準では、std :: complex内のデータが実数コンポーネントとそれに続く虚数コンポーネントとして格納されることを保証しません。これは、BLASやLAPACKなどの外部ライブラリとのインターフェースにとって重要です。それはすべての主要な実装に当てはまりますが、私はそれを保証できることを望みます。
実数成分と虚数成分を直接操作できることを好みます。std :: complexはこれを不必要に難しくします。
最終的には、フィールドを必要とするのではなく、データ型がリングである必要があるだけのより一般的なバージョンが欲しいです。これには、ガウス整数が含まれます。
私std::complex<>
は自分のプログラムで使用していますが、新しいコンパイラーまたはコンパイラーのアップグレードごとに、コンパイラーのフラグと回避策と戦わなければなりません。私はこれらの戦いを時系列に数えてみよう:
std::norm
がオーバーフローを回避する方法で)を、結果を2乗したことがわかりました。この問題は、コンパイルフラグで修正できます-ffast-math
。std::arg
特定の構成(特定のgccバージョンとのリンク互換性)で非optにコンパイルされたLinux(またはリンカー)上のインテルiccコンパイラー。問題は頻繁に表面化しすぎたためstd::arg
、に置き換える必要がありましたatan2(imag(),real())
。しかし、新しいコードを書くときにこれを忘れるのはとても簡単でした。std::complex
は、組み込みのC99複合型、および新しいgccバージョンの組み込みのFortran複合型とは異なる呼び出し規則(= ABI)を使用します。-ffast-math
予期しない方法での浮動小数点例外の処理とコンパイルフラグが相互作用。何が起こるかというと、コンパイラーは除算をループから引き出し、それによってdivision by zero
実行時に例外を引き起こします。これらの例外は、対応する分割が周囲のロジックのために行われなかったため、ループ内では発生しませんでした。浮動小数点例外処理(異なるコンパイルフラグを使用)を使用するプログラムとは別にコンパイルされ、これらの問題に遭遇する(対応するチームは世界の反対側に座っていたので、この問題は本当にひどいトラブルを引き起こしました)。これは、コンパイラーが使用する最適化を手動でより注意して行うことで解決されました。-ffast-math
コンパイルフラグを使用しなくなりました。新しいgccバージョンへのアップグレード後、パフォーマンスが大幅に低下しました。この問題についてはまだ詳しく調査していませんが、C99 Annex Gに関連しているのではないかと心配しています。私は複素数の乗算のこの奇妙な定義に完全に混乱していることを認めざるを得ず、他のバージョンが誤っていると主張するこのバージョンの異なるバージョンが存在するようです。この新しいgccバージョンに-fcx-limited-range
関連する別の問題があるように思えるので、コンパイルフラグが問題を解決することを願っています-ffast-math
。-ffast-math
コンパイルフラグの挙動になりNaN
GCCの新しいバージョン(でものために完全に予測できないisnan
影響されます)。唯一の回避策NaN
は、プログラム内でのの発生を回避することであるように思われ、これはの存在の目的を無効にしNaN
ます。ここでstd::complex
、これらの理由により、組み込みの複合型を放棄する予定があるかどうかを尋ねることができます。C ++を使用する限り、組み込み型を使用します。C ++が科学計算で完全に使用できなくなった場合、科学計算に関連する問題をより注意深く処理する言語に切り替えることを検討します。
z
型の左辺値式であるCVstd::complex<T>
、その後はreinterpret_cast<cv T(&)[2]>(z)
とreinterpret_cast<cv T(&)[2]>(z)[0]
の実部を指定しなければならないz
、とreinterpret_cast<cv T(&)[2]>(z)[1]
の虚部を指定しなければなりませんz
。複素数の配列も扱われます。