[libcxx-commits] [PATCH] D79555: [libc++] [P0415] [C++20] - Constexpr for std::complex.

Marek Kurdej via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Sat Nov 7 12:53:37 PST 2020


curdeius updated this revision to Diff 303663.
curdeius added a comment.

Fix edge cases. Fix operator* and operator/.
Use "shortcuts" to avoid NaN in constexpr evaluation (disallowed).

One remaining problem.
2 tests:

- complex_divides_complex.pass.cpp
- complex_times_complex.pass.cpp

do not pass on clang unless additional parameter `--param=compile_flags='-fconstexpr-steps=4000000'` is given.
That's because they test all the edge cases and each pair thereof and clang has too low a limit for the maximum number of constexpr execution steps.
I thought about splitting these tests somehow but given their (combinatoric) nature, it's pretty awkward.

I don't know how I should pass this compile flag only for these tests and only for clang (I know of ADDITIONAL_COMPILE_FLAGS but I cannot exclude gcc with that).

TODO:

- Test (at least locally) a different floating-point type (e.g. float128) to catch missing constexpr markers in the default implementation (non-specialization).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D79555/new/

https://reviews.llvm.org/D79555

Files:
  libcxx/include/complex


Index: libcxx/include/complex
===================================================================
--- libcxx/include/complex
+++ libcxx/include/complex
@@ -881,6 +881,45 @@
             __d = scalbn(__d, -__ilogbw);
         }
     }
+    if (__libcpp_is_constant_evaluated()) {
+        bool __z_zero = __a == _Tp(0) && __b == _Tp(0);
+        bool __w_zero = __c == _Tp(0) && __d == _Tp(0);
+        bool __z_inf = __libcpp_isinf_or_builtin(__a) || __libcpp_isinf_or_builtin(__b);
+        bool __w_inf = __libcpp_isinf_or_builtin(__c) || __libcpp_isinf_or_builtin(__d);
+        bool __z_nan = !__z_inf && (
+            (__libcpp_isnan_or_builtin(__a) && __libcpp_isnan_or_builtin(__b))
+            || (__libcpp_isnan_or_builtin(__a) && __b == _Tp(0))
+            || (__a == _Tp(0) && __libcpp_isnan_or_builtin(__b))
+        );
+        bool __w_nan = !__w_inf && (
+            (__libcpp_isnan_or_builtin(__c) && __libcpp_isnan_or_builtin(__d))
+            || (__libcpp_isnan_or_builtin(__c) && __d == _Tp(0))
+            || (__c == _Tp(0) && __libcpp_isnan_or_builtin(__d))
+        );
+        if ((__z_nan || __w_nan) || (__z_inf && __w_inf)) {
+            return complex<_Tp>(_Tp(NAN), _Tp(0));
+        }
+        bool __z_nonzero_nan = !__z_inf && !__z_nan && (__libcpp_isnan_or_builtin(__a) || __libcpp_isnan_or_builtin(__b));
+        bool __w_nonzero_nan = !__w_inf && !__w_nan && (__libcpp_isnan_or_builtin(__c) || __libcpp_isnan_or_builtin(__d));
+        if (__z_nonzero_nan || __w_nonzero_nan) {
+            if (__w_zero) {
+                return complex<_Tp>(_Tp(INFINITY), _Tp(INFINITY));
+            }
+            return complex<_Tp>(_Tp(NAN), _Tp(0));
+        }
+        if (__w_inf) {
+            return complex<_Tp>(_Tp(0), _Tp(0));
+        }
+        if (__z_inf) {
+            return complex<_Tp>(_Tp(INFINITY), _Tp(INFINITY));
+        }
+        if (__w_zero) {
+            if (__z_zero) {
+                return complex<_Tp>(_Tp(NAN), _Tp(0));
+            }
+            return complex<_Tp>(_Tp(INFINITY), _Tp(INFINITY));
+        }
+    }
     _Tp __denom = __c * __c + __d * __d;
     _Tp __x{};
     _Tp __y{};


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D79555.303663.patch
Type: text/x-patch
Size: 2160 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20201107/794f3ebd/attachment.bin>


More information about the libcxx-commits mailing list