@@ -148,16 +148,26 @@ template <typename argT, typename resT> struct SqrtFunctor
148
148
constexpr realT half = realT (0x1 .0p-1f ); // 1/2
149
149
constexpr realT zero = realT (0 );
150
150
151
- if (std::signbit (x)) {
152
- realT m = std::hypot (x, y);
153
- realT d = std::sqrt ((m - x) * half);
154
- return {(d == zero ? zero : std::abs (y) / d * half),
155
- std::copysign (d, y)};
151
+ const int exp_x = std::ilogb (x);
152
+ const int exp_y = std::ilogb (y);
153
+
154
+ int sc = std::max<int >(exp_x, exp_y) / 2 ;
155
+ const realT xx = std::ldexp (x, -sc * 2 );
156
+ const realT yy = std::ldexp (y, -sc * 2 );
157
+
158
+ if (std::signbit (xx)) {
159
+ const realT m = std::hypot (xx, yy);
160
+ const realT d = std::sqrt ((m - xx) * half);
161
+ const realT res_re = (d == zero ? zero : std::abs (yy) / d * half);
162
+ const realT res_im = std::copysign (d, yy);
163
+ return {std::ldexp (res_re, sc), std::ldexp (res_im, sc)};
156
164
}
157
165
else {
158
- realT m = std::hypot (x, y);
159
- realT d = std::sqrt ((m + x) * half);
160
- return {d, (d == zero) ? std::copysign (zero, y) : y * half / d};
166
+ const realT m = std::hypot (xx, yy);
167
+ const realT d = std::sqrt ((m + xx) * half);
168
+ const realT res_im =
169
+ (d == zero) ? std::copysign (zero, yy) : yy * half / d;
170
+ return {std::ldexp (d, sc), std::ldexp (res_im, sc)};
161
171
}
162
172
}
163
173
};
0 commit comments