Tôi sử dụng std::complex<>
trong các chương trình của mình và phải chiến đấu với cờ trình biên dịch và cách khắc phục cho mỗi trình biên dịch hoặc trình biên dịch mới. Tôi sẽ cố gắng kể lại những trận đánh này theo thứ tự thời gian:
std::norm
| z|2| z|-ffast-math
- Trình biên dịch intel icc trên linux (hoặc trình liên kết) được biên dịch
std::arg
thành không chọn theo các cấu hình nhất định (tương thích liên kết với một phiên bản gcc cụ thể). Vấn đề xuất hiện trở lại quá thường xuyên, do đó std::arg
phải được thay thế bằng atan2(imag(),real())
. Nhưng tất cả quá dễ dàng để quên điều này khi viết mã mới.
- Loại
std::complex
sử dụng các quy ước cuộc gọi khác nhau (= ABI) so với loại phức hợp C99 tích hợp và loại phức hợp Fortran tích hợp cho các phiên bản gcc mới hơn.
- Các
-ffast-math
tương tác cờ biên dịch với việc xử lý các trường hợp ngoại lệ điểm nổi theo những cách bất ngờ. Điều gì xảy ra là trình biên dịch kéo các bộ phận ra khỏi các vòng lặp, do đó gây ra division by zero
ngoại lệ khi chạy. Những ngoại lệ này sẽ không bao giờ xảy ra trong vòng lặp, bởi vì sự phân chia tương ứng đã không diễn ra do logic xung quanh. Đó là một điều thực sự tồi tệ, bởi vì đó là một thư viện được biên dịch tách biệt với chương trình sử dụng xử lý ngoại lệ dấu phẩy động (sử dụng các cờ biên dịch khác nhau) và gặp phải các vấn đề này (các đội tương ứng đang ngồi ở các khu vực đối diện trên thế giới, vì vậy vấn đề này thực sự gây ra rắc rối xấu). Điều này đã được giải quyết bằng cách thực hiện tối ưu hóa được sử dụng bởi trình biên dịch bằng tay cẩn thận hơn.
- Thư viện đã trở thành một phần của chương trình và không còn sử dụng
-ffast-math
cờ biên dịch. Sau khi nâng cấp lên phiên bản gcc mới hơn, hiệu suất giảm do yếu tố rất lớn. Tôi đã không điều tra vấn đề này một cách chi tiết, nhưng tôi sợ nó có liên quan đến C99 Phụ lục G . Tôi phải thừa nhận rằng tôi hoàn toàn bối rối với định nghĩa nhân số kỳ lạ này cho các số phức và thậm chí dường như còn tồn tại các phiên bản khác nhau của điều này với tuyên bố rằng các phiên bản khác bị nhầm lẫn. Tôi hy vọng rằng -fcx-limited-range
cờ biên dịch sẽ giải quyết vấn đề, bởi vì dường như có một vấn đề khác liên quan đến -ffast-math
phiên bản gcc mới hơn này.
- Các
-ffast-math
lá cờ biên dịch làm cho hành vi của NaN
hoàn toàn không thể đoán trước cho các phiên bản mới hơn của gcc (thậm chí isnan
bị ảnh hưởng). Cách giải quyết duy nhất dường như là để tránh mọi sự xuất hiện NaN
trong chương trình, đánh bại mục đích cho sự tồn tại của NaN
.
Bây giờ bạn có thể hỏi liệu tôi có kế hoạch từ bỏ các loại phức tạp tích hợp không và std::complex
vì những lý do này. Tôi sẽ ở lại với các loại tích hợp, miễn là tôi ở lại với C ++. Trong trường hợp C ++ nên quản lý để trở nên hoàn toàn không sử dụng được cho máy tính khoa học, tôi muốn xem xét chuyển sang một ngôn ngữ quan tâm nhiều hơn đến các vấn đề liên quan đến điện toán khoa học.
z
là một biểu thức vế trái của loại cvstd::complex<T>
sau đóreinterpret_cast<cv T(&)[2]>(z)
vàreinterpret_cast<cv T(&)[2]>(z)[0]
sẽ chỉ định một phần thực sự củaz
, vàreinterpret_cast<cv T(&)[2]>(z)[1]
sẽ chỉ định phần ảo củaz
. Mảng số phức cũng được giải quyết.