@@ -142,23 +142,44 @@ struct DivideFunctor<ComplexType<T>> {
142142#endif
143143
144144 T real_, imag_;
145+
146+ auto rat = (abs_c >= abs_d) ? (d / c) : (c / d);
147+ auto scl =
148+ (abs_c >= abs_d) ? (T (1.0 ) / (c + d * rat)) : (T (1.0 ) / (d + c * rat));
145149 if (abs_c >= abs_d) {
146- if (abs_c == T (0 ) && abs_d == T (0 )) {
147- /* divide by zeros should yield a complex inf or nan */
148- real_ = a / abs_c;
149- imag_ = b / abs_d;
150+ #if __cplusplus >= 201703L
151+ if constexpr (std::is_same_v<T, float >) {
152+ real_ = std::fmaf (b, rat, a) * scl;
153+ imag_ = std::fmaf (-a, rat, b) * scl;
154+ } else if constexpr (std::is_same_v<T, double >) {
155+ real_ = std::fma (b, rat, a) * scl;
156+ imag_ = std::fma (-a, rat, b) * scl;
150157 } else {
151- auto rat = d / c;
152- auto scl = T (1.0 ) / (c + d * rat);
153158 real_ = (a + b * rat) * scl;
154159 imag_ = (b - a * rat) * scl;
155160 }
161+ #else
162+ real_ = (a + b * rat) * scl;
163+ imag_ = (b - a * rat) * scl;
164+ #endif
156165 } else {
157- auto rat = c / d;
158- auto scl = T (1.0 ) / (d + c * rat);
166+ #if __cplusplus >= 201703L
167+ if constexpr (std::is_same_v<T, float >) {
168+ real_ = std::fmaf (a, rat, b) * scl;
169+ imag_ = std::fmaf (b, rat, -a) * scl;
170+ } else if constexpr (std::is_same_v<T, double >) {
171+ real_ = std::fma (a, rat, b) * scl;
172+ imag_ = std::fma (b, rat, -a) * scl;
173+ } else {
174+ real_ = (a * rat + b) * scl;
175+ imag_ = (b * rat - a) * scl;
176+ }
177+ #else
159178 real_ = (a * rat + b) * scl;
160179 imag_ = (b * rat - a) * scl;
180+ #endif
161181 }
182+
162183 return ComplexType<T>(real_, imag_);
163184 }
164185};
@@ -184,23 +205,44 @@ struct InverseDivideFunctor<ComplexType<T>> {
184205#endif
185206
186207 T real_, imag_;
208+
209+ auto rat = (abs_c >= abs_d) ? (d / c) : (c / d);
210+ auto scl =
211+ (abs_c >= abs_d) ? (T (1.0 ) / (c + d * rat)) : (T (1.0 ) / (d + c * rat));
187212 if (abs_c >= abs_d) {
188- if (abs_c == T (0 ) && abs_d == T (0 )) {
189- /* divide by zeros should yield a complex inf or nan */
190- real_ = a / abs_c;
191- imag_ = b / abs_d;
213+ #if __cplusplus >= 201703L
214+ if constexpr (std::is_same_v<T, float >) {
215+ real_ = std::fmaf (b, rat, a) * scl;
216+ imag_ = std::fmaf (-a, rat, b) * scl;
217+ } else if constexpr (std::is_same_v<T, double >) {
218+ real_ = std::fma (b, rat, a) * scl;
219+ imag_ = std::fma (-a, rat, b) * scl;
192220 } else {
193- auto rat = d / c;
194- auto scl = T (1.0 ) / (c + d * rat);
195221 real_ = (a + b * rat) * scl;
196222 imag_ = (b - a * rat) * scl;
197223 }
224+ #else
225+ real_ = (a + b * rat) * scl;
226+ imag_ = (b - a * rat) * scl;
227+ #endif
198228 } else {
199- auto rat = c / d;
200- auto scl = T (1.0 ) / (d + c * rat);
229+ #if __cplusplus >= 201703L
230+ if constexpr (std::is_same_v<T, float >) {
231+ real_ = std::fmaf (a, rat, b) * scl;
232+ imag_ = std::fmaf (b, rat, -a) * scl;
233+ } else if constexpr (std::is_same_v<T, double >) {
234+ real_ = std::fma (a, rat, b) * scl;
235+ imag_ = std::fma (b, rat, -a) * scl;
236+ } else {
237+ real_ = (a * rat + b) * scl;
238+ imag_ = (b * rat - a) * scl;
239+ }
240+ #else
201241 real_ = (a * rat + b) * scl;
202242 imag_ = (b * rat - a) * scl;
243+ #endif
203244 }
245+
204246 return ComplexType<T>(real_, imag_);
205247 }
206248};
@@ -776,22 +818,41 @@ struct RemainderFunctor<ComplexType<T>> {
776818#endif
777819
778820 T real_, imag_;
821+ auto rat = (abs_c >= abs_d) ? (d__ / c__) : (c__ / d__);
822+ auto scl = (abs_c >= abs_d) ? (T (1.0 ) / (c__ + d__ * rat))
823+ : (T (1.0 ) / (d__ + c__ * rat));
779824 if (abs_c >= abs_d) {
780- if (abs_c == T (0 ) && abs_d == T (0 )) {
781- /* divide by zeros should yield a complex inf or nan */
782- real_ = a__ / abs_c;
783- imag_ = b__ / abs_d;
825+ #if __cplusplus >= 201703L
826+ if constexpr (std::is_same_v<T, float >) {
827+ real_ = std::fmaf (b__, rat, a__) * scl;
828+ imag_ = std::fmaf (-a__, rat, b__) * scl;
829+ } else if constexpr (std::is_same_v<T, double >) {
830+ real_ = std::fma (b__, rat, a__) * scl;
831+ imag_ = std::fma (-a__, rat, b__) * scl;
784832 } else {
785- auto rat = d__ / c__;
786- auto scl = T (1.0 ) / (c__ + d__ * rat);
787833 real_ = (a__ + b__ * rat) * scl;
788834 imag_ = (b__ - a__ * rat) * scl;
789835 }
836+ #else
837+ real_ = (a__ + b__ * rat) * scl;
838+ imag_ = (b__ - a__ * rat) * scl;
839+ #endif
790840 } else {
791- auto rat = c__ / d__;
792- auto scl = T (1.0 ) / (d__ + c__ * rat);
841+ #if __cplusplus >= 201703L
842+ if constexpr (std::is_same_v<T, float >) {
843+ real_ = std::fmaf (a__, rat, b__) * scl;
844+ imag_ = std::fmaf (b__, rat, -a__) * scl;
845+ } else if constexpr (std::is_same_v<T, double >) {
846+ real_ = std::fma (a__, rat, b__) * scl;
847+ imag_ = std::fma (b__, rat, -a__) * scl;
848+ } else {
849+ real_ = (a__ * rat + b__) * scl;
850+ imag_ = (b__ * rat - a__) * scl;
851+ }
852+ #else
793853 real_ = (a__ * rat + b__) * scl;
794854 imag_ = (b__ * rat - a__) * scl;
855+ #endif
795856 }
796857 auto q = ComplexType<T>(real_, imag_);
797858
@@ -970,22 +1031,41 @@ struct InverseRemainderFunctor<
9701031#endif
9711032
9721033 T real_, imag_;
1034+ auto rat = (abs_c >= abs_d) ? (d__ / c__) : (c__ / d__);
1035+ auto scl = (abs_c >= abs_d) ? (T (1.0 ) / (c__ + d__ * rat))
1036+ : (T (1.0 ) / (d__ + c__ * rat));
9731037 if (abs_c >= abs_d) {
974- if (abs_c == T (0 ) && abs_d == T (0 )) {
975- /* divide by zeros should yield a complex inf or nan */
976- real_ = a__ / abs_c;
977- imag_ = b__ / abs_d;
1038+ #if __cplusplus >= 201703L
1039+ if constexpr (std::is_same_v<T, float >) {
1040+ real_ = std::fmaf (b__, rat, a__) * scl;
1041+ imag_ = std::fmaf (-a__, rat, b__) * scl;
1042+ } else if constexpr (std::is_same_v<T, double >) {
1043+ real_ = std::fma (b__, rat, a__) * scl;
1044+ imag_ = std::fma (-a__, rat, b__) * scl;
9781045 } else {
979- auto rat = d__ / c__;
980- auto scl = T (1.0 ) / (c__ + d__ * rat);
9811046 real_ = (a__ + b__ * rat) * scl;
9821047 imag_ = (b__ - a__ * rat) * scl;
9831048 }
1049+ #else
1050+ real_ = (a__ + b__ * rat) * scl;
1051+ imag_ = (b__ - a__ * rat) * scl;
1052+ #endif
9841053 } else {
985- auto rat = c__ / d__;
986- auto scl = T (1.0 ) / (d__ + c__ * rat);
1054+ #if __cplusplus >= 201703L
1055+ if constexpr (std::is_same_v<T, float >) {
1056+ real_ = std::fmaf (a__, rat, b__) * scl;
1057+ imag_ = std::fmaf (b__, rat, -a__) * scl;
1058+ } else if constexpr (std::is_same_v<T, double >) {
1059+ real_ = std::fma (a__, rat, b__) * scl;
1060+ imag_ = std::fma (b__, rat, -a__) * scl;
1061+ } else {
1062+ real_ = (a__ * rat + b__) * scl;
1063+ imag_ = (b__ * rat - a__) * scl;
1064+ }
1065+ #else
9871066 real_ = (a__ * rat + b__) * scl;
9881067 imag_ = (b__ * rat - a__) * scl;
1068+ #endif
9891069 }
9901070 auto q = ComplexType<T>(real_, imag_);
9911071
0 commit comments