ฉันใช้std::complex<>
ในโปรแกรมของฉันและต้องต่อสู้กับธงคอมไพเลอร์และวิธีแก้ปัญหาสำหรับคอมไพเลอร์ใหม่หรืออัพเกรดคอมไพเลอร์ ฉันจะพยายามนับการต่อสู้เหล่านี้ตามลำดับเวลา:
std::norm
| Z|2| Z|-ffast-math
- คอมไพเลอร์ intel icc บน linux (หรือตัวลิงก์) ที่คอมไพล์แล้ว
std::arg
ไปยังตัวเลือกที่ไม่ใช้ภายใต้การกำหนดค่าบางอย่าง ปัญหาเกิดซ้ำบ่อยเกินไปดังนั้นจึงstd::arg
ต้องถูกแทนที่ด้วย atan2(imag(),real())
แต่มันง่ายเกินไปที่จะลืมสิ่งนี้เมื่อเขียนรหัสใหม่
- ชนิดนี้
std::complex
ใช้ระเบียบการโทรที่แตกต่างกัน (= ABI) กว่าประเภทคอมเพล็กซ์ในตัว C99 และประเภทคอมเพล็กซ์ Fortran ในตัวสำหรับรุ่น gcc ที่ใหม่กว่า
- การ
-ffast-math
คอมไพล์ธงทำปฏิกิริยากับการจัดการข้อยกเว้นจุดลอยตัวในวิธีที่ไม่คาดคิด สิ่งที่เกิดขึ้นคือคอมไพเลอร์ดึงหน่วยงานออกจากลูปจึงทำให้เกิดdivision by zero
ข้อยกเว้นในขณะทำงาน ข้อยกเว้นเหล่านี้จะไม่เกิดขึ้นภายในลูปเนื่องจากส่วนที่เกี่ยวข้องไม่ได้เกิดขึ้นเนื่องจากตรรกะโดยรอบ อันนั้นแย่มากเพราะเป็นห้องสมุดที่รวบรวมแยกต่างหากจากโปรแกรมที่ใช้การส่งข้อยกเว้นจุดลอยตัว (ใช้ธงคอมไพล์ที่แตกต่างกัน) และพบปัญหาเหล่านี้ (ทีมที่เกี่ยวข้องกำลังนั่งอยู่ตรงข้ามส่วนหนึ่งของโลก) ปัญหานี้ทำให้เกิดปัญหาที่เลวร้ายจริงๆ) สิ่งนี้แก้ไขได้ด้วยการเพิ่มประสิทธิภาพที่คอมไพเลอร์ใช้ด้วยมืออย่างระมัดระวังมากขึ้น
- ไลบรารีกลายเป็นส่วนหนึ่งของโปรแกรมและไม่ใช้
-ffast-math
แฟล็กการคอมไพล์อีกต่อไป หลังจากอัปเกรดเป็น gcc รุ่นใหม่ประสิทธิภาพจะลดลงตามปัจจัยที่มีขนาดใหญ่ ฉันยังไม่ได้ตรวจสอบปัญหานี้ในรายละเอียด แต่ฉันกลัวว่ามันจะเกี่ยวข้องกับC99 ภาคผนวก G ฉันต้องยอมรับว่าฉันสับสนอย่างสมบูรณ์โดยคำจำกัดความที่แปลกประหลาดของการคูณสำหรับจำนวนเชิงซ้อนและดูเหมือนว่ามีอยู่ในรุ่นที่แตกต่างกันของเรื่องนี้โดยอ้างว่ารุ่นอื่นเข้าใจผิด ฉันหวังว่าการ-fcx-limited-range
รวบรวมการตั้งค่าสถานะจะแก้ปัญหาได้เนื่องจากมีปัญหาอื่นที่เกี่ยวข้องกับ-ffast-math
รุ่น gcc ที่ใหม่กว่านี้
- การ
-ffast-math
คอมไพล์แฟล็กทำให้พฤติกรรมNaN
ไม่สามารถคาดเดาได้อย่างสมบูรณ์สำหรับ gcc รุ่นใหม่ (แม้isnan
จะได้รับผลกระทบ) วิธีแก้ปัญหาเท่านั้นดูเหมือนว่าจะหลีกเลี่ยงการเกิดใด ๆในโปรแกรมซึ่งขัดแย้งกับวัตถุประสงค์สำหรับการดำรงอยู่ของNaN
NaN
ตอนนี้คุณอาจถามว่าฉันวางแผนที่จะละทิ้งประเภทที่ซับซ้อนในตัวและstd::complex
ด้วยเหตุผลเหล่านี้ ฉันจะอยู่กับประเภทในตัวตราบใดที่ฉันยังคงอยู่กับ C ++ ในกรณีที่ C ++ ควรจัดการให้ใช้ไม่ได้อย่างสมบูรณ์สำหรับการคำนวณทางวิทยาศาสตร์ฉันจะพิจารณาเปลี่ยนไปใช้ภาษาที่ดูแลปัญหาที่เกี่ยวข้องกับการคำนวณทางวิทยาศาสตร์มากขึ้น
z
คือการแสดงออก lvalue ชนิดพันธุ์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
อาร์เรย์ของตัวเลขที่ซับซ้อนจะได้รับการแก้ไขด้วย